Commit bf959dc3 authored by vicotor's avatar vicotor

fix bug for deploy

parent 50f6d41d
node_modules
.idea
.env
# Hardhat files
......@@ -15,3 +16,4 @@ node_modules
# Hardhat Ignition default folder for deployments against a local node
ignition/deployments/chain-31337
.secret
ADDR_USDT_TOKEN=
ADDR_API_SERVER=0x9f8fb0488de145e7467fded872098e1115d6ea4c
ADDR_MINT_RECEIVER=0xf5F236e1249C427100E3aB989ebFE829f700E352
ADDR_BONUS_POOL=0xac8b968d7c45919eE468c0DF421A6EA1567A6cb4
ADDR_BONUS_BURNED=0x8452D87bb98db41C5c4A0E7D1992b4EA3c9959Cd
ADDR_BONUS_PLATFORM=0x19Bd3121fEC07F047ac991e7b35C265a2B1F51eE
ADDR_FEE_RECEIVER=0x19Bd3121fEC07F047ac991e7b35C265a2B1F51eE
\ No newline at end of file
ADDR_USDT_TOKEN=
ADDR_API_SERVER=0x9f8fb0488de145e7467fded872098e1115d6ea4c
ADDR_MINT_RECEIVER=0x565897f5A092d754f5Eff148baF0Adefe7e4074D
ADDR_BONUS_POOL=0x525Dca17813e4d9b0b6c77FFB4F8F88748066Fa0
ADDR_BONUS_BURNED=0x4BccBC797a7f4041A5E4609bB98406582615984e
ADDR_BONUS_PLATFORM=0x46604a83103c7963dd0CD6e35434EB6C025A6913
ADDR_FEE_RECEIVER=0x46604a83103c7963dd0CD6e35434EB6C025A6913
ADDR_USDT_TOKEN=
ADDR_API_SERVER=0x9f8fb0488de145e7467fded872098e1115d6ea4c
ADDR_MINT_RECEIVER=0xf5F236e1249C427100E3aB989ebFE829f700E352
ADDR_BONUS_POOL=0xac8b968d7c45919eE468c0DF421A6EA1567A6cb4
ADDR_BONUS_BURNED=0x8452D87bb98db41C5c4A0E7D1992b4EA3c9959Cd
ADDR_BONUS_PLATFORM=0x19Bd3121fEC07F047ac991e7b35C265a2B1F51eE
ADDR_FEE_RECEIVER=0x19Bd3121fEC07F047ac991e7b35C265a2B1F51eE
\ No newline at end of file
ADDR_USDT_TOKEN=0xc2132d05d31c914a87c6611c10748aeb04b58e8f
ADDR_API_SERVER=0x9f8fb0488de145e7467fded872098e1115d6ea4c
ADDR_MINT_RECEIVER=0x565897f5A092d754f5Eff148baF0Adefe7e4074D
ADDR_BONUS_POOL=0x525Dca17813e4d9b0b6c77FFB4F8F88748066Fa0
ADDR_BONUS_BURNED=0x4BccBC797a7f4041A5E4609bB98406582615984e
ADDR_BONUS_PLATFORM=0x46604a83103c7963dd0CD6e35434EB6C025A6913
ADDR_FEE_RECEIVER=0x46604a83103c7963dd0CD6e35434EB6C025A6913
// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
pragma solidity ^0.8.22;
contract Box {
uint256 private value;
......
// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
pragma solidity ^0.8.22;
contract BoxV2 {
uint256 private value;
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
interface IERC721Metadata {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
interface IERC721 is IERC165 {
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
}
interface IERC721Token is IERC721, IERC721Metadata {
}
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface IERC20Metadata {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
interface IERC20Token is IERC20, IERC20Metadata {
}
interface IERC20TokenMinable is IERC20Token {
function mint(address recipient, uint amount) external returns (bool);
}
interface IERC721TokenMinable is IERC721Token {
function mint(address to) external returns (uint256);
function mint(address to, bytes memory _data) external returns (uint256);
function mint(uint256 len, address to) external returns (uint256[] memory);
function mint(uint256 len, address to, bytes memory _data) external returns (uint256[] memory);
function mint(uint256 len, address to, bytes[] memory _data) external returns (uint256[] memory);
function mint(uint256 len, address[] memory to, bytes[] memory _data) external returns (uint256[] memory);
}
interface IERC721BeforeTransfer {
function beforeTransfer(address from, address to, uint256 tokenId) external returns (bool);
}
interface IERC721AfterTransfer {
function afterTransfer(address from, address to, uint256 tokenId) external returns (bool);
}
interface IRaceBonusDistribute {
function distribute(address _raceCourse, uint256[] memory _tokenIds, uint256 _money) external returns (uint256,address[] memory, uint256[] memory);
}
interface IRaceBonusPool {
function distribute(address _raceCourse, uint256[] memory _tokenIds, uint256 _money, uint256 count, address[] memory lstAddress, uint256[] memory lstAmount) external;
function claim(uint256 nft_id) external;
}
\ No newline at end of file
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface IArenaOpera {
function setHorseFactName(uint256 tokenId, string calldata name) external returns (bool);
function setCreateTime(uint256 tokenId, uint256 time) external returns (bool);
function setHorseFactTypes(uint256 tokenId, uint256 types) external returns (bool);
function setFactoryStatus(uint256 tokenId, uint256 status) external returns (bool);
function setRaceCount(uint256 tokenId, uint256 count) external returns (bool);
function uptTotalRaceCount(uint256 tokenId) external returns (bool);
function setLastRaceTime(uint256 tokenId, uint256 time) external returns (bool);
function setMortAmount(uint256 tokenId, uint256 amount) external returns (bool);
function getFactoryName(uint256 tokenId) external returns (string memory);
function getCreateTime(uint256 tokenId) external returns (uint256);
function getOwnerType(uint256 tokenId) external returns (uint256);
function getIsClose(uint256 tokenId) external returns (uint256);
function getRaceCount(uint256 tokenId) external returns (uint256);
function getLastRaceTime(uint256 tokenId) external returns (uint256);
function getTotalRaceCount(uint256 tokenId) external returns (uint256);
function getMortAmount(uint256 tokenId) external returns (uint256);
function setGameId(uint256 tokenId, uint256 gameId) external returns (bool);
function checkGameId(uint256 tokenId, uint256 gameId) external returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface ICoin {
function safeTransferFrom(uint256 coin, address from, address to, uint256 value) external;
function safeTransferFrom1(uint256 coin, address from, address to, uint256 value) external;
function safeTransfer(uint256 coin, address to, uint256 value) external;
function safeTransfer1(uint256 coin, address to, uint256 value) external;
function safeTransferWei(uint256 _coinName, address to, uint256 value) external;
function balanceOf(uint256 _coinName, address account) external returns (uint256);
function decimals(uint256 _coinName) external returns (uint);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface ICoin721 {
function safeTransferFrom(address token, address from, address to, uint256 tokenId) external;
function balanceOf(address token, address account) external returns (uint256);
function ownerOf(address token, uint256 tokenId) external returns (address);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface IConstant {
function getMortAmount() external view returns (uint256);
function getMortToken() external view returns (uint256);
function getMinMortTime() external view returns (uint256);
function getGameCountLimit() external view returns (uint256);
function getMaxSpacing() external view returns (uint256);
function getApplyGameToken() external view returns (uint256);
function getApplyGameAmount() external view returns (uint256);
function getMinRaceUptTime() external view returns (uint256);
function getAwardToken() external view returns (uint256);
function getAwardAmount() external view returns (uint256);
function getExtraAwardToken() external view returns (uint256);
function getExtraAwardAmount() external view returns (uint256);
function getMaxScore() external view returns (uint256);
function getUseEnergy() external view returns (uint256);
function getResting() external view returns (uint256);
function getOnSale() external view returns (uint256);
function getBreeding() external view returns (uint256);
function getSigning() external view returns (uint256);
function getInGame() external view returns (uint256);
function getOnHold() external view returns (uint256);
function getOnSell() external view returns (uint256);
function getEquipped() external view returns (uint256);
function getFeeRateOfHorse() external view returns (uint256);
function getMinDiscountOfHorse() external view returns (uint256);
function getMaxRewardOfHorse() external view returns (uint256);
function getMinSellUptTime() external view returns (uint256);
function getFeeRateOfEquip() external view returns (uint256);
function getMinDiscountOfEquip() external view returns (uint256);
function getMaxRewardOfEquip() external view returns (uint256);
function getMinSpacing() external view returns (uint256);
function getMinTraValue() external view returns (uint256);
function getMaxTraValue() external view returns (uint256);
function getTraAddValue() external view returns (uint256);
function getTraTime() external view returns (uint256);
function getUntTime() external view returns (uint256);
function getTraToken() external view returns (uint256);
function getTraTokenAmount() external view returns (uint256);
function getBreDiscount() external view returns (uint256);
function getBreCoefficient() external view returns (uint256);
function getMinMareBrSpaTime() external view returns (uint256);
function getMinStaBrSpaTime() external view returns (uint256);
function getMinMatureTime() external view returns (uint256);
function getMinStudUptTime() external view returns (uint256);
function getBreCoin1() external view returns (uint256);
function getBreCoin1Amount() external view returns (uint256);
function getBreCoin2() external view returns (uint256);
function getBreCoin2Amount() external view returns (uint256);
function getWeekRankCount() external view returns (uint256);
function getMonthRankCount() external view returns (uint256);
function getYearRankCount() external view returns (uint256);
function getDate() external returns (uint32, uint32, uint32);
function isOfficialContract(address addr) external view returns (bool);
function getAccount() external view returns (address);
function getApplyGameAmountByDistance(uint256 distance) external view returns (uint256);
function getAwardAmountByDistance(uint256 distance) external view returns (uint256);
function getMaxApplyCount() external view returns (uint256);
function getTrackNumber() external view returns (uint256);
function getInitColorsCount() external view returns (uint32);
function getInitColors(uint8 index) external view returns (string memory);
function getInitGrade() external view returns (uint256);
function getInitIntegral() external view returns (uint256);
function getMaxEnergy() external view returns (uint256);
function getModifyNameTimes() external view returns (uint256);
function getEnergyRecoverCD() external view returns (uint256);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface IERC721Attr {
function setValues(address addr, uint256 tokenId, string calldata field, bytes calldata value) external returns (bool);
function getValue(address addr, uint256 tokenId, string calldata field) external view returns (bytes memory result);
function setFiled(address addr, string[] calldata field, uint256[] calldata types, uint256[] calldata auth) external returns (bool);
function setUniques(address addr, string calldata field, bytes calldata value) external returns (bool);
function clearUniques(address addr, string memory field, bytes memory value) external returns (bool);
function delFiled(address addr, string calldata field) external returns (bool);
function delValues(address addr, uint256 tokenId, string calldata field) external returns (bool);
function getAuth(address addr, string calldata field) external view returns (uint256);
function getType(address addr, string calldata field) external view returns (uint256);
function getUniques(address addr, string calldata field, bytes calldata value) external view returns (bool);
function setArrayValue(uint256 tokenId, string calldata field, bytes calldata value) external returns (bool);
function checkArrayValue(uint256 tokenId, string calldata field, bytes calldata value) external view returns (bool);
function delArrayValue(uint256 tokenId, string calldata field) external returns (bool);
function removeArrayValue(uint256 tokenId, string calldata field, bytes calldata value) external returns (bool);
function getArrayValue(uint256 tokenId, string calldata field) external view returns (uint256[] memory);
function getArrayCount(uint256 tokenId, string calldata field) external view returns (uint256);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface IERC721BeforeTransfer {
function beforeTransfer(address from, address to, uint256 tokenId) external returns (bool);
}
interface IERC721AfterTransfer {
function afterTransfer(address from, address to, uint256 tokenId) external returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface IERC721Token {
/**
* @dev Returns the number of NFTs in `owner`'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the NFT specified by `tokenId`.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
* another (`to`).
*
*
*
* Requirements:
* - `from`, `to` cannot be zero.
* - `tokenId` must be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this
* NFT by either {approve} or {setApprovalForAll}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
* another (`to`).
*
* Requirements:
* - If the caller is not `from`, it must be approved to move this NFT by
* either {approve} or {setApprovalForAll}.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
function safeMint(address to) external returns (uint256);
function safeMint(address to, uint256 tokenId) external returns (uint256);
function exists(uint256 tokenId) external returns (bool);
function mint(address to) external returns (uint256);
function mint(address to, bytes memory _data) external returns (uint256);
function mint(uint256 len, address to) external returns (uint256[] memory);
function mint(uint256 len, address to, bytes memory _data) external returns (uint256[] memory);
function mint(uint256 len, address to, bytes[] memory _data) external returns (uint256[] memory);
function mint(uint256 len, address[] memory to, bytes[] memory _data) external returns (uint256[] memory);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface IHorseEquipOpera {
function setEquipStatus(uint256 tokenId, uint256 status) external returns (bool);
function setEquipStatusBatch(uint256[] calldata tokenIds, uint256 status) external returns (bool);
function setEquipTypes(uint256 tokenId, uint256 types) external returns (bool);
function setEquipStyle(uint256 tokenId, uint256 style) external returns (bool);
function setEquipPrice(uint256 tokenId, uint256 price) external returns (bool);
function setEquipOfHorseId(uint256 tokenId, uint256 horseId) external returns (bool);
function setEquipDis(uint256 tokenId, uint256 discount) external returns (bool);
function setEquipReward(uint256 tokenId, uint256 reward) external returns (bool);
function setEquipCoin(uint256 tokenId, uint256 coin) external returns (bool);
function setLastOperaTime1(uint256 tokenId, uint256 operaTime) external returns (bool);
function setLastOperaTime2(uint256 tokenId) external returns (bool);
function setEquipLastOwner(uint256 tokenId, address addr) external returns (bool);
function setEquipLastPrice(uint256 tokenId, uint256 price) external returns (bool);
function getLastOperaTime(uint256 tokenId) external returns (uint256);
function getHorseEquipLastOwner(uint256 tokenId) external returns (address);
function getHorseEquipStatus(uint256 tokenId) external returns (uint256);
function getHorseEquipCoin(uint256 tokenId) external returns (uint256);
function getHorseEquipPrice(uint256 tokenId) external returns (uint256);
function getHorseEquipDiscount(uint256 tokenId) external returns (uint256);
function getHorseEquipReward(uint256 tokenId) external returns (uint256);
function getHorseEquipTypes(uint256 tokenId) external returns (uint256);
function getHorseEquipStyle(uint256 tokenId) external returns (uint256);
function getHorseEquipLastPrice(uint256 tokenId) external returns (uint256);
function getEquipOfHorseId(uint256 tokenId) external returns (uint256);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface IHorseRaceOpera {
function setHorseStatus(uint256 tokenId, uint256 status) external returns (bool);
function setHorseStatusBatch(uint256[] calldata tokenId, uint256 status) external returns (bool);
function setHorseCount(uint256 tokenId, uint256 count) external returns (bool);
function setHorseName(uint256 tokenId, string calldata name) external returns (bool);
function setHorseNameUptCount(uint256 tokenId, uint256 count) external returns (bool);
function setHorseBirthDay(uint256 tokenId, uint256 birthDay) external returns (bool);
// horse mainGeneration
function setHorseMGene(uint256 tokenId, uint256 mainGeneration) external returns (bool);
function setHorseSGene(uint256 tokenId, uint256 slaveGeneration) external returns (bool);
// 迭代系数
function setHorseGeneSc(uint256 tokenId, uint256 generationScore) external returns (bool);
// 性别
function setHorseGender(uint256 tokenId, uint256 gender) external returns (bool);
// 皮肤颜色
function setHorseColor(uint256 tokenId, string calldata color) external returns (bool);
//基因综合评分
function setHorseGene(uint256 tokenId, string calldata gene) external returns (bool);
// 设置训练值
function setHorseTraValue(uint256 tokenId, uint256 trainingValue) external returns (bool);
// 设置训练时间
function setHorseTraTime(uint256 tokenId, uint256 trainingTime) external returns (bool);
// 设置能量
function setHorseEnergy(uint256 tokenId, uint256 energy) external returns (bool);
// 能量恢复时间
function setHorseEngTime(uint256 tokenId, uint256 energyUpdateTime) external returns (bool);
// 马匹评分
function setHorseGradeSc(uint256 tokenId, uint256 gradeScore) external returns (bool);
// 马匹积分
function setHorseIntegral(uint256 tokenId, uint256 integral) external returns (bool);
// 马匹积分正负值标记
function setHorseIntMark(uint256 tokenId, uint256 gradeScoreMark) external returns (bool);
//积分最后一次更新时间
function setHorseScUptTime(uint256 tokenId, uint256 raceScoreUpdateTime) external returns (bool);
function setHorseFatherId(uint256 tokenId, uint256 father) external returns (bool);
function setHorseMotherId(uint256 tokenId, uint256 mother) external returns (bool);
// 繁殖次数
function setHorseBreedCount(uint256 tokenId) external returns (bool);
// 繁殖时间
function setHorseBreedTime(uint256 tokenId, uint256 breedTime) external returns (bool);
function setHeadWearId(uint256 tokenId, uint256 headWearId) external returns (bool);
function setArmorId(uint256 tokenId, uint256 armorId) external returns (bool);
function setPonytailId(uint256 tokenId, uint256 ponytailId) external returns (bool);
function setHoofId(uint256 tokenId, uint256 hoofId) external returns (bool);
function setGrade(uint256 tokenId, uint256 grade) external returns (bool);
function setWinCount(uint256 tokenId, uint256 winCount) external returns (bool);
function setRacePrice(uint256 tokenId, uint256 price) external returns (bool);
function setRaceDis(uint256 tokenId, uint256 discount) external returns (bool);
function setRaceReward(uint256 tokenId, uint256 reward) external returns (bool);
function setRaceCoin(uint256 tokenId, uint256 coin) external returns (bool);
function setSellUpdateTime(uint256 tokenId) external returns (bool);
function setStudUpdateTime(uint256 tokenId) external returns (bool);
function setRaceLastOwner(uint256 tokenId, address addr) external returns (bool);
function setRaceLastPrice(uint256 tokenId, uint256 price) external returns (bool);
function setRaceId(uint256 tokenId, uint256 raceId) external returns (bool);
function setRaceType(uint256 tokenId, uint256 raceType) external returns (bool);
function setRacecourse(uint256 tokenId, uint256 racecourse) external returns (bool);
function setDistance(uint256 tokenId, uint256 distance) external returns (bool);
function setRaceUpdateTime(uint256 tokenId, uint256 raceUpdateTime) external returns (bool);
function getHorseName(uint256 tokenId) external returns (string memory);
function getNameUptCount(uint256 tokenId) external returns (uint256);
function getBirthDay(uint256 tokenId) external returns (uint256);
function getHorseMGene(uint256 tokenId) external returns (uint256);
function getHorseSGene(uint256 tokenId) external returns (uint256);
function getHorseGeneSC(uint256 tokenId) external returns (uint256);
function getHorseGender(uint256 tokenId) external returns (uint256);
function getHorseColor(uint256 tokenId) external returns (string memory);
function getHorseGene(uint256 tokenId) external returns (string memory);
function getTrainingTime(uint256 tokenId) external returns (uint256);
function getTrainingValue(uint256 tokenId) external returns (uint256);
function getEnergy(uint256 tokenId) external returns (uint256);
function getEnergyUpdateTime(uint256 tokenId) external returns (uint256);
function getGradeScore(uint256 tokenId) external returns (uint256);
function getGradeScoreMark(uint256 tokenId) external returns (uint256);
function getScoreUpdateTime(uint256 tokenId) external returns (uint256);
function getFather(uint256 tokenId) external view returns (uint256);
function getMother(uint256 tokenId) external view returns (uint256);
function getBreedCount(uint256 tokenId) external returns (uint256);
function getBreedTime(uint256 tokenId) external returns (uint256);
function getHeadWearId(uint256 tokenId) external returns (uint256);
function getArmorId(uint256 tokenId) external returns (uint256);
function getPonytailId(uint256 tokenId) external returns (uint256);
function getHoofId(uint256 tokenId) external returns (uint256);
function getGrade(uint256 tokenId) external returns (uint256);
function getRaceCount(uint256 tokenId) external returns (uint256);
function getWinCount(uint256 tokenId) external returns (uint256);
function getHorseRaceLastOwner(uint256 tokenId) external returns (address);
function getHorseRaceStatus(uint256 tokenId) external returns (uint256);
function getHorseRaceCoin(uint256 tokenId) external returns (uint256);
function getHorseRacePrice(uint256 tokenId) external returns (uint256);
function getHorseRaceDiscount(uint256 tokenId) external returns (uint256);
function getHorseRaceReward(uint256 tokenId) external returns (uint256);
function getHorseRaceLastPrice(uint256 tokenId) external returns (uint256);
function getSellUpdateTime(uint256 tokenId) external returns (uint256);
function getStudUpdateTime(uint256 tokenId) external returns (uint256);
function getRaceId(uint256 tokenId) external returns (uint256);
function getRaceType(uint256 tokenId) external returns (uint256);
function getRacecourse(uint256 tokenId) external returns (uint256);
function getDistance(uint256 tokenId) external returns (uint256);
function getRaceUpdateTime(uint256 tokenId) external returns (uint256);
function checkStatus(uint256[] calldata tokenIds, uint256 status) external returns (bool);
function checkGameInfo(uint256[] calldata tokenIds, uint256 types, uint256 raceId, uint256 racecourseId,
uint256 level, uint256 distance) external returns (bool);
function getUseTraTime(uint256 tokenId) external returns (uint256);
function setUseTraTime(uint256 tokenId, uint256 trainingTime) external returns (bool);
function setHorseGripGene(uint256 tokenId, string calldata gene) external returns (bool);
function setHorseAccGene(uint256 tokenId, string calldata gene) external returns (bool);
function setHorseEndGene(uint256 tokenId, string calldata gene) external returns (bool);
function setHorseSpdGene(uint256 tokenId, string calldata gene) external returns (bool);
function setHorseTurnGene(uint256 tokenId, string calldata gene) external returns (bool);
function setHorseContGene(uint256 tokenId, string calldata gene) external returns (bool);
function getHorseGripGene(uint256 tokenId) external returns (string memory);
function getHorseAccGene(uint256 tokenId) external returns (string memory);
function getHorseEndGene(uint256 tokenId) external returns (string memory);
function getHorseSpdGene(uint256 tokenId) external returns (string memory);
function getHorseTurnGene(uint256 tokenId) external returns (string memory);
function getHorseContGene(uint256 tokenId) external returns (string memory);
function getIntegral(uint256 tokenId) external returns (uint256);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
interface IRacecourseOpera {
function setCreateTime(uint256 tokenId, uint256 time) external returns (bool);
function setLever(uint256 tokenId, uint256 lever) external returns (bool);
function setRaceType(uint256 tokenId, uint256 raceType) external returns (bool);
function setDistance(uint256 tokenId, uint256 distance) external returns (bool);
function setStatus(uint256 tokenId, uint256 status) external returns (bool);
function getCreateTime(uint256 tokenId) external returns (uint256);
function getLever(uint256 tokenId) external returns (uint256);
function getRaceType(uint256 tokenId) external returns (uint256);
function getDistance(uint256 tokenId) external returns (uint256);
function getStatus(uint256 tokenId) external returns (uint256);
function delHorseId(uint256 tokenId) external returns (bool);
function delHorseIdBatch(uint256[] calldata tokenIds) external returns (bool);
function getHorseId(uint256 tokenId) external returns (uint256[] memory);
function checkHorseId(uint256 tokenId, uint256 horseId) external returns (bool);
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
pragma solidity ^0.8.22;
// Uncomment this line to use console.log
// import "hardhat/console.sol";
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract Admin is Initializable, OwnableUpgradeable {
mapping(address => bool) private _admins;
modifier onlyAdmin() {
require(_admins[msg.sender], "Only admin can call it");
_;
}
// constructor() {
// _disableInitializers();
// }
function admin_initialize() internal onlyInitializing {
__Ownable_init(msg.sender); // Initialize with the owner
_admins[msg.sender] = true; // Set the initial owner as admin
}
function addAdmin(address _admin) public onlyOwner {
_admins[_admin] = true;
}
function delAdmin(address _admin) public onlyOwner {
_admins[_admin] = false;
}
function isAdmin(address _addr) public view returns (bool) {
return _admins[_addr];
}
}
contract Program is Admin {
mapping(address => bool) private _programs;
modifier onlyProgram() {
require(_programs[msg.sender], "Only program can call it");
_;
}
function program_initialize() internal onlyInitializing {
admin_initialize();
}
function addProgram(address _program) public onlyOwner {
_programs[_program] = true;
}
function delProgram(address _program) public onlyOwner {
_programs[_program] = false;
}
function isProgram(address _program) public view returns (bool) {
return _programs[_program];
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/Address.sol";
import "./Auth.sol";
interface IERC20Token {
function decimals() external view returns (uint);
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(address sender, address recipient, uint amount) external returns (bool);
}
library SafeERC20Token {
using Address for address;
function safeTransfer(IERC20Token token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20Token token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function callOptionalReturn(IERC20Token token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
// require(address(token).isContract(), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {// Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
contract Coin is Program {
using SafeERC20Token for IERC20Token;
mapping(uint256 => uint256) public priceOf;
mapping(uint256 => address) public addressOf;
mapping(address => bool) private minters;
function initialize() public initializer {
program_initialize();
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyMiner() {
require(minters[msg.sender], "!miner");
_;
}
function addMinter(address _minter) public onlyOwner {
minters[_minter] = true;
}
function removeMinter(address _minter) public onlyOwner {
minters[_minter] = false;
}
/**
* @dev Add supported token symbols, addresses and prices
*/
function add(uint256[] memory _coins, address[] memory _address, uint256[] memory _price) public onlyAdmin returns (bool) {
require(_coins.length == _address.length && _coins.length == _price.length && _coins.length <= 256, "Invalid parameters");
for (uint256 i = 0; i < _coins.length; i++) {
uint256 coin = _coins[i];
addressOf[coin] = _address[i];
priceOf[coin] = _price[i];
}
return true;
}
/**
* @dev Del supported token symbols, addresses and prices
*/
function del(uint256[] memory _coins) public onlyAdmin returns (bool) {
require(_coins.length > 0 && _coins.length <= 256, "Invalid parameters");
for (uint256 i = 0; i < _coins.length; i++) {
uint256 coin = _coins[i];
delete priceOf[coin];
delete addressOf[coin];
}
return true;
}
/**
* @dev update token prices
*/
function setPrice(uint256[] memory _coins, uint256[] memory _price) public onlyProgram returns (bool) {
require(_coins.length == _price.length && _coins.length <= 256, "Invalid parameters");
for (uint256 i = 0; i < _coins.length; i++) {
uint256 coin = _coins[i];
if (_price[i] != 0 && priceOf[coin] != 0) {
priceOf[coin] = _price[i];
}
}
return true;
}
/**
* @dev Price conversion
*/
function convert(uint256 _coinName, uint256 _usdAmount) public view returns (uint256) {
uint256 _decimals = 10 ** IERC20Token(addressOf[_coinName]).decimals();
return _decimals * _usdAmount / priceOf[_coinName];
}
function convert1(uint256 _coinName, uint256 _usdAmount) public view returns (uint256) {
uint256 _decimals = 10 ** IERC20Token(addressOf[_coinName]).decimals();
return _decimals * _usdAmount;
}
/**
* @dev Safe transfer from 'from' account to 'to' account
*/
function safeTransferFrom(uint256 _coinName, address from, address to, uint256 value) public onlyMiner {
require(addressOf[_coinName] != address(0), "Not supported coin!");
IERC20Token(addressOf[_coinName]).safeTransferFrom(from, to, convert(_coinName, value));
}
function safeTransferFrom1(uint256 _coinName, address from, address to, uint256 value) public onlyMiner {
require(addressOf[_coinName] != address(0), "Not supported coin!");
IERC20Token(addressOf[_coinName]).safeTransferFrom(from, to, convert1(_coinName, value));
}
/**
* @dev Safe transfer from 'this' account to 'to' account
*/
function safeTransfer(uint256 _coinName, address to, uint256 value) public onlyMiner {
require(addressOf[_coinName] != address(0), "Not supported coin!");
IERC20Token(addressOf[_coinName]).safeTransfer(to, convert(_coinName, value));
}
function safeTransfer1(uint256 _coinName, address to, uint256 value) public onlyMiner {
require(addressOf[_coinName] != address(0), "Not supported coin!");
IERC20Token(addressOf[_coinName]).safeTransfer(to, convert1(_coinName, value));
}
function safeTransferWei(uint256 _coinName, address to, uint256 value) public onlyMiner {
require(addressOf[_coinName] != address(0), "Not supported coin!");
IERC20Token(addressOf[_coinName]).safeTransfer(to, value);
}
function balanceOf(uint256 _coinName, address account) public view returns (uint256){
require(addressOf[_coinName] != address(0), "Not supported coin!");
uint256 balance = IERC20Token(addressOf[_coinName]).balanceOf(account);
return balance;
}
function decimals(uint256 _coinName) public view returns (uint) {
require(addressOf[_coinName] != address(0), "Not supported coin!");
uint d = IERC20Token(addressOf[_coinName]).decimals();
return d;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/Address.sol";
import "./Auth.sol";
interface IERC721Token {
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}
contract Coin721 is Program {
mapping(address => address) public addressOf;
mapping(address => bool) private minters;
function initialize() public initializer {
program_initialize();
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyMiner() {
require(minters[msg.sender], "!miner");
_;
}
function addMinter(address _minter) public onlyOwner {
minters[_minter] = true;
}
function removeMinter(address _minter) public onlyOwner {
minters[_minter] = false;
}
/**
* @dev Add supported token addresses
*/
function add(address[] memory _address) public onlyAdmin returns (bool) {
require(_address.length <= 256, "Invalid parameters");
for (uint256 i = 0; i < _address.length; i++) {
addressOf[_address[i]] = _address[i];
}
return true;
}
/**
* @dev Del supported addresses
*/
function del(address[] memory _coins) public onlyAdmin returns (bool) {
require(_coins.length > 0 && _coins.length <= 256, "Invalid parameters");
for (uint256 i = 0; i < _coins.length; i++) {
delete addressOf[_coins[i]];
}
return true;
}
/**
* @dev Safe transfer from 'from' account to 'to' account
*/
function safeTransferFrom(address token, address from, address to, uint256 tokenId) public onlyMiner {
require(addressOf[token] != address(0), "Not supported coin!");
IERC721Token(addressOf[token]).safeTransferFrom(from, to, tokenId);
}
function balanceOf(address token, address account) public view returns (uint256){
require(addressOf[token] != address(0), "Not supported coin!");
uint256 balance = IERC721Token(addressOf[token]).balanceOf(account);
return balance;
}
function ownerOf(address token, uint256 tokenId) public view returns (address) {
require(addressOf[token] != address(0), "Not supported coin!");
address owner = IERC721Token(addressOf[token]).ownerOf(tokenId);
return owner;
}
function onERC721Received(address, address, uint256, bytes calldata) external pure returns(bytes4) {
return bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./Auth.sol";
contract Constant is Program {
// 马匹状态.0 休息、1出售中(在拍卖行)、2在繁殖场、3报名参赛、4比赛中
uint256 constant _resting = 0;
uint256 constant _onSale = 1;
uint256 constant _breeding = 2;
uint256 constant _signing = 3;
uint256 constant _inGame = 4;
// 装饰状态.0 持有、1出售中(在拍卖行)、2装备中
uint256 constant _onHold = 0;
uint256 constant _onSell = 1;
uint256 constant _equipped = 2;
// 抵押开设赛场相关
uint256 public _mortAmount;// 抵押开设马场资产的数量,待定
uint256 public _mortToken;// 抵押资产的token, meta
uint256 public _minMortTime;// 抵押时间
uint256 public _gameCountLimit;// 每天可创建比赛场次
uint256 public _maxSpacing;// 创建场次达到最大后的冷却时间
uint256 public _distApplyFee;// 报名费分配比例,10%,分配给赛场.
//锦标赛相关
uint256 public _applyGameToken;// 报名锦标赛的token, meta
mapping (uint256=>uint256) public _applyGameAmount; // 报名比赛的费用, 不同的distance 费用不同.
mapping (uint256=>uint256) public _awardGameAmount; // 报名比赛的费用, 不同的distance 费用不同.
uint256 public _minRaceUptTime;// 取消报名多久可以再次报名,10秒
uint256 public _awardToken;// 参赛马匹获得奖励的token,race, race 由增发产出.
uint256 public _awardAmount;// 参赛马匹获得奖励, 数量待定
uint256 public _extraAwardToken;// 参赛马匹前三名获得额外奖励token, meta, meta不增发,从报名费中给出.
uint256 public _extraAwardAmount;// 参赛马匹前三名获得额外奖励最高40,依次减半,数量待定.
uint256 public _maxScore;//锦标赛奖励最高评分
uint256 public _useEnergy;// 每1200米消耗10能量
uint256 public _energyRecoverCD;// 每恢复一点能量需要多久, 12分钟,1天恢复满
//马匹交易相关
uint256 public _feeRateOfHorse;// 购买时所需的手续费
uint256 public _minDiscountOfHorse; // 购买马匹的折扣
uint256 public _maxRewardOfHorse; // 暂时没用到
uint256 public _minSellUptTime;//出售、取消出售最小空闲时间
//装饰交易相关
uint256 public _feeRateOfEquip;// 购买时所需的手续费
uint256 public _minDiscountOfEquip; // 购买装饰的折扣
uint256 public _maxRewardOfEquip; // 暂时没用到
uint256 public _minSpacing;//装备出售CD时间
// 马匹训练相关
uint256 public _minTraValue;// 训练值最小值
uint256 public _maxTraValue;// 训练值最大值
uint256 public _traAddValue;// 每次训练增加训练值
uint256 public _traTime;// 训练时间间隔,每24小时训练一次, CD
uint256 public _untTime;// 多久未训练,训练值减少1。
uint256 public _traToken;// 训练所需token, race.
uint256 public _traTokenAmount;// 训练所需token数量,暂定
// 繁殖相关
uint256 public _breDiscount;//繁殖时系统扣费,给平台15%
uint256 public _breCoefficient;//繁殖系数
uint256 public _minMareBrSpaTime;// 母马繁殖CD
uint256 public _minStaBrSpaTime;// 种马繁殖CD
uint256 public _minMatureTime;// 马匹成长时间
uint256 public _minStudUptTime;//繁殖、取消繁殖最小空闲时间,CD
// 繁殖增发小马所需两种费用
uint256 public _breCoin1; // meta
uint256 public _breCoin1Amount; // 待定
uint256 public _breCoin2; // race
uint256 public _breCoin2Amount; // 待定
//马匹获得后改名机会次数
uint256 public _modifyNameTimes; // 购买马匹之后的改名次数.
uint256 public _maxEnergy;// 能量最大值
uint256 public _initScore;// 马匹初始评分, 评分不能为0
uint256 public _initGrade;// 马匹初始等级
uint256 public _maxApplyCount;// 一个赛场一天可报名的最大数
uint256 public _trackNumber;// 一场比赛的赛道数
uint256 public _weekRankCount; // 周排名数量,待定
uint256 public _monthRankCount; // 月奖励数量,待定
uint256 public _yearRankCount; // 年奖励数量,待定
// golbal param
uint32 public _dateYear; // current date Year
uint32 public _dateMonth; // current date Month
uint32 public _dateWeek; // current date Week
bytes[50] public _initHorseColors; // init horse colors
address[100] public _officialContracts; // all official extra contract's addresses
// 签名SDK账户
address _account;
function initialize() public initializer {
program_initialize();
// 抵押开设赛场相关
_mortAmount = 200000;// 抵押开设马场资产的数量,待定
_mortToken = 1;// 抵押资产的token, meta
_minMortTime = 10 days;// 抵押时间
_gameCountLimit = 30;// 每天可创建比赛场次
_maxSpacing = 1 days;// 创建场次达到最大后的冷却时间
_distApplyFee = 1000;// 报名费分配比例,10%,分配给赛场.
//锦标赛相关
_applyGameToken = 1;// 报名锦标赛的token, meta
_minRaceUptTime = 10;// 取消报名多久可以再次报名,10秒
_awardToken = 2;// 参赛马匹获得奖励的token,race, race 由增发产出.
_awardAmount = 20;// 参赛马匹获得奖励, 数量待定
_extraAwardToken = 1;// 参赛马匹前三名获得额外奖励token, meta, meta不增发,从报名费中给出.
_extraAwardAmount = 40;// 参赛马匹前三名获得额外奖励最高40,依次减半,数量待定.
_maxScore = 10;//锦标赛奖励最高评分
_useEnergy = 10;// 每1200米消耗10能量
_energyRecoverCD = 12*60;// 每恢复一点能量需要多久, 12分钟,1天恢复满
//马匹交易相关
_feeRateOfHorse = 1500;// 购买时所需的手续费
_minDiscountOfHorse = 10000; // 购买马匹的折扣
_maxRewardOfHorse = 0; // 暂时没用到
_minSellUptTime = 20;//出售、取消出售最小空闲时间
//装饰交易相关
_feeRateOfEquip = 1500;// 购买时所需的手续费
_minDiscountOfEquip = 10000; // 购买装饰的折扣
_maxRewardOfEquip = 0; // 暂时没用到
_minSpacing = 10;//装备出售CD时间
// 马匹训练相关
_minTraValue = 100;// 训练值最小值
_maxTraValue = 120;// 训练值最大值
_traAddValue = 1;// 每次训练增加训练值
_traTime = 1 days;// 训练时间间隔,每24小时训练一次, CD
_untTime = 2 days;// 多久未训练,训练值减少1。
_traToken = 2;// 训练所需token, race.
_traTokenAmount = 10;// 训练所需token数量,暂定
// 繁殖相关
_breDiscount = 8500;//繁殖时系统扣费,给平台15%
_breCoefficient = 9500;//繁殖系数
_minMareBrSpaTime = 30 days;// 母马繁殖CD
_minStaBrSpaTime = 10 days;// 种马繁殖CD
_minMatureTime = 28 days;// 马匹成长时间
_minStudUptTime = 20;//繁殖、取消繁殖最小空闲时间,CD
// 繁殖增发小马所需两种费用
_breCoin1 = 1; // meta
_breCoin1Amount = 100; // 待定
_breCoin2 = 2; // race
_breCoin2Amount = 500; // 待定
//马匹获得后改名机会次数
_modifyNameTimes = 1; // 购买马匹之后的改名次数.
_maxEnergy = 100;// 能量最大值
_initScore = 0;// 马匹初始评分, 评分不能为0
_initGrade = 999;// 马匹初始等级
_maxApplyCount = 36000;// 一个赛场一天可报名的最大数
_trackNumber = 12;// 一场比赛的赛道数
_weekRankCount = 100; // 周排名数量,待定
_monthRankCount = 300; // 月奖励数量,待定
_yearRankCount = 1000; // 年奖励数量,待定
// golbal param
_dateYear = 0; // current date Year
_dateMonth = 0; // current date Month
_dateWeek = 0; // current date Week
// 签名SDK账户
_account = 0x9f8fb0488dE145E7467FDeD872098e1115d6ea4C;
}
function getConstant() public view returns (
uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256){
return (_feeRateOfHorse, _modifyNameTimes, _minSellUptTime, _minSellUptTime, _minMatureTime,
_minStudUptTime, _minStudUptTime, _minMareBrSpaTime, _minStaBrSpaTime, _breCoin1, _breCoin1Amount,
_breCoin2, _breCoin2Amount);
}
function getConstant2() public view returns (
uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256){
return (_minTraValue, _maxTraValue, _traAddValue, _traTime,
_untTime, _traAddValue, _traToken, _traTokenAmount, _gameCountLimit, _minRaceUptTime, _minRaceUptTime,
_applyGameToken, _applyGameAmount[0]);
}
function getConstant3() public view returns (uint256, uint256, uint256, uint256, uint256){
return (_breDiscount, 0, _useEnergy, _energyRecoverCD, _minMortTime);
}
function getConstant4() public view returns (uint256, uint256, uint256, uint256, uint256,
uint256, uint256, uint256, uint256, uint256,
uint256, uint256) {
return (_weekRankCount, _monthRankCount, _yearRankCount, _maxEnergy, _initScore,
_initGrade, _maxApplyCount, _trackNumber, _breCoefficient, _minDiscountOfHorse,
_maxRewardOfHorse, _mortAmount);
}
function getConstant5() public view returns (uint256, uint256, uint256, uint256, uint256,
uint256, uint256, uint256, uint256, uint256,
uint256, uint256) {
return (_mortToken, _maxSpacing, _distApplyFee, _awardToken, _awardAmount,
_extraAwardToken, _extraAwardAmount, _maxScore, _feeRateOfEquip, _minDiscountOfEquip,
_maxRewardOfEquip,_minSpacing);
}
function getConstant6() public pure returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256) {
return (_resting, _onSale, _breeding, _signing, _inGame, _onHold, _onSell, _equipped);
}
// 开设马场抵押资产
function setMortConst(uint256 mortToken, uint256 mortAmount, uint256 minMortTime, uint256 gameCountLimit,
uint256 maxSpacing, uint256 distApplyFee) public onlyAdmin returns (bool){
_mortAmount = mortAmount;
_mortToken = mortToken;
_minMortTime = minMortTime;
_gameCountLimit = gameCountLimit;
_maxSpacing = maxSpacing;
_distApplyFee = distApplyFee;
return true;
}
// 参加锦标赛相关
function setGameConst(
uint256 applyGameToken,
uint256 applyGameAmount,
uint256 minRaceUptTime,
uint256 awardToken,
uint256 awardAmount,
uint256 extraAwardToken,
uint256 extraAwardAmount,
uint256 maxScore,
uint256 useEnergy
) public onlyAdmin returns (bool){
_applyGameToken = applyGameToken;
_applyGameAmount[0] = applyGameAmount;
_minRaceUptTime = minRaceUptTime;
_awardToken = awardToken;
_awardAmount = awardAmount;
_extraAwardToken = extraAwardToken;
_extraAwardAmount = extraAwardAmount;
_maxScore = maxScore;
_useEnergy = useEnergy;
return true;
}
//马匹交易相关
function setHorseTxConst(uint256 feeRateOfHorse, uint256 minDiscountOfHorse, uint256 maxRewardOfHorse, uint256 minSellUptTime) public onlyAdmin returns (bool){
_feeRateOfHorse = feeRateOfHorse;
_minDiscountOfHorse = minDiscountOfHorse;
_maxRewardOfHorse = maxRewardOfHorse;
_minSellUptTime = minSellUptTime;
return true;
}
//装饰交易相关
function setEquipTxConst(uint256 feeRateOfEquip, uint256 minDiscountOfEquip, uint256 maxRewardOfEquip, uint256 minSpacing) public onlyAdmin returns (bool){
_feeRateOfEquip = feeRateOfEquip;
_minDiscountOfEquip = minDiscountOfEquip;
_maxRewardOfEquip = maxRewardOfEquip;
_minSpacing = minSpacing;
return true;
}
// 马匹训练相关
function setTraConst(
uint256 minTraValue,
uint256 maxTraValue,
uint256 traAddValue,
uint256 traTime,
uint256 untTime,
uint256 traToken,
uint256 traTokenAmount
) public onlyAdmin returns (bool){
_minTraValue = minTraValue;
_maxTraValue = maxTraValue;
_traAddValue = traAddValue;
_traTime = traTime;
_untTime = untTime;
_traToken = traToken;
_traTokenAmount = traTokenAmount;
return true;
}
// 马匹繁殖相关
function setBreConst(
uint256 breDiscount,
uint256 breCoefficient,
uint256 minMareBrSpaTime,
uint256 minStaBrSpaTime,
uint256 minMatureTime,
uint256 minStudUptTime
) public onlyAdmin returns (bool){
_breDiscount = breDiscount;
_breCoefficient = breCoefficient;
_minMareBrSpaTime = minMareBrSpaTime;
_minStaBrSpaTime = minStaBrSpaTime;
_minMatureTime = minMatureTime;
_minStudUptTime = minStudUptTime;
return true;
}
// 繁殖增发小马所需两种费用
function setBreCostConst(uint256 breCoin1, uint256 breCoin1Amount, uint256 breCoin2, uint256 breCoin2Amount) public onlyAdmin returns (bool){
_breCoin1 = breCoin1;
_breCoin1Amount = breCoin1Amount;
_breCoin2 = breCoin2;
_breCoin2Amount = breCoin2Amount;
return true;
}
// 繁殖增发小马所需两种费用
function setModifyNameTimes(uint256 modifyNameTimes) public onlyAdmin returns (bool){
_modifyNameTimes = modifyNameTimes;
return true;
}
// 马匹能量最大值
function setMaxEnergy(uint256 maxEnergy) public onlyAdmin returns (bool){
_maxEnergy = maxEnergy;
return true;
}
// 马匹初始评分
function setInitScore(uint256 initScore) public onlyAdmin returns (bool){
_initScore = initScore;
return true;
}
// 马匹初始等级
function setInitGrade(uint256 initGrade) public onlyAdmin returns (bool){
_initGrade = initGrade;
return true;
}
// 赛场每天最大可报名次数
function setMaxApplyCount(uint256 maxApplyCount) public onlyAdmin returns (bool){
_maxApplyCount = maxApplyCount;
return true;
}
function setTrackNumber(uint256 trackNumber) public onlyAdmin returns (bool){
_trackNumber = trackNumber;
return true;
}
// 报名费个人赛场获得比例
function setEnergyRecoverCD(uint256 energyRecoverCD) public onlyAdmin returns (bool){
_energyRecoverCD = energyRecoverCD;
return true;
}
function setAccount(address account) public onlyAdmin returns (bool){
_account = account;
return true;
}
function setWeekRankCount(uint256 weekRankCount) public onlyAdmin returns (bool) {
_weekRankCount = weekRankCount;
return true;
}
function setMonthRankCount(uint256 monthRankCount) public onlyAdmin returns (bool) {
_monthRankCount = monthRankCount;
return true;
}
function setYearRankCount(uint256 yearRankCount) public onlyAdmin returns (bool) {
_yearRankCount = yearRankCount;
return true;
}
function setDate(uint32 year, uint32 month, uint32 week) public onlyAdmin {
_dateYear = year;
_dateMonth = month;
_dateWeek = week;
}
function setApplyGameAmount(uint256 distance, uint256 amount) public onlyAdmin {
_applyGameAmount[distance] = amount;
}
function setAwardGameAmount(uint256 distance, uint256 amount) public onlyAdmin {
_awardGameAmount[distance] = amount;
}
function rmColor(bytes memory color) public onlyAdmin {
for (uint i = 0; i < _initHorseColors.length; i++) {
if (_initHorseColors[i].length == 0) {
continue;
}
if (keccak256(color) == keccak256(_initHorseColors[i])) {
_initHorseColors[i] = new bytes(0);
break;
}
}
}
function addColor(string memory color) public onlyAdmin {
for (uint i = 0; i < _initHorseColors.length; i++) {
if (_initHorseColors[i].length == 0) {
_initHorseColors[i] = bytes(color);
break;
}
}
}
function addOfficialContract(address addr) public onlyAdmin {
for (uint i = 0; i < _officialContracts.length; i++) {
if (_officialContracts[i] == address(0)) {
_officialContracts[i] = addr;
break;
}
}
}
function delOfficialContract(address addr) public onlyAdmin {
for (uint i = 0; i < _officialContracts.length; i++) {
if (_officialContracts[i] == address(0)) {
continue;
}
if (_officialContracts[i] == addr) {
_officialContracts[i] = address(0);
break;
}
}
}
function getAccount() public view returns (address){
return _account;
}
function getEnergyRecoverCD() public view returns (uint256){
return _energyRecoverCD;
}
function getModifyNameTimes() public view returns (uint256){
return _modifyNameTimes;
}
function getMaxEnergy() public view returns (uint256){
return _maxEnergy;
}
function getInitIntegral() public view returns (uint256){
return _initScore;
}
function getInitGrade() public view returns (uint256){
return _initGrade;
}
function getMaxApplyCount() public view returns (uint256){
return _maxApplyCount;
}
function getTrackNumber() public view returns (uint256){
return _trackNumber;
}
function getMortAmount() public view returns (uint256){
return _mortAmount;
}
function getMortToken() public view returns (uint256){
return _mortToken;
}
function getMinMortTime() public view returns (uint256){
return _minMortTime;
}
function getGameCountLimit() public view returns (uint256){
return _gameCountLimit;
}
function getMaxSpacing() public view returns (uint256){
return _maxSpacing;
}
function getDistApplyFee() public view returns (uint256){
return _distApplyFee;
}
function getApplyGameToken() public view returns (uint256){
return _applyGameToken;
}
function getApplyGameAmount() public view returns (uint256){
return _applyGameAmount[0];
}
function getApplyGameAmountByDistance(uint256 distance) public view returns (uint256) {
return _applyGameAmount[distance];
}
function getAwardAmountByDistance(uint256 distance) public view returns (uint256) {
return _awardGameAmount[distance];
}
function getMinRaceUptTime() public view returns (uint256){
return _minRaceUptTime;
}
function getAwardToken() public view returns (uint256){
return _awardToken;
}
function getAwardAmount() public view returns (uint256){
return _awardAmount;
}
function getExtraAwardToken() public view returns (uint256){
return _extraAwardToken;
}
function getExtraAwardAmount() public view returns (uint256){
return _extraAwardAmount;
}
function getMaxScore() public view returns (uint256){
return _maxScore;
}
function getUseEnergy() public view returns (uint256){
return _useEnergy;
}
function getResting() public pure returns (uint256){
return _resting;
}
function getOnSale() public pure returns (uint256){
return _onSale;
}
function getBreeding() public pure returns (uint256){
return _breeding;
}
function getSigning() public pure returns (uint256){
return _signing;
}
function getInGame() public pure returns (uint256){
return _inGame;
}
function getOnHold() public pure returns (uint256){
return _onHold;
}
function getOnSell() public pure returns (uint256){
return _onSell;
}
function getEquipped() public pure returns (uint256){
return _equipped;
}
function getFeeRateOfHorse() public view returns (uint256){
return _feeRateOfHorse;
}
function getMinDiscountOfHorse() public view returns (uint256){
return _minDiscountOfHorse;
}
function getMaxRewardOfHorse() public view returns (uint256){
return _maxRewardOfHorse;
}
function getMinSellUptTime() public view returns (uint256){
return _minSellUptTime;
}
function getFeeRateOfEquip() public view returns (uint256){
return _feeRateOfEquip;
}
function getMinDiscountOfEquip() public view returns (uint256){
return _minDiscountOfEquip;
}
function getMaxRewardOfEquip() public view returns (uint256){
return _maxRewardOfEquip;
}
function getMinSpacing() public view returns (uint256){
return _minSpacing;
}
function getMinTraValue() public view returns (uint256){
return _minTraValue;
}
function getMaxTraValue() public view returns (uint256){
return _maxTraValue;
}
function getTraAddValue() public view returns (uint256){
return _traAddValue;
}
function getTraTime() public view returns (uint256){
return _traTime;
}
function getUntTime() public view returns (uint256){
return _untTime;
}
function getTraToken() public view returns (uint256){
return _traToken;
}
function getTraTokenAmount() public view returns (uint256){
return _traTokenAmount;
}
function getBreDiscount() public view returns (uint256){
return _breDiscount;
}
function getBreCoefficient() public view returns (uint256){
return _breCoefficient;
}
function getMinMareBrSpaTime() public view returns (uint256){
return _minMareBrSpaTime;
}
function getMinStaBrSpaTime() public view returns (uint256){
return _minStaBrSpaTime;
}
function getMinMatureTime() public view returns (uint256){
return _minMatureTime;
}
function getMinStudUptTime() public view returns (uint256){
return _minStudUptTime;
}
function getBreCoin1() public view returns (uint256){
return _breCoin1;
}
function getBreCoin1Amount() public view returns (uint256){
return _breCoin1Amount;
}
function getBreCoin2() public view returns (uint256){
return _breCoin2;
}
function getBreCoin2Amount() public view returns (uint256){
return _breCoin2Amount;
}
function getWeekRankCount() public view returns (uint256) {
return _weekRankCount;
}
function getMonthRankCount() public view returns (uint256) {
return _monthRankCount;
}
function getYearRankCount() public view returns (uint256) {
return _yearRankCount;
}
function getDate() public view returns (uint32, uint32, uint32) {
return (_dateYear, _dateMonth, _dateWeek);
}
function getInitColorsCount() public view returns (uint32) {
uint32 count = 0;
for (uint i = 0; i < _initHorseColors.length; i++) {
if (_initHorseColors[i].length > 0) {
count++;
}
}
return count;
}
function getInitColors(uint8 index) public view returns (string memory) {
require(index < _initHorseColors.length, "over flow horseColors index");
return string(_initHorseColors[index]);
}
function isOfficialContract(address addr) public view returns (bool) {
for (uint i = 0; i < _officialContracts.length; i++) {
if (_officialContracts[i] == addr) {
return true;
}
}
return false;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Bytes.sol";
import "./Auth.sol";
import "../Interface/BaseInterface.sol";
contract ERC721Attr is Program {
using Bytes for bytes;
IERC721Token private tokenAddress;
// key => field => value.
// Record the fields and values corresponding to each contract
mapping(address => mapping(uint256 => mapping(string => bytes))) private values;
// field => types.
// Define fields and types
mapping(address => mapping(string => uint256)) private fieldsType;
// field => auth.
// Define the modification permissions of the field.
// 1 =>onlyAdmin, 2 => onlyProgram, 3 => owner
mapping(address => mapping(string => uint256)) private fieldsAuth;
// field => value => true.
// Record has only required fields
mapping(address => mapping(string => mapping(bytes => bool))) private uniques;
// 记录数组。
// tokenId ===> field ===> 索引
mapping(uint256 => mapping(string => uint256)) private index;
// tokenId ===> field ===> 索引 ===> 值
mapping(uint256 => mapping(string => mapping(uint256 => bytes))) private arrayValue;
modifier checkAuth(string memory fields, address addr, uint256 tokenId) {
uint256 auth = fieldsAuth[addr][fields];
if (auth == 1) {
require(isAdmin(msg.sender), "only admin");
} else if (auth == 2) {
require(isProgram(msg.sender), "only program");
} else if (auth == 3) {
tokenAddress = IERC721Token(addr);
require(tokenAddress.ownerOf(tokenId) == msg.sender, "only owner");
} else if (auth == 0) {
require(false, "Invalid field");
}
_;
}
function initialize() public initializer {
program_initialize();
}
// 初始化参数,参数名称、参数类型、参数修改权限(1 admin,2 program,3 拥有者)
function setFiled(address addr, string[] memory field, uint256[] memory types, uint256[] memory auth) public onlyAdmin returns (bool) {
require(field.length > 0 && field.length <= 256, "Invalid parameters");
require(field.length == types.length && field.length == auth.length, "Invalid parameters");
for (uint256 i = 0; i < field.length; i++) {
bool result = _setFiled(addr, field[i], types[i], auth[i]);
require(result, "setFiled error");
}
return true;
}
function setValues(address addr, uint256 tokenId, string memory field, bytes memory value) public checkAuth(field, addr, tokenId) returns (bool) {
bool result = _setValue(addr, tokenId, field, value);
return result;
}
function setUniques(address addr, string memory field, bytes memory value) public onlyProgram returns (bool) {
require(!uniques[addr][field][value], "Uniqueness verification failed");
bool result = _setUniques(addr, field, value, true);
return result;
}
function clearUniques(address addr, string memory field, bytes memory value) public onlyProgram returns (bool) {
require(uniques[addr][field][value], "Uniqueness verification failed");
bool result = _setUniques(addr, field, value, false);
delete uniques[addr][field][value];
return result;
}
function delFiled(address addr, string memory field) public onlyAdmin returns (bool) {
bool result = _delFiled(addr, field);
return result;
}
function delValues(address addr, uint256 tokenId, string memory field) public checkAuth(field, addr, tokenId) returns (bool) {
bool result = _delValue(addr, tokenId, field);
return result;
}
// function delUniques(address addr, string memory field) public onlyProgram returns (bool) {
// _delUniques(field);
// return true;
// }
function _setValue(address addr, uint256 tokenId, string memory field, bytes memory value) internal returns (bool){
values[addr][tokenId][field] = value;
return true;
}
function _setUniques(address addr, string memory field, bytes memory value, bool b) internal returns (bool){
uniques[addr][field][value] = b;
return true;
}
function _setFiled(address addr, string memory field, uint256 types, uint256 auth) internal returns (bool){
fieldsType[addr][field] = types;
fieldsAuth[addr][field] = auth;
return true;
}
function _delFiled(address addr, string memory field) internal returns (bool){
delete fieldsType[addr][field];
delete fieldsAuth[addr][field];
return true;
}
function _delValue(address addr, uint256 tokenId, string memory field) internal returns (bool){
delete values[addr][tokenId][field];
return true;
}
function getValue(address addr, uint256 tokenId, string memory field) public view returns (bytes memory result){
return values[addr][tokenId][field];
}
function getAuth(address addr, string memory field) public view returns (uint256){
return fieldsAuth[addr][field];
}
function getType(address addr, string memory field) public view returns (uint256){
return fieldsType[addr][field];
}
function getUniques(address addr, string memory field, bytes memory value) public view returns (bool){
return uniques[addr][field][value];
}
function setArrayValue(uint256 tokenId, string memory field, bytes memory value) public onlyProgram returns (bool){
uint256 count = index[tokenId][field];
arrayValue[tokenId][field][count] = value;
index[tokenId][field] = count + 1;
return true;
}
function delArrayValue(uint256 tokenId, string memory field) public onlyProgram returns (bool){
uint256 count = index[tokenId][field];
for (uint256 i = 0; i < count; i++) {
delete arrayValue[tokenId][field][i];
}
delete index[tokenId][field];
return true;
}
function removeArrayValue(uint256 tokenId, string memory field, bytes memory value) public onlyProgram returns (bool){
uint256 count = index[tokenId][field];
bool isOn;
for (uint256 i = 0; i < count; i++) {
if (keccak256(value) == keccak256(arrayValue[tokenId][field][i])) {
isOn = true;
continue;
}
if (isOn) {
bytes memory oldValue = arrayValue[tokenId][field][i];
arrayValue[tokenId][field][i - 1] = oldValue;
}
}
if (isOn) {
index[tokenId][field] = count - 1;
}
return true;
}
function checkArrayValue(uint256 tokenId, string memory field, bytes memory value) public view onlyProgram returns (bool){
uint256 count = index[tokenId][field];
for (uint256 i = 0; i < count; i++) {
if (keccak256(value) == keccak256(arrayValue[tokenId][field][i])) {
return true;
}
}
return false;
}
function getArrayValue(uint256 tokenId, string memory field) public view returns (uint256[] memory){
uint256 count = index[tokenId][field];
uint256[] memory arr = new uint256[](count);
for (uint256 i = 0; i < count; i++) {
bytes memory id = arrayValue[tokenId][field][i];
arr[i] = id.BytesToUint256();
}
return arr;
}
function getArrayCount(uint256 tokenId, string memory field) public view returns (uint256){
return index[tokenId][field];
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../Interface/IERC721Attr.sol";
import "../Interface/IERC721Token.sol";
import "../Interface/IConstant.sol";
import "../Interface/ICoin.sol";
import "./Auth.sol";
import "../library/Bytes.sol";
import "hardhat/console.sol";
interface IArenaOpera {
function setHorseFactName(uint256 tokenId, string calldata name) external returns (bool);
function setCreateTime(uint256 tokenId, uint256 time) external returns (bool);
function setHorseFactTypes(uint256 tokenId, uint256 types) external returns (bool);
function setFactoryStatus(uint256 tokenId, uint256 status) external returns (bool);
function setMortAmount(uint256 tokenId, uint256 amount) external returns (bool);
function getCreateTime(uint256 tokenId) external returns (uint256);
function getMortAmount(uint256 tokenId) external returns (uint256);
}
contract HorseArenaContract is Program {
using Math for uint256;
using Bytes for bytes;
ICoin private _coin; // 抵押token合约地址
IArenaOpera private _opera;
IERC721Token private _arenaTokenAddress;
IConstant private _constant; // 常量合约地址
event MintArena(address account, uint256 tokenId, uint256 time, uint256 types, uint256 mortAmount, string name, uint256 status);
event CloseArena(address account, uint256 tokenId, uint256 time, uint256 mortAmount, uint256 status);
event ArenaTransfer(address from, address to, uint256 tokenId, uint256 time);
modifier checkAuth(uint256 tokenId) {
require(_arenaTokenAddress.ownerOf(tokenId) == msg.sender, "only owner can do it!");
_;
}
modifier senderIsToken() {
require(msg.sender == address(_arenaTokenAddress), "only token contract can do it");
_;
}
function initialize() public initializer {
program_initialize();
}
function init(address operaAddr, address tokenAddr, address coinAddr, address consAddr) public onlyAdmin returns (bool){
_opera = IArenaOpera(operaAddr);
_arenaTokenAddress = IERC721Token(tokenAddr);
_coin = ICoin(coinAddr);
_constant = IConstant(consAddr);
return true;
}
// 生成马场:type : 0 官方的, 1 私人的
function _mintArena(string memory name, bytes memory sign, uint256 types) internal returns (uint256) {
require(sign.Decode(name) == _constant.getAccount(), "Signature verification failure");
require(types == 0 || types == 1, "invalid arena type");
_coin.safeTransferFrom1(_constant.getMortToken(), msg.sender, address(_coin), _constant.getMortAmount());
uint256 tokenId = _arenaTokenAddress.mint(msg.sender);
_opera.setHorseFactName(tokenId, name);
_opera.setCreateTime(tokenId, block.timestamp);
_opera.setHorseFactTypes(tokenId, types);
_opera.setFactoryStatus(tokenId, 1);
_opera.setMortAmount(tokenId, _constant.getMortAmount());
emit MintArena(msg.sender, tokenId, block.timestamp, types, _constant.getMortAmount(), name, 1);
return tokenId;
}
function mintOfficialArena(string memory name, bytes memory sign) public onlyAdmin() {
_mintArena(name, sign, 0);
}
// 抵押增发赛场
function mintArena(string memory name, bytes memory sign) public returns (uint256) {
return _mintArena(name, sign, 1);
}
// 关闭赛场
function closeArena(uint256 tokenId) public checkAuth(tokenId) returns (bool) {
uint256 current = block.timestamp;
uint256 spacing = current - (_opera.getCreateTime(tokenId));
require(spacing > _constant.getMinMortTime(), "Must not be less than the minimum mortgage time");
uint256 mortAmount = _opera.getMortAmount(tokenId);
_coin.safeTransfer1(_constant.getMortToken(), msg.sender, mortAmount);
_opera.setFactoryStatus(tokenId, 2);
_arenaTokenAddress.safeTransferFrom(msg.sender, address(_arenaTokenAddress), tokenId);
emit CloseArena(msg.sender, tokenId, block.timestamp, mortAmount, 2);
return true;
}
function beforeTransfer(address from, address to, uint256) public view senderIsToken returns (bool) {
// no need more handler.
if (_constant.isOfficialContract(from) || _constant.isOfficialContract(to)) {
//console.log("no need handler for arena extra contract transfer");
} else {
// nothing to do.
}
return true;
}
function afterTransfer(address from, address to, uint256 tokenId) public senderIsToken returns (bool) {
if (_constant.isOfficialContract(from) || _constant.isOfficialContract(to)) {
//console.log("no need handler for arena extra contract transfer");
} else {
console.log("emit event arenatransfer");
emit ArenaTransfer(from, to, tokenId,block.timestamp);
}
return true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../Interface/IERC721Attr.sol";
import "../Interface/IERC721Token.sol";
import "../library/Bytes.sol";
import "../library/Uint256.sol";
import "../library/String.sol";
import "../library/Address.sol";
import "./Auth.sol";
contract HorseArenaAttrOperaContract is Program {
using Uint256 for uint256;
using String for string;
using Address for address;
using Bytes for bytes;
IERC721Attr private _horseFactoryAttrAddress;
IERC721Token private _horseFactoryTokenAddress;
string public _name; //名称
string public _createTime; //创建日期
string public _ownerType; //类型
string public _isClose; // 是否关闭
string public _raceCount; //当天开赛次数,私人赛场每天有次数限制
string public _lastRaceTime; //最后一次开赛时间
string public _totalRaceCount; //总开赛次数
string public _mortAmount; //抵押金额
string public _gameId; //比赛的id
string public _horseIds; //比赛的id
modifier checkOwnerTypeValue(uint256 ownerType) {
if (ownerType == 0 || ownerType == 1) {
require(true, "Legal field value");
} else {
require(false, "Invalid field value");
}
_;
}
modifier checkAuth(uint256 tokenId) {
require(_horseFactoryTokenAddress.ownerOf(tokenId) == msg.sender, "only owner can do it!");
_;
}
function initialize() public initializer {
program_initialize();
_name = "name";//名称
_createTime = "createTime";//创建日期
_ownerType = "ownerType";//类型
_isClose = "isClose"; // 是否关闭
_raceCount = "raceCount";//当天开赛次数,私人赛场每天有次数限制
_lastRaceTime = "lastRaceTime";//最后一次开赛时间
_totalRaceCount = "totalRaceCount";//总开赛次数
_mortAmount = "mortAmount";//抵押金额
_gameId = "gameId";//比赛的id
_horseIds = "horseIds";//比赛的id
}
function init(address factoryAttrAddress, address factoryToken) public onlyAdmin returns (bool) {
_horseFactoryAttrAddress = IERC721Attr(factoryAttrAddress);
_horseFactoryTokenAddress = IERC721Token(factoryToken);
return true;
}
function setHorseFactName(uint256 tokenId, string memory name) public onlyProgram returns (bool) {
bytes memory nameBytes = name.StringToBytes();
bool boo = _horseFactoryAttrAddress.getUniques(address(_horseFactoryTokenAddress), _name, nameBytes);
require(!boo, "Name already used");
bool result = _horseFactoryAttrAddress.setValues(address(_horseFactoryTokenAddress), tokenId, _name, nameBytes);
_horseFactoryAttrAddress.setUniques(address(_horseFactoryTokenAddress), _name, nameBytes);
return result;
}
function setCreateTime(uint256 tokenId, uint256 time) public onlyProgram returns (bool) {
bool result = _horseFactoryAttrAddress.setValues(address(_horseFactoryTokenAddress), tokenId, _createTime, time.Uint256ToBytes());
return result;
}
function setHorseFactTypes(uint256 tokenId, uint256 types) public onlyProgram returns (bool) {
bool result = _horseFactoryAttrAddress.setValues(address(_horseFactoryTokenAddress), tokenId, _ownerType, types.Uint256ToBytes());
return result;
}
function setFactoryStatus(uint256 tokenId, uint256 status) public onlyProgram returns (bool) {
bool result = _horseFactoryAttrAddress.setValues(address(_horseFactoryTokenAddress), tokenId, _isClose, status.Uint256ToBytes());
return result;
}
function setRaceCount(uint256 tokenId, uint256 count) public onlyProgram returns (bool) {
bool result = _horseFactoryAttrAddress.setValues(address(_horseFactoryTokenAddress), tokenId, _raceCount, count.Uint256ToBytes());
return result;
}
function uptTotalRaceCount(uint256 tokenId, uint256 count) public onlyProgram returns (bool) {
bool result = _horseFactoryAttrAddress.setValues(address(_horseFactoryTokenAddress), tokenId, _totalRaceCount, count.Uint256ToBytes());
return result;
}
function setLastRaceTime(uint256 tokenId, uint256 time) public onlyProgram returns (bool) {
bool result = _horseFactoryAttrAddress.setValues(address(_horseFactoryTokenAddress), tokenId, _lastRaceTime, time.Uint256ToBytes());
return result;
}
function setMortAmount(uint256 tokenId, uint256 amount) public onlyProgram returns (bool) {
bool result = _horseFactoryAttrAddress.setValues(address(_horseFactoryTokenAddress), tokenId, _mortAmount, amount.Uint256ToBytes());
return result;
}
function getFactoryName(uint256 tokenId) public view returns (string memory){
bytes memory bytesInfo = _horseFactoryAttrAddress.getValue(address(_horseFactoryTokenAddress), tokenId, _name);
return bytesInfo.BytesToString();
}
function getCreateTime(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseFactoryAttrAddress.getValue(address(_horseFactoryTokenAddress), tokenId, _createTime);
return bytesInfo.BytesToUint256();
}
function getOwnerType(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseFactoryAttrAddress.getValue(address(_horseFactoryTokenAddress), tokenId, _ownerType);
return bytesInfo.BytesToUint256();
}
function getIsClose(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseFactoryAttrAddress.getValue(address(_horseFactoryTokenAddress), tokenId, _isClose);
return bytesInfo.BytesToUint256();
}
function getRaceCount(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseFactoryAttrAddress.getValue(address(_horseFactoryTokenAddress), tokenId, _raceCount);
return bytesInfo.BytesToUint256();
}
function getLastRaceTime(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseFactoryAttrAddress.getValue(address(_horseFactoryTokenAddress), tokenId, _lastRaceTime);
return bytesInfo.BytesToUint256();
}
function getTotalRaceCount(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseFactoryAttrAddress.getValue(address(_horseFactoryTokenAddress), tokenId, _totalRaceCount);
return bytesInfo.BytesToUint256();
}
function getMortAmount(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseFactoryAttrAddress.getValue(address(_horseFactoryTokenAddress), tokenId, _mortAmount);
return bytesInfo.BytesToUint256();
}
function setGameId(uint256 tokenId, uint256 gameId) public onlyProgram returns (bool) {
bool result = _horseFactoryAttrAddress.setArrayValue(tokenId, _gameId, gameId.Uint256ToBytes());
return result;
}
function setHorseId(uint256 tokenId, uint256 horseId) public onlyProgram returns (bool) {
bool result = _horseFactoryAttrAddress.setArrayValue(tokenId, _horseIds, horseId.Uint256ToBytes());
return result;
}
function checkGameId(uint256 tokenId, uint256 gameId) public view returns (bool){
bool result = _horseFactoryAttrAddress.checkArrayValue(tokenId, _gameId, gameId.Uint256ToBytes());
return result;
}
function checkGameIdIsExit(uint256 gameId) public view returns (bool){
bytes memory idBytes = gameId.Uint256ToBytes();
bool boo = _horseFactoryAttrAddress.getUniques(address(_horseFactoryTokenAddress), _gameId, idBytes);
return boo;
}
function setGameIdUniques(uint256 gameId) public onlyProgram returns (bool) {
bytes memory idBytes = gameId.Uint256ToBytes();
bool boo = _horseFactoryAttrAddress.setUniques(address(_horseFactoryTokenAddress), _gameId, idBytes);
return boo;
}
function clearGameIdUniques(uint256 gameId) public onlyProgram returns (bool) {
bytes memory idBytes = gameId.Uint256ToBytes();
bool boo = _horseFactoryAttrAddress.setUniques(address(_horseFactoryTokenAddress), _gameId, idBytes);
return boo;
}
function checkHorseId(uint256 tokenId, uint256 horseId) public view returns (bool){
bool result = _horseFactoryAttrAddress.checkArrayValue(tokenId, _horseIds, horseId.Uint256ToBytes());
return result;
}
function getHorseIdCount(uint256 tokenId) public view returns (uint256){
uint256 count = _horseFactoryAttrAddress.getArrayCount(tokenId, _horseIds);
return count;
}
function delHorseIdOne(uint256 tokenId, uint256 horseId) public onlyProgram returns (bool) {
bool result = _horseFactoryAttrAddress.removeArrayValue(tokenId, _horseIds, horseId.Uint256ToBytes());
return result;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../Interface/IERC721Attr.sol";
import "../Interface/ICoin.sol";
import "../Interface/IConstant.sol";
import "../Interface/BaseInterface.sol";
import "./Auth.sol";
import "hardhat/console.sol";
interface IHorseRaceOpera {
function setHorseStatusBatch(uint256[] calldata tokenId, uint256 status) external returns (bool);
// 设置能量
function setHorseEnergy(uint256 tokenId, uint256 energy) external returns (bool);
// 能量恢复时间
function setHorseEngTime(uint256 tokenId, uint256 energyUpdateTime) external returns (bool);
// 马匹评分
function setHorseGradeSc(uint256 tokenId, uint256 gradeScore) external returns (bool);
// 马匹积分
function setHorseIntegral(uint256 tokenId, uint256 integral) external returns (bool);
// 马匹积分正负值标记
function setHorseIntMark(uint256 tokenId, uint256 gradeScoreMark) external returns (bool);
//积分最后一次更新时间
function setHorseScUptTime(uint256 tokenId, uint256 raceScoreUpdateTime) external returns (bool);
function setRaceId(uint256 tokenId, uint256 raceId) external returns (bool);
function setHorseCount(uint256 tokenId) external returns (bool);
function setWinCount(uint256 tokenId) external returns (bool);
function setGrade(uint256 tokenId, uint256 grade) external returns (bool);
function setRaceType(uint256 tokenId, uint256 raceType) external returns (bool);
function setRacecourse(uint256 tokenId, uint256 racecourse) external returns (bool);
function setDistance(uint256 tokenId, uint256 distance) external returns (bool);
function setHorseDetailIntegral(uint256 tokenId, uint256 totalIntegral, uint256 integralYear, uint256 integralMonth, uint256 integralWeek) external returns (bool);
function setHorseIntegralDate(uint256 tokenId, uint256 year, uint256 month, uint256 week) external returns (bool);
function getEnergy(uint256 tokenId) external view returns (uint256);
function getEnergyUpdateTime(uint256 tokenId) external view returns (uint256);
function getTrainingValue(uint256 tokenId) external view returns (uint256);
function getTrainingTime(uint256 tokenId) external view returns (uint256);
function getGradeScoreMark(uint256 tokenId) external returns (uint256);
function getGradeScore(uint256 tokenId) external returns (uint256);
function getGrade(uint256 tokenId) external returns (uint256);
function getIntegral(uint256 tokenId) external returns (uint256);
function getWinCount(uint256 tokenId) external returns (uint256);
function getRaceCount(uint256 tokenId) external returns (uint256);
function getDistance(uint256 tokenId) external returns (uint256);
function getDetailIntegral(uint256 tokenId) external returns (uint256, uint256, uint256, uint256);
function getIntegralDate(uint256 tokenId) external returns (uint256, uint256, uint256);
}
interface IERC20Mint is IERC20Token {
function mint(address recipient, uint amount) external;
}
interface IRacecourseOpera {
function getHorseId(uint256 tokenId) external returns (uint256[] memory);
function checkHorseId(uint256 tokenId, uint256 horseId) external returns (bool);
}
interface IArenaOpera {
function getIsClose(uint256 tokenId) external returns (uint256);
function checkGameId(uint256 tokenId, uint256 gameId) external returns (bool);
}
contract HorseArenaExtra is Program {
using Math for uint256;
ICoin private _coin; // 抵押token合约地址
IERC20Token private _metaToken; // meta token
IERC20Mint private _raceToken; // race token
IArenaOpera private _opera;
IRacecourseOpera private _racecourseOpera;
IHorseRaceOpera private _horseOpera;
IHorseRaceOpera private _horseOpera1_1;
IHorseRaceOpera private _horseOpera2;
IHorseRaceOpera private _horseOpera2_1;
IERC721Token private _horseTokenAddress; // 比赛合约地址
IERC721Token private _arenaTokenAddress; // 赛场资产地址
IConstant private _constant; // 常量合约地址
IRaceBonusDistribute private _bonusPool; // 奖池合约
event EndGame(uint256 gameId, uint256 status, uint256 time);
event SetHorseIntegral(uint256 horseId, uint256 count, uint256 time, uint256 integralYear, uint256 integralMonth, uint256 integralWeek);
event SetHorseGradeSc(uint256 horseId, uint256 count, uint256 mark, uint256 time, uint256 grade);
event EndGameOfHorse(uint256 horseId, uint256 status, uint256 time, int256 arenaId,
uint256 gameId, uint256 raceType, uint256 distance, uint256 energy, uint256 raceCount, uint256 winCount, uint256 grade);
function initialize() public initializer {
program_initialize();
}
function init(address operaAddr, address coinAddr, address racecourseOpera,
address horseOpera, address horseOpera1_1, address horseOpera2, address horseOpera2_1,
address horseTokenAddress, address arenaTokenAddress, address consAddr, address metaCoin, address raceCoin) public onlyAdmin returns (bool){
_opera = IArenaOpera(operaAddr);
_coin = ICoin(coinAddr);
_racecourseOpera = IRacecourseOpera(racecourseOpera);
_horseOpera = IHorseRaceOpera(horseOpera);
_horseOpera1_1 = IHorseRaceOpera(horseOpera1_1);
_horseOpera2 = IHorseRaceOpera(horseOpera2);
_horseOpera2_1 = IHorseRaceOpera(horseOpera2_1);
_horseTokenAddress = IERC721Token(horseTokenAddress);
_arenaTokenAddress = IERC721Token(arenaTokenAddress);
_constant = IConstant(consAddr);
_metaToken = IERC20Token(metaCoin);
_raceToken = IERC20Mint(raceCoin);
return true;
}
function setDistribute(address distribute) public onlyAdmin returns (bool) {
_bonusPool = IRaceBonusDistribute(distribute);
return true;
}
function calcIntegral(uint256 horseId, uint256 newIntegral) public returns (uint256, uint256, uint256, uint256) {
uint256 totalIntegral;
uint256 yearIntegral;
uint256 monthIntegral;
uint256 weekIntegral;
(totalIntegral, yearIntegral, monthIntegral, weekIntegral) = _horseOpera2.getDetailIntegral(horseId);
uint256 lastYear;
uint256 lastMonth;
uint256 lastWeek ;
(lastYear, lastMonth, lastWeek) = _horseOpera2.getIntegralDate(horseId);
uint32 nowYear;
uint32 nowMonth;
uint32 nowWeek ;
(nowYear, nowMonth, nowWeek) = _constant.getDate();
if (nowWeek != lastWeek) {
weekIntegral = 0;
}
if (nowMonth != lastMonth) {
monthIntegral = 0;
}
if (nowYear != lastYear) {
yearIntegral = 0;
}
totalIntegral += newIntegral;
weekIntegral += newIntegral;
monthIntegral += newIntegral;
yearIntegral += newIntegral;
return (totalIntegral, yearIntegral, monthIntegral, weekIntegral);
}
function getHorseEnergy(uint256 horseId) public view returns(uint256) {
uint256 energy = _horseOpera2.getEnergy(horseId);
uint256 lastTime = _horseOpera2.getEnergyUpdateTime(horseId);
uint256 recover = _constant.getEnergyRecoverCD();
uint256 maxEnergy = _constant.getMaxEnergy();
if (block.timestamp > lastTime) {
energy = energy + (block.timestamp - lastTime) / recover;
}
return (energy > maxEnergy) ? maxEnergy : energy;
}
function getHorseTraingValue(uint256 horseId) public view returns(uint256) {
uint256 lastTraTime = _horseOpera2.getTrainingTime(horseId);
uint256 current = block.timestamp;
// 计算马匹当前训练值
uint256 traingUntTime = _constant.getUntTime();
uint256 traingValue = _horseOpera2.getTrainingValue(horseId);
uint256 subValue = (current - lastTraTime) / traingUntTime;
if (traingValue <= subValue) {
subValue = traingValue; // 最多减去当前已有的训练值,避免溢出.
}
traingValue = traingValue - (subValue);
traingValue = traingValue.max(_constant.getMinTraValue());
return traingValue;
}
function updateHorseEnergy(uint256 distance, uint256 horseId) internal returns(uint256) {
uint256 useEnergy = (distance / 1200) * _constant.getUseEnergy();
uint256 energy = getHorseEnergy(horseId);
if (useEnergy > energy) {
energy = 0;
} else {
energy = energy - (useEnergy);
}
_horseOpera.setHorseEnergy(horseId, energy);
_horseOpera.setHorseEngTime(horseId, block.timestamp);
return energy;
}
// 大奖赛结束比赛.rank是horseId排序
function endGrandGame(uint256 tokenId, uint256 gameId, uint256[] memory rank,
uint256[] memory score, uint256[] memory comp) public onlyProgram returns (bool){
require(_opera.getIsClose(tokenId) == 1, "The stadium is closed");
require(_opera.checkGameId(tokenId, gameId), "The field and the game do not match");
require(rank.length == score.length && rank.length == comp.length && rank.length == _constant.getTrackNumber(), "Track limit exceeded");
require(_checkScore(rank, score), "Score check failure");
uint256[] memory horseIds = _racecourseOpera.getHorseId(gameId);
uint256 distance = _horseOpera2_1.getDistance(rank[0]);
// 批量修改马匹状态为休息中
_horseOpera1_1.setHorseStatusBatch(horseIds, _constant.getResting());
for (uint256 i = 0; i < rank.length; i++) {
require(_racecourseOpera.checkHorseId(gameId, rank[i]), "The field does not match the horses");
require(_check(horseIds, rank[i]), "Horse information does not match");
uint256 level = _horseOpera2_1.getGrade(rank[i]);
uint256 energy = updateHorseEnergy(distance, rank[i]);
if (i < 3) {
// 前三名
_horseOpera1_1.setWinCount(rank[i]);
{
uint256 totalIntegral;
uint256 integralYear;
uint256 integralMonth;
uint256 integralWeek;
uint256 newIntegral = _constant.getMaxScore() - i - level + 1;
(totalIntegral, integralYear, integralMonth, integralWeek) = calcIntegral(rank[i], newIntegral);
_horseOpera.setHorseDetailIntegral(rank[i], totalIntegral, integralYear, integralMonth, integralWeek);
emit SetHorseIntegral(rank[i], totalIntegral, block.timestamp, integralYear, integralMonth, integralWeek);
}
{
uint256 nowYear;
uint256 nowMonth;
uint256 nowWeek;
(nowYear,nowMonth,nowWeek) = _constant.getDate();
_horseOpera.setHorseIntegralDate(rank[i], nowYear, nowMonth, nowWeek);
}
}
if (i < 4 || i > 7) {
_horseOpera.setHorseGradeSc(rank[i], score[i]);
_horseOpera.setHorseScUptTime(rank[i], block.timestamp);
uint256 _grade = _setGrade(comp[i], rank[i]);
emit SetHorseGradeSc(rank[i], score[i], _horseOpera2.getGradeScoreMark(rank[i]), block.timestamp, _grade);
}
// 马匹参赛信息,逻辑删除
_horseOpera1_1.setHorseCount(rank[i]);
_horseOpera1_1.setRaceId(rank[i], 0);
_horseOpera1_1.setRaceType(rank[i], 0);
_horseOpera1_1.setRacecourse(rank[i], 0);
_horseOpera1_1.setDistance(rank[i], 0);
uint256 raceCount = _horseOpera2_1.getRaceCount(rank[i]);
uint256 winCount = _horseOpera2_1.getWinCount(rank[i]);
uint256 grade = _horseOpera2_1.getGrade(rank[i]);
emit EndGameOfHorse(rank[i], _constant.getResting(), block.timestamp, 0, 0, 0, 0,
energy, raceCount, winCount, grade);
}
_raceAward(rank, distance);
_distApplyFee(tokenId, rank, distance);
emit EndGame(tokenId, 0, block.timestamp);
return true;
}
// 积分赛结束比赛.rank是horseId排序
function endPointGame(uint256 tokenId, uint256 gameId, uint256[] memory rank,
uint256[] memory score, uint256[] memory comp) public onlyProgram returns (bool){
require(_opera.getIsClose(tokenId) == 1, "The stadium is closed");
require(_opera.checkGameId(tokenId, gameId), "The field and the game do not match");
require(rank.length == score.length && rank.length == _constant.getTrackNumber(), "Track limit exceeded");
require(_checkScore(rank, score), "Score check failure");
uint256[] memory horseIds = _racecourseOpera.getHorseId(gameId);
uint256 distance = _horseOpera2_1.getDistance(rank[0]);
// 批量修改马匹状态为休息中
_horseOpera1_1.setHorseStatusBatch(horseIds, _constant.getResting());
for (uint256 i = 0; i < rank.length; i++) {
require(_racecourseOpera.checkHorseId(gameId, rank[i]), "The field does not match the horses");
require(_check(horseIds, rank[i]), "Horse information does not match");
uint256 energy = updateHorseEnergy(distance, rank[i]);
if (i < 3) {
_horseOpera1_1.setWinCount(rank[i]);
}
if (i < 4 || i > 7) {
_horseOpera.setHorseGradeSc(rank[i], score[i]);
_horseOpera.setHorseScUptTime(rank[i], block.timestamp);
uint256 _grade = _setGrade(comp[i], rank[i]);
emit SetHorseGradeSc(rank[i], score[i], _horseOpera2.getGradeScoreMark(rank[i]), block.timestamp, _grade);
}
// 马匹参赛信息,逻辑删除
_horseOpera1_1.setHorseCount(rank[i]);
_horseOpera1_1.setRaceId(rank[i], 0);
_horseOpera1_1.setRaceType(rank[i], 0);
_horseOpera1_1.setRacecourse(rank[i], 0);
_horseOpera1_1.setDistance(rank[i], 0);
// uint256 useEnergy = _horseOpera2_1.getDistance(rank[i]).div(1200).mul(_constant.getUseEnergy());
// 修改马匹能量值
uint256 raceCount = _horseOpera2_1.getRaceCount(rank[i]);
uint256 winCount = _horseOpera2_1.getWinCount(rank[i]);
uint256 grade = _horseOpera2_1.getGrade(rank[i]);
emit EndGameOfHorse(rank[i], _constant.getResting(), block.timestamp, 0, 0, 0, 0,
energy, raceCount, winCount, grade);
}
emit EndGame(gameId, 0, block.timestamp);
return true;
}
// 根据综合评分设置马匹等级
function _setGrade(uint256 score, uint256 horseId) internal returns (uint256){
uint256 grade;
if (score < 20) {
grade = 999;
} else if (score < 30) {
grade = 5;
} else if (score < 40) {
grade = 4;
} else if (score < 50) {
grade = 3;
} else if (score < 60) {
grade = 2;
} else {
grade = 1;
}
_horseOpera1_1.setGrade(horseId, grade);
return grade;
}
// 验证马匹评分.
function _checkScore(uint256[] memory rank, uint256[] memory score) internal returns (bool){
// 第一名增加的评分,然后递减
uint256 integral = 4;
for (uint256 i = 0; i < rank.length; i++) {
uint256 horseScore = _horseOpera2.getGradeScore(rank[i]);
uint256 newInt;
if (3 < i && i < 8) {
newInt = horseScore;
}
if (i < 4) {
newInt = horseScore - (integral);
integral = integral - (1);
}
if (i > 7) {
// 分数不能为负.
integral = integral + 1;
if (horseScore >= integral) {
newInt = horseScore - integral;
} else if (horseScore < integral) {
newInt = 0;
}
}
if (newInt != score[i]) {
return false;
}
}
return true;
}
function _raceAward(uint256 []memory rank, uint256 distance) internal {
uint256 maxAward = _constant.getAwardAmountByDistance(distance);
for (uint256 i = 0; i < rank.length; i++) {
address owner = _horseTokenAddress.ownerOf(rank[i]);
{
uint decimal = _raceToken.decimals();
uint256 award = maxAward * 10 ** decimal;
console.log("award owner", owner);
console.log("award race", award);
_raceToken.mint(owner, award);
}
}
}
function _distApplyFee(uint256 tokenId, uint256 []memory rank, uint256 distance) internal {
uint256 applyAmount = _constant.getApplyGameAmountByDistance(distance);
uint256 total = rank.length * applyAmount;
address owner = _arenaTokenAddress.ownerOf(tokenId);
uint decimal = _coin.decimals(_constant.getApplyGameToken());
total = total * 10 ** decimal;
uint256 leng;
address [] memory addresses;
uint256[] memory money;
(leng, addresses, money) = _bonusPool.distribute(owner, rank, total);
console.log("get distribute length is ", leng);
for(uint256 i=0; i < leng; i++) {
console.log("distribute fee to user ", addresses[i]);
console.log("distribute fee to user amount ", money[i]);
_coin.safeTransferWei(_constant.getApplyGameToken(), addresses[i], money[i]);
}
}
function _check(uint256[] memory horseIds, uint256 horseId) internal pure returns (bool){
for (uint256 a = 0; a < horseIds.length; a++) {
if (horseIds[a] == horseId) {
return true;
}
}
return false;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../Interface/ICoin.sol";
import "../Interface/IConstant.sol";
import "./Auth.sol";
interface IHorseRaceOpera {
function setHorseStatusBatch(uint256[] calldata tokenId, uint256 status) external returns (bool);
function setHorseStatus(uint256 tokenId, uint256 status) external returns (bool);
function setRaceUpdateTime(uint256 tokenId, uint256 raceUpdateTime) external returns (bool);
function getBirthDay(uint256 tokenId) external returns (uint256);
function getHorseRaceStatus(uint256 tokenId) external returns (uint256);
function getRaceUpdateTime(uint256 tokenId) external returns (uint256);
function setRaceId(uint256 tokenId, uint256 raceId) external returns (bool);
function setRaceIdBatch(uint256[] calldata tokenIds, uint256 raceId) external returns (bool);
function setRaceType(uint256 tokenId, uint256 raceType) external returns (bool);
function setRacecourse(uint256 tokenId, uint256 racecourse) external returns (bool);
function setDistance(uint256 tokenId, uint256 distance) external returns (bool);
function getGrade(uint256 tokenId) external returns (uint256);
function getRacecourse(uint256 tokenId) external returns (uint256);
function checkStatus(uint256[] calldata tokenIds, uint256 status) external returns (bool);
function checkGameInfo(uint256[] calldata tokenIds, uint256 types, uint256 racecourseId,
uint256 level, uint256 distance) external returns (bool);
function getDistance(uint256 tokenId) external returns (uint256);
}
interface IERC721Token {
function ownerOf(uint256 tokenId) external view returns (address owner);
}
interface IRacecourseOpera {
function setHorseId(uint256 tokenId, uint256 horseId) external returns (bool);
function getHorseId(uint256 tokenId) external returns (uint256[] memory);
function delHorseId(uint256 tokenId) external returns (bool);
}
interface IArenaOpera {
function getIsClose(uint256 tokenId) external returns (uint256);
function checkGameIdIsExit(uint256 gameId) external returns (bool);
function setGameIdUniques(uint256 gameId) external returns (bool);
function getHorseIdCount(uint256 tokenId) external returns (uint256);
function setHorseId(uint256 tokenId, uint256 horseId) external returns (bool);
function delHorseIdOne(uint256 tokenId, uint256 horseId) external returns (bool);
function checkGameId(uint256 tokenId, uint256 gameId) external returns (bool);
function checkHorseId(uint256 tokenId, uint256 gameId) external returns (bool);
function getRaceCount(uint256 tokenId) external returns (uint256);
function getTotalRaceCount(uint256 tokenId) external returns (uint256);
function getLastRaceTime(uint256 tokenId) external returns (uint256);
function getOwnerType(uint256 tokenId) external returns (uint256);
function setRaceCount(uint256 tokenId, uint256 count) external returns (bool);
function setGameId(uint256 tokenId, uint256 gameId) external returns (bool);
function uptTotalRaceCount(uint256 tokenId, uint256 count) external returns (bool);
function setLastRaceTime(uint256 tokenId, uint256 time) external returns (bool);
}
contract HorseArenaExtra2 is Program {
using Math for uint256;
ICoin private _coin; // 抵押token合约地址
IArenaOpera private _opera;
IHorseRaceOpera private _horseOpera1_1;
IHorseRaceOpera private _horseOpera2;
IHorseRaceOpera private _horseOpera2_1;
IConstant private _constant; // 常量合约地址
IERC721Token private _horseTokenAddress;
event ApplyGame(address account, uint256 horseId, uint256 arenaId, uint256 raceType, uint256 distance,
uint256 time, uint256 status);
event CancelApplyGame(address account, uint256 horseId, uint256 status, uint256 time, uint256 arenaId, uint256 gameId,
uint256 raceType, uint256 distance);
event WeekScoreRank(uint256[] horseId, uint256[] totalScore, address[] accounts, uint256[] rank);
event MonthScoreRank(uint256[] horseId, uint256[] totalScore, address[] accounts, uint256[] rank);
event YearsScoreRank(uint256[] horseId, uint256[] totalScore, address[] accounts, uint256[] rank);
modifier checkAuth(uint256 tokenId) {
require(_horseTokenAddress.ownerOf(tokenId) == msg.sender, "only owner can do it!");
_;
}
function initialize() public initializer {
program_initialize();
}
function init(address operaAddr, address coinAddr, address horseTokenAddress,
address horseOpera1_1, address horseOpera2, address horseOpera2_1, address consAddr) public onlyAdmin returns (bool){
_opera = IArenaOpera(operaAddr);
_coin = ICoin(coinAddr);
_horseOpera1_1 = IHorseRaceOpera(horseOpera1_1);
_horseOpera2 = IHorseRaceOpera(horseOpera2);
_horseOpera2_1 = IHorseRaceOpera(horseOpera2_1);
_constant = IConstant(consAddr);
_horseTokenAddress = IERC721Token(horseTokenAddress);
return true;
}
// 报名比赛。
function applyGame(uint256 tokenId, uint256 horseId,
uint256 raceType, uint256 distance, uint256 level) public checkAuth(horseId) {
require(_opera.getIsClose(tokenId) == 1, "The stadium is closed");
require(_horseOpera2_1.getHorseRaceStatus(horseId) == _constant.getResting(), "Abnormal state");
require(_horseOpera2_1.getGrade(horseId) == level, "Level mismatch");
require(_opera.getHorseIdCount(tokenId) <= _constant.getMaxApplyCount(), "The maximum number of apply game is exceeded");
require(level == 999 ? distance == 1200 : true, "unmatched horselevel and distance");
// 成长时间
uint256 spacing = block.timestamp - (_horseOpera2.getBirthDay(horseId));
require(spacing > _constant.getMinMatureTime(), "Immature horses");
// 多次操作冷却时间
uint256 raceSpacing = block.timestamp - (_horseOpera2_1.getRaceUpdateTime(horseId));
require(raceSpacing > _constant.getMinRaceUptTime(), "Cooling time");
// 大奖赛需要报名费
if (level != 999) {
_coin.safeTransferFrom1(_constant.getApplyGameToken(), msg.sender, address(_coin), _constant.getApplyGameAmountByDistance(distance));
}
_opera.setHorseId(tokenId, horseId);
// 修改马匹状态为报名中,记录马匹报名信息
_horseOpera1_1.setHorseStatus(horseId, _constant.getSigning());
_horseOpera1_1.setRaceType(horseId, raceType);
_horseOpera1_1.setRacecourse(horseId, tokenId);
_horseOpera1_1.setDistance(horseId, distance);
_horseOpera1_1.setRaceUpdateTime(horseId, block.timestamp);
emit ApplyGame(msg.sender, horseId, tokenId, raceType, distance, block.timestamp, _constant.getSigning());
}
// 取消报名
function cancelApplyGame(uint256 horseId) public checkAuth(horseId) {
require(_horseOpera2_1.getHorseRaceStatus(horseId) == 3, "Abnormal state");
// 多次操作冷却时间
uint256 raceSpacing = block.timestamp - (_horseOpera2_1.getRaceUpdateTime(horseId));
require(raceSpacing > _constant.getMinRaceUptTime(), "Cooling time");
// 大奖赛需要退还报名费
uint256 level = _horseOpera2_1.getGrade(horseId);
if (level != 999) {
uint256 distance = _horseOpera2_1.getDistance(horseId);
_coin.safeTransfer1(_constant.getApplyGameToken(), msg.sender, _constant.getApplyGameAmountByDistance(distance));
}
// 修改马匹状态为休息中,记录马匹报名信息,逻辑删除
_opera.delHorseIdOne(_horseOpera2_1.getRacecourse(horseId), horseId);
_horseOpera1_1.setHorseStatus(horseId, _constant.getResting());
_horseOpera1_1.setRaceId(horseId, 0);
_horseOpera1_1.setRaceType(horseId, 0);
_horseOpera1_1.setRacecourse(horseId, 0);
_horseOpera1_1.setDistance(horseId, 0);
_horseOpera1_1.setRaceUpdateTime(horseId, block.timestamp);
emit CancelApplyGame(msg.sender, horseId, _constant.getResting(), block.timestamp, 0, 0, 0, 0);
}
function _check(uint256 tokenId, uint256[] memory horseId) internal {
for (uint256 i = 0; i < horseId.length; i++) {
require(_opera.checkHorseId(tokenId, horseId[i]), "Abnormal state");
}
}
function weekRank(
uint256[] memory horseIds,
uint256[] memory totalScores,
address[] memory accounts,
uint256[] memory rank) public onlyProgram {
require(horseIds.length == totalScores.length || horseIds.length == accounts.length ||
horseIds.length == rank.length, "The parameter length is inconsistent");
emit WeekScoreRank(horseIds, totalScores, accounts, rank);
}
function monthRank(
uint256[] memory horseIds,
uint256[] memory totalScores,
address[] memory accounts,
uint256[] memory rank) public onlyProgram {
require(horseIds.length == totalScores.length || horseIds.length == accounts.length ||
horseIds.length == rank.length, "The parameter length is inconsistent");
emit MonthScoreRank(horseIds, totalScores, accounts, rank);
}
function yearsRank(
uint256[] memory horseIds,
uint256[] memory totalScores,
address[] memory accounts,
uint256[] memory rank) public onlyProgram {
require(horseIds.length == totalScores.length || horseIds.length == accounts.length ||
horseIds.length == rank.length, "The parameter length is inconsistent");
emit YearsScoreRank(horseIds, totalScores, accounts, rank);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../Interface/ICoin.sol";
import "./Auth.sol";
import "hardhat/console.sol";
interface IHorseRaceOpera {
function setHorseStatusBatch(uint256[] calldata tokenId, uint256 status) external returns (bool);
function setHorseStatus(uint256 tokenId, uint256 status) external returns (bool);
function setRaceUpdateTime(uint256 tokenId, uint256 raceUpdateTime) external returns (bool);
function getBirthDay(uint256 tokenId) external returns (uint256);
function getHorseRaceStatus(uint256 tokenId) external returns (uint256);
function getRaceUpdateTime(uint256 tokenId) external returns (uint256);
function setRaceId(uint256 tokenId, uint256 raceId) external returns (bool);
function setRaceIdBatch(uint256[] calldata tokenIds, uint256 raceId) external returns (bool);
function setRaceType(uint256 tokenId, uint256 raceType) external returns (bool);
function setRacecourse(uint256 tokenId, uint256 racecourse) external returns (bool);
function setDistance(uint256 tokenId, uint256 distance) external returns (bool);
function getGrade(uint256 tokenId) external returns (uint256);
function getRacecourse(uint256 tokenId) external returns (uint256);
function checkStatus(uint256[] calldata tokenIds, uint256 status) external returns (bool);
function checkGameInfo(uint256[] calldata tokenIds, uint256 types, uint256 racecourseId,
uint256 level, uint256 distance) external returns (bool);
}
interface IERC721Token {
function ownerOf(uint256 tokenId) external view returns (address owner);
}
interface IConstant {
function getApplyGameToken() external returns (uint256);
function getMaxApplyCount() external returns (uint256);
function getTrackNumber() external returns (uint256);
function getApplyGameAmount() external returns (uint256);
function getMinRaceUptTime() external returns (uint256);
function getMinMatureTime() external returns (uint256);
function getSigning() external returns (uint256);
function getResting() external returns (uint256);
function getInGame() external returns (uint256);
function getGameCountLimit() external returns (uint256);
function getMaxSpacing() external returns (uint256);
}
interface IRacecourseOpera {
function setHorseId(uint256 tokenId, uint256 horseId) external returns (bool);
function getHorseId(uint256 tokenId) external returns (uint256[] memory);
function delHorseId(uint256 tokenId) external returns (bool);
}
interface IArenaOpera {
function getIsClose(uint256 tokenId) external returns (uint256);
function checkGameIdIsExit(uint256 gameId) external returns (bool);
function setGameIdUniques(uint256 gameId) external returns (bool);
function clearGameIdUniques(uint256 gameId) external returns (bool);
function getHorseIdCount(uint256 tokenId) external returns (uint256);
function setHorseId(uint256 tokenId, uint256 horseId) external returns (bool);
function delHorseIdOne(uint256 tokenId, uint256 horseId) external returns (bool);
function checkGameId(uint256 tokenId, uint256 gameId) external returns (bool);
function checkHorseId(uint256 tokenId, uint256 gameId) external returns (bool);
function getRaceCount(uint256 tokenId) external returns (uint256);
function getTotalRaceCount(uint256 tokenId) external returns (uint256);
function getLastRaceTime(uint256 tokenId) external returns (uint256);
function getOwnerType(uint256 tokenId) external returns (uint256);
function setRaceCount(uint256 tokenId, uint256 count) external returns (bool);
function setGameId(uint256 tokenId, uint256 gameId) external returns (bool);
function uptTotalRaceCount(uint256 tokenId, uint256 count) external returns (bool);
function setLastRaceTime(uint256 tokenId, uint256 time) external returns (bool);
}
contract HorseArenaExtra3 is Program {
using Math for uint256;
IArenaOpera private _opera;
IRacecourseOpera private _racecourseOpera;
IHorseRaceOpera private _horseOpera1_1;
IHorseRaceOpera private _horseOpera2_1;
IConstant private _constant; // 常量合约地址
event StartGame(uint256[] horseIds, uint256 status, uint256 time, uint256 gameId);
event StartGameOfRace(uint256 gameId, uint256 status, uint256 time);
event CancelGame(uint256[] gameId, uint256 status, uint256 time);
event CancelGameOfHorse(uint256[] horseIds, uint256 status, uint256 time, uint256 gameId);
event CancelGameOfArena(address account, uint256 tokenId, uint256[] gameId, uint256 time, uint256 count, uint256 totalCount);
event UptArena(address account, uint256 tokenId, uint256 gameId, uint256 time, uint256 count, uint256 totalCount);
event CreateGame(address account, uint256 gameId, uint256 time, uint256 level, uint256 raceType, uint256 distance, uint256 status);
function initialize() public initializer {
program_initialize();
}
function init(address operaAddr, address racecourseOpera,
address horseOpera1_1, address horseOpera2_1, address consAddr) public onlyAdmin returns (bool){
_opera = IArenaOpera(operaAddr);
_racecourseOpera = IRacecourseOpera(racecourseOpera);
_horseOpera1_1 = IHorseRaceOpera(horseOpera1_1);
_horseOpera2_1 = IHorseRaceOpera(horseOpera2_1);
_constant = IConstant(consAddr);
return true;
}
event logmsg(string info);
// 开始比赛
function startGame(
uint256 tokenId,
uint256 gameId,
uint256[] memory horseId,
uint256 types,
uint256 level,
uint256 distance
) public onlyProgram returns (bool){
require(_opera.getIsClose(tokenId) == 1, "The stadium is closed");
emit logmsg("the stadium is normal");
require(horseId.length == _constant.getTrackNumber(), "Track limit exceeded");
emit logmsg("the horse track status is normal");
require(_horseOpera2_1.checkStatus(horseId, _constant.getSigning()), "Abnormal state");
emit logmsg("the horse state is normal");
require(_horseOpera2_1.checkGameInfo(horseId, types, tokenId, level, distance), "Horse registration information does not match");
emit logmsg("the horse register infomation is normal");
require(!_opera.checkGameIdIsExit(gameId), "GameId already used");
emit logmsg("the gameid is normal");
_opera.setGameIdUniques(gameId);
emit logmsg("set game id unique passed");
_check(tokenId, horseId);
emit logmsg("check race and horse id passed");
uint256 gameCount = _opera.getRaceCount(tokenId);
uint256 lastRaceTime = _opera.getLastRaceTime(tokenId);
uint256 ownerType = _opera.getOwnerType(tokenId);
emit logmsg("get count,racetime,owner passed");
uint256 gameCountLimit = _constant.getGameCountLimit();
uint256 maxSpacing = _constant.getMaxSpacing(); // 每 maxspaceing 时间可最多开启 gameCountLimit 次比赛.
emit logmsg("get countlimit,maxspace passed");
if (ownerType == 1) {
uint256 currentUnit = block.timestamp/(maxSpacing);
uint256 lastUnit = lastRaceTime/(maxSpacing);
if (currentUnit == lastUnit && gameCount > gameCountLimit) {
emit logmsg("execeed max game limit");
require(false, "execeed max game count limit");
} else if (currentUnit != lastUnit) {
gameCount = 0;
_opera.setLastRaceTime(tokenId, block.timestamp);
}
}
gameCount = gameCount + 1;
_opera.setRaceCount(tokenId, gameCount);
emit logmsg("update racecount passed");
_opera.setGameId(tokenId, gameId);
emit logmsg("set gameid passed");
uint256 totalGameCount = _opera.getTotalRaceCount(tokenId);
_opera.uptTotalRaceCount(tokenId, totalGameCount + 1);
emit logmsg("update total race count passed");
_uptHorseInfo(horseId, gameId);
emit CreateGame(msg.sender, gameId, block.timestamp, level, types, distance, 1);
emit UptArena(msg.sender, tokenId, gameId, block.timestamp, gameCount, totalGameCount + 1);
return true;
}
// 修改马匹状态为比赛中
function _uptHorseInfo(uint256[] memory horseId, uint256 gameId) internal {
for (uint256 i = 0; i < horseId.length; i++) {
_racecourseOpera.setHorseId(gameId, horseId[i]);
}
_horseOpera1_1.setRaceIdBatch(horseId, gameId);
_horseOpera1_1.setHorseStatusBatch(horseId, _constant.getInGame());
emit StartGame(horseId, _constant.getInGame(), block.timestamp, gameId);
emit StartGameOfRace(gameId, _constant.getInGame(), block.timestamp);
}
// 批量取消比赛-用于比赛过程中服务器宕机,回退可以重新开始比赛
function cancelGame(uint256 tokenId, uint256 [] memory gameIds) public onlyProgram returns (bool){
require(gameIds.length > 0 && gameIds.length <= 256, "Cannot opera 0 and must be less than 256");
for (uint256 i = 0; i < gameIds.length; i++) {
require(_opera.checkGameId(tokenId, gameIds[i]), "The field and the records don't match");
uint256[] memory horseIds = _racecourseOpera.getHorseId(gameIds[i]);
if (horseIds.length > 0) {
// 批量修改马匹状态为报名中
_horseOpera1_1.setHorseStatusBatch(horseIds, _constant.getSigning());
_horseOpera1_1.setRaceIdBatch(horseIds, 0);
emit CancelGameOfHorse(horseIds, _constant.getSigning(), block.timestamp, 0);
}
_racecourseOpera.delHorseId(gameIds[i]);
}
emit CancelGame(gameIds, 1, block.timestamp);
uint256 gameCount = _opera.getRaceCount(tokenId);
_opera.setRaceCount(tokenId, gameCount - 1);
uint256 totalGameCount = _opera.getTotalRaceCount(tokenId);
_opera.uptTotalRaceCount(tokenId, totalGameCount - 1);
emit CancelGameOfArena(msg.sender, tokenId, gameIds, block.timestamp, gameCount - 1, totalGameCount - 1);
return true;
}
function _check(uint256 tokenId, uint256[] memory horseId) internal {
for (uint256 i = 0; i < horseId.length; i++) {
require(_opera.checkHorseId(tokenId, horseId[i]), "Abnormal state");
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../Interface/IERC721Token.sol";
import "../Interface/IERC721Attr.sol";
import "../Interface/ICoin.sol";
import "../Interface/ICoin721.sol";
import "../Interface/IHorseEquipOpera.sol";
import "../Interface/IConstant.sol";
import "./Auth.sol";
import "hardhat/console.sol";
interface IHorseRaceOpera {
function setHeadWearId(uint256 tokenId, uint256 headWearId) external returns (bool);
function setArmorId(uint256 tokenId, uint256 armorId) external returns (bool);
function setPonytailId(uint256 tokenId, uint256 ponytailId) external returns (bool);
function setHoofId(uint256 tokenId, uint256 hoofId) external returns (bool);
}
contract HorseEquipContract is Admin {
using Math for uint256;
ICoin private _coin;
ICoin721 private _coin721;
IHorseEquipOpera private _opera;
IHorseRaceOpera private _opera1_1;
IERC721Token private _horseEquipToken;
address private _feeAccount;
IConstant private _constant; // 常量合约地址
event MintEquip(address account, uint256 tokenId, uint256 time, address to, uint256 types, uint256 style, uint256 status);
event Sell(address account, uint256 tokenId, uint256 kind, uint256 coin, uint256 price, uint256 time);
event CancelSell(address account, uint256 tokenId, uint256 status, uint256 time);
event Buy(address account, uint256 tokenId, uint256 status);
event UnloadEquip(address account, uint256 tokenId, uint256 status);
event UnloadEquipOfHorse(address account, uint256 horseId, uint256 types, uint256 status);
event EquipTransfer(address from, address to, uint256 tokenId, uint256 time);
modifier checkSellAuth(uint256 tokenId) {
require(_horseEquipToken.ownerOf(tokenId) == msg.sender, "only owner can do it!");
_;
}
modifier senderIsToken() {
require(msg.sender == address(_horseEquipToken), "only token contract can do it");
_;
}
function initialize() public initializer {
admin_initialize();
}
function initHorseEquipAttrAddress(address coinAddr, address coin721Addr, address operaAddr, address horseEquipToken,
address feeAccount, address constAddr, address opera1_1) public onlyAdmin returns (bool){
_coin = ICoin(coinAddr);
_coin721 = ICoin721(coin721Addr);
_opera = IHorseEquipOpera(operaAddr);
_opera1_1 = IHorseRaceOpera(opera1_1);
_horseEquipToken = IERC721Token(horseEquipToken);
_constant = IConstant(constAddr);
_feeAccount = feeAccount;
return true;
}
function batchMintEquip(address[] memory to, uint256[] memory equip_types, uint256[] memory equip_style) public onlyAdmin {
require(to.length == equip_types.length && to.length == equip_style.length, "invalid param length");
require(to.length <= 100, "param length need little than 100");
for(uint i = 0; i < to.length; i++) {
mintEquip(to[i], equip_types[i], equip_style[i]);
}
}
function mintEquip(address to, uint256 equip_types, uint256 equip_style) public onlyAdmin returns (uint256) {
uint256 tokenId = _horseEquipToken.mint(to);
_opera.setEquipTypes(tokenId, equip_types);
_opera.setEquipStyle(tokenId, equip_style);
_opera.setEquipStatus(tokenId, 0);
emit MintEquip(msg.sender, tokenId, block.timestamp, to, equip_types, equip_style, 0);
return tokenId;
}
function buy(uint256 coin, uint256 tokenId) public {
address owner = _opera.getHorseEquipLastOwner(tokenId);
require(owner != msg.sender, "Not allowed to purchase own orders!");
uint256 status = _opera.getHorseEquipStatus(tokenId);
require(status == 1, "This token is not selling!");
uint256 coinType = _opera.getHorseEquipCoin(tokenId);
require(coinType == coin, "This coin is not selling!");
uint256 price = _opera.getHorseEquipPrice(tokenId);
uint256 discount = _opera.getHorseEquipDiscount(tokenId);
uint256 real_dis = discount.max(_constant.getMinDiscountOfEquip());
uint256 real_price = price * (real_dis) / (10000);
// 购买者转给coin合约
_coin.safeTransferFrom(coinType, msg.sender, address(_coin), real_price);
_buy(tokenId, coin, owner, msg.sender, real_price);
_opera.setEquipLastPrice(tokenId, price);
_opera.setEquipStatus(tokenId, 0);
emit Buy(msg.sender, tokenId, 0);
}
function batchSellEquip(uint256[] memory tokenId, uint256[] memory coin, uint256[] memory price) public {
require(coin.length == price.length && coin.length == tokenId.length, "invalid param length");
require(tokenId.length < 100, "param length need little than 100");
for(uint i = 0; i < tokenId.length; i++) {
sellOne(coin[i], price[i], tokenId[i]);
}
}
function batchSellEquipOnePrice(uint256[] memory tokenId, uint256 coin, uint256 price) public {
require(tokenId.length < 100, "param length need little than 100");
for(uint i = 0; i < tokenId.length; i++) {
sellOne(coin, price, tokenId[i]);
}
}
function sellOne(
uint256 coin,
uint256 price,
uint256 tokenId
) public checkSellAuth(tokenId) {
uint256 status = _opera.getHorseEquipStatus(tokenId);
require(status == 0, "Equipment must be in a backpack to be sold");
uint256 lastOperaTime = _opera.getLastOperaTime(tokenId);
uint256 spacing = block.timestamp - (lastOperaTime);
require(spacing >= _constant.getMinSpacing(), "The minimum interval is not met, please operate later");
_sellOne(msg.sender, _constant.getOnSell(), coin, price, _constant.getMinDiscountOfEquip(), _constant.getMaxRewardOfEquip(), tokenId);
}
function cancelSell(uint256 tokenId) public returns (bool) {
uint256 status = _opera.getHorseEquipStatus(tokenId);
require(status == 1, "Equipment not for sale");
uint256 lastOperaTime = _opera.getLastOperaTime(tokenId);
uint256 spacing = block.timestamp - (lastOperaTime);
require(spacing >= _constant.getMinSpacing(), "The minimum interval is not met, please operate later");
address lastOwner = _opera.getHorseEquipLastOwner(tokenId);
require(lastOwner == msg.sender, "Only owner can do it!");
_coin721.safeTransferFrom(address(_horseEquipToken),address(_coin721), lastOwner, tokenId);
//出售价格设置为0
_opera.setEquipPrice(tokenId, 0);
_opera.setEquipStatus(tokenId, 0);
emit CancelSell(msg.sender, tokenId, 0, block.timestamp);
return true;
}
function _sellOne(
address from,
uint256 status,
uint256 coin,
uint256 price,
uint256 discount,
uint256 reward,
uint256 tokenId
) internal {
_horseEquipToken.safeTransferFrom(from, address(_coin721), tokenId);
_opera.setEquipPrice(tokenId, price);
_opera.setEquipStatus(tokenId, status);
_opera.setEquipDis(tokenId, discount);
_opera.setEquipReward(tokenId, reward);
_opera.setEquipCoin(tokenId, coin);
_opera.setEquipLastOwner(tokenId, from);
_opera.setLastOperaTime2(tokenId);
emit Sell(from, tokenId, status, coin, price, block.timestamp);
}
function _buy(
uint256 tokenId,
uint256 coin,
address from, // 这里是出售者地址
address to,
uint256 real_price
) internal {
uint256 fee_to_pay = real_price * (_constant.getFeeRateOfEquip()) / (10000);
// transfer the handling fee to the set handling fee account
_coin.safeTransfer(coin, _feeAccount, fee_to_pay);
// transfer the benefits to the account of the transaction initiator
_coin.safeTransfer(coin, from, real_price - (fee_to_pay));
_coin721.safeTransferFrom(address(_horseEquipToken), address(_coin721), to, tokenId);
}
function _unloadEquip(uint256 tokenid, uint256 horseid) internal returns (bool) {
uint256 equipType = _opera.getHorseEquipTypes(tokenid);
bool result = false;
if (equipType == 1) {
result = true;
_opera1_1.setHeadWearId(horseid, 0);
emit UnloadEquipOfHorse(msg.sender, horseid, 1, 0);
} else if (equipType == 2) {
result = true;
_opera1_1.setArmorId(horseid, 0);
emit UnloadEquipOfHorse(msg.sender, horseid, 2, 0);
} else if (equipType == 3) {
result = true;
_opera1_1.setPonytailId(horseid, 0);
emit UnloadEquipOfHorse(msg.sender, horseid, 3, 0);
} else {
result = true;
_opera1_1.setHoofId(horseid, 0);
emit UnloadEquipOfHorse(msg.sender, horseid, 4, 0);
}
return result;
}
// 一键卸载装备
function unloadEquip(uint256[] memory tokenIds, uint256 horseId) public returns (bool) {
require(tokenIds.length <= 256, "Invalid parameters");
for (uint256 i = 0; i < tokenIds.length; i++) {
require(_horseEquipToken.ownerOf(tokenIds[i]) == msg.sender, "only owner can do it!");
uint256 status = _opera.getHorseEquipStatus(tokenIds[i]);
require(status == 2, "Abnormal equipment status");
uint256 hId = _opera.getEquipOfHorseId(tokenIds[i]);
require(hId == horseId, "Horses and decorations are an unusual match");
_unloadEquip(tokenIds[i], horseId);
emit UnloadEquip(msg.sender, tokenIds[i], 0);
}
_opera.setEquipStatusBatch(tokenIds, 0);
return true;
}
function beforeTransfer(address from, address to, uint256 tokenId) public senderIsToken returns (bool) {
// no need more handler.
if (_constant.isOfficialContract(from) || _constant.isOfficialContract(to)) {
//console.log("no need handler for equip extra contract transfer");
} else {
uint256 status = _opera.getHorseEquipStatus(tokenId);
if (status == 2) {
// 在装备中,卸载装备
uint256 hId = _opera.getEquipOfHorseId(tokenId);
_unloadEquip(tokenId, hId);
}
}
return true;
}
function afterTransfer(address from, address to, uint256 tokenId) public senderIsToken returns (bool) {
// no need more handler.
// no need more handler.
if (_constant.isOfficialContract(from) || _constant.isOfficialContract(to)) {
//console.log("no need handler for equip extra contract transfer");
} else {
console.log("emit event equiptransfer");
emit EquipTransfer(from, to, tokenId,block.timestamp);
}
return true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../Interface/IERC721Attr.sol";
import "../Interface/IERC721Token.sol";
import "../library/Bytes.sol";
import "../library/Uint256.sol";
import "../library/String.sol";
import "../library/Address.sol";
import "./Auth.sol";
contract HorseEquipAttrOperaContract is Program {
using Uint256 for uint256;
using String for string;
using Address for address;
using Bytes for bytes;
IERC721Attr private _horseEquipAttrAddress;
IERC721Token private _horseEquipTokenAddress;
string public _horseEquipTypes;
string public _horseEquipStyle;
string public _horseEquipStatus;
string public _horseEquipPrice; // 出售价格
string public _horseEquipOfUid;
string public _horseEquipOfHorseId;
string public _horseEquipDiscount;
string public _horseEquipReward;
string public _horseEquipCoin;
string public _horseEquipLastOwner; // 最后一次操作者
string public _horseEquipLastPrice; // 最后一次成交价格
string public _lastOperaTime; // 最后操作时间
modifier checkEquipTypesValue(uint256 equip_types) {
if (equip_types == 1 || equip_types == 2 || equip_types == 3 || equip_types == 4) {
require(true, "Legal field value");
} else {
require(false, "Invalid field value");
}
_;
}
modifier checkEquipStyleValue(uint256 equip_style) {
if (equip_style == 1 || equip_style == 2 || equip_style == 3 || equip_style == 4 || equip_style == 5) {
require(true, "Legal field value");
} else {
require(false, "Invalid field value");
}
_;
}
modifier checkSellAuth(uint256 tokenId) {
require(_horseEquipTokenAddress.ownerOf(tokenId) == msg.sender, "only owner can do it!");
_;
}
function initialize() public initializer {
program_initialize();
_horseEquipTypes = "horseEquipTypes";
_horseEquipStyle = "horseEquipStyle";
_horseEquipStatus = "horseEquipStatus";
_horseEquipPrice = "horseEquipPrice"; // 出售价格
_horseEquipOfUid = "horseEquipOfUid";
_horseEquipOfHorseId = "horseEquipOfHorseId";
_horseEquipDiscount = "horseEquipDiscount";
_horseEquipReward = "horseEquipReward";
_horseEquipCoin = "horseEquipCoin";
_horseEquipLastOwner = "horseEquipLastOwner"; // 最后一次操作者
_horseEquipLastPrice = "horseEquipLastPrice"; // 最后一次成交价格
_lastOperaTime = "lastOperaTime"; // 最后操作时间
}
function init(address equipAttrAddress, address horseEquipToken) public onlyAdmin returns (bool) {
_horseEquipAttrAddress = IERC721Attr(equipAttrAddress);
_horseEquipTokenAddress = IERC721Token(horseEquipToken);
return true;
}
function setEquipStatus(uint256 tokenId, uint256 status) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _horseEquipStatus, status.Uint256ToBytes());
return result;
}
function setEquipStatusBatch(uint256[] memory tokenIds, uint256 status) public onlyProgram returns (bool) {
require(tokenIds.length <= 256, "Invalid parameters");
for (uint256 i = 0; i < tokenIds.length; i++) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenIds[i], _horseEquipStatus, status.Uint256ToBytes());
require(result, "setEquipStatus error");
}
return true;
}
function setEquipTypes(uint256 tokenId, uint256 types) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _horseEquipTypes, types.Uint256ToBytes());
return result;
}
function setEquipStyle(uint256 tokenId, uint256 style) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _horseEquipStyle, style.Uint256ToBytes());
return result;
}
function setEquipPrice(uint256 tokenId, uint256 price) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _horseEquipPrice, price.Uint256ToBytes());
return result;
}
function setEquipOfHorseId(uint256 tokenId, uint256 horseId) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _horseEquipOfHorseId, horseId.Uint256ToBytes());
return result;
}
function setEquipDis(uint256 tokenId, uint256 discount) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _horseEquipDiscount, discount.Uint256ToBytes());
return result;
}
function setEquipReward(uint256 tokenId, uint256 reward) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _horseEquipReward, reward.Uint256ToBytes());
return result;
}
function setEquipCoin(uint256 tokenId, uint256 coin) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _horseEquipCoin, coin.Uint256ToBytes());
return result;
}
function setLastOperaTime1(uint256 tokenId, uint256 operaTime) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _lastOperaTime, operaTime.Uint256ToBytes());
return result;
}
function setLastOperaTime2(uint256 tokenId) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _lastOperaTime, block.timestamp.Uint256ToBytes());
return result;
}
function setEquipLastOwner(uint256 tokenId, address addr) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _horseEquipLastOwner, addr.AddressToBytes());
return result;
}
function setEquipLastPrice(uint256 tokenId, uint256 price) public onlyProgram returns (bool) {
bool result = _horseEquipAttrAddress.setValues(address(_horseEquipTokenAddress), tokenId, _horseEquipLastPrice, price.Uint256ToBytes());
return result;
}
function getLastOperaTime(uint256 tokenId) public view returns (uint256){
bytes memory timeBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _lastOperaTime);
return timeBytes.BytesToUint256();
}
function getHorseEquipLastOwner(uint256 tokenId) public view returns (address){
bytes memory ownerBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _horseEquipLastOwner);
return ownerBytes.BytesToAddress();
}
function getHorseEquipStatus(uint256 tokenId) public view returns (uint256){
bytes memory statusBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _horseEquipStatus);
return statusBytes.BytesToUint256();
}
function getHorseEquipCoin(uint256 tokenId) public view returns (uint256){
bytes memory coinBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _horseEquipCoin);
return coinBytes.BytesToUint256();
}
function getHorseEquipPrice(uint256 tokenId) public view returns (uint256){
bytes memory priceBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _horseEquipPrice);
return priceBytes.BytesToUint256();
}
function getHorseEquipDiscount(uint256 tokenId) public view returns (uint256){
bytes memory DisBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _horseEquipDiscount);
return DisBytes.BytesToUint256();
}
function getHorseEquipReward(uint256 tokenId) public view returns (uint256){
bytes memory rewBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _horseEquipReward);
return rewBytes.BytesToUint256();
}
function getHorseEquipTypes(uint256 tokenId) public view returns (uint256){
bytes memory typesBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _horseEquipTypes);
return typesBytes.BytesToUint256();
}
function getHorseEquipStyle(uint256 tokenId) public view returns (uint256){
bytes memory styleBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _horseEquipStyle);
return styleBytes.BytesToUint256();
}
function getHorseEquipLastPrice(uint256 tokenId) public view returns (uint256){
bytes memory priceBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _horseEquipLastPrice);
return priceBytes.BytesToUint256();
}
function getEquipOfHorseId(uint256 tokenId) public view returns (uint256){
bytes memory idBytes = _horseEquipAttrAddress.getValue(address(_horseEquipTokenAddress), tokenId, _horseEquipOfHorseId);
return idBytes.BytesToUint256();
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../Interface/BaseInterface.sol";
import "../Interface/ICoin.sol";
import "../Interface/IConstant.sol";
import "../Interface/IHorseRaceOpera.sol";
import "./Auth.sol";
import "../library/Bytes.sol";
import "hardhat/console.sol";
contract HorseRelation is Program {
IHorseRaceOpera private _op;
function _horse_relation_init() internal onlyInitializing {
program_initialize();
}
function getHorseOp() internal virtual view returns(IHorseRaceOpera) {
return _op;
}
function setHorseOp(IHorseRaceOpera op_) public onlyAdmin {
_op = op_;
}
function getAncestors(uint256 childId, uint256[] memory ancestors, uint256 level) public view returns (uint256[] memory) {
uint256 fatherId = getHorseOp().getFather(childId);
uint256 motherId = getHorseOp().getMother(childId);
uint256 len = ancestors.length;
if (fatherId > 0) {
len++;
}
if (motherId > 0) {
len++;
}
uint256[] memory lst = new uint256[](len);
uint256 i = 0;
for (; i < ancestors.length; i++) {
lst[i] = ancestors[i];
}
if (fatherId > 0) {
lst[i++] = fatherId;
}
if (motherId > 0) {
lst[i++] = motherId;
}
if (fatherId > 0 && level > 1) {
lst = getAncestors(fatherId, lst, level - 1);
}
if (motherId > 0 && level > 1) {
lst = getAncestors(motherId, lst, level - 1);
}
return lst;
}
function isKinship(uint256 horseId, uint256 stallId) public view returns(bool) {
uint256[] memory lst = new uint256[](0);
uint256[] memory lstMare = getAncestors(horseId, lst, 2);
uint256[] memory lstStall = getAncestors(stallId, lst, 2);
for (uint256 i = 0; i < lstMare.length; i++) {
if (lstMare[i] == stallId) {
return true;
}
for (uint256 j = 0; j < lstStall.length; j++) {
if (lstStall[j] == lstMare[i]) {
return true;
}
}
}
for (uint256 i = 0; i < lstStall.length; i++) {
if (lstStall[i] == horseId) {
return true;
}
}
return false;
}
}
contract HorseRaceContract is HorseRelation {
using Math for uint256;
using Bytes for bytes;
ICoin private _coin;
IHorseRaceOpera private _opera1;
IHorseRaceOpera private _opera1_1;
IHorseRaceOpera private _opera2_1;
IHorseRaceOpera private _opera2;
IERC721TokenMinable private _horseTokenAddress;
address private _feeAccount;
IConstant private _constant; // 常量合约地址
event Breeding(address account, uint256 tokenId, uint256 stallId, uint256 newHorseId, string name,
uint256 generationScore, uint256 gender, uint256 integralTime, uint256 energyTime, uint256 status);
event Breeding1(uint256 newHorseId, uint256 time, string color, string gene,
uint256 mGene, uint256 sGene, uint256 traValue, uint256 energy, uint256 grade, uint256 integral);
event BreedingOfHorse(uint256 horseId, uint256 time, uint256 count);
modifier checkOwner(uint256 tokenId) {
require(_horseTokenAddress.ownerOf(tokenId) == msg.sender, "only owner can do it!");
_;
}
modifier checkSign(string memory name, bytes memory sign) {
require(sign.Decode(name) == _constant.getAccount(), "Signature verification failure");
_;
}
function initialize() public initializer {
_horse_relation_init();
}
function getHorseOp() internal override view returns(IHorseRaceOpera) {
return _opera2;
}
function initHorseRaceAttrAddress(
address operaAddr1, address operaAddr1_1, address tokenAddr,
address operaAddr2, address operaAddr2_1,
address coinAddress, address constantAddr, address feeAccount) public onlyAdmin returns (bool){
_opera1 = IHorseRaceOpera(operaAddr1);
_opera1_1 = IHorseRaceOpera(operaAddr1_1);
_opera2 = IHorseRaceOpera(operaAddr2);
_opera2_1 = IHorseRaceOpera(operaAddr2_1);
_horseTokenAddress = IERC721TokenMinable(tokenAddr);
_coin = ICoin(coinAddress);
_constant = IConstant(constantAddr);
_feeAccount = feeAccount;
return true;
}
function _makeProperty(string memory name, string memory style, string memory gene, string memory color, uint256 gender) internal pure returns (string memory) {
if(gender == 0) {
return string(abi.encodePacked(name, ",", style, ",", gene, ",", color, ",", "0"));
}
return string(abi.encodePacked(name, ",", style, ",", gene, ",", color, ",", "1"));
}
// 繁殖
function breeding(uint256 horseId, uint256 stallId, uint256 coinType, string memory name, bytes memory sign) public
checkOwner(horseId) checkSign(name, sign) {
require(_opera2_1.getHorseRaceStatus(horseId) == 0, "Horses must be idle!");
require(_opera2.getHorseGender(horseId) == 0, "Horse must be a mare!");
require(!isKinship(horseId, stallId), "Horse and stall can't be kinship!");
uint256 status = _opera2_1.getHorseRaceStatus(stallId);
if (status == 0) {
require(_horseTokenAddress.ownerOf(stallId) == msg.sender, "only owner can do it!");
require(_opera2.getHorseGender(stallId) == 1, "The horse must be a stallion");
} else {
require(_opera2_1.getHorseRaceStatus(stallId) == 2, "Horses must be in breeding condition!");
}
_checkBreedTime(horseId, stallId);
// 繁殖费用
_breCost(stallId, coinType, status);
string memory newGene;
{
// 基因遗传
string memory motherGene = _opera2.getHorseGene(horseId);
string memory fatherGene = _opera2.getHorseGene(stallId);
newGene = _geneBreeding(bytes(motherGene), bytes(fatherGene));
}
string memory newColor = _colorRandom();
uint256 gender = _genderRandom();
uint256 newHorseId;
{
string memory property = _makeProperty(name, "BRED_HORSE", newGene, newColor, gender);
newHorseId = _horseTokenAddress.mint(msg.sender, bytes(property));
}
_initHorse(horseId, stallId, newHorseId, name, newGene, newColor, gender);
}
function _checkBreedTime(uint256 horseId, uint256 stallId) internal {
uint256 current = block.timestamp;
uint256 birthDay = _opera2.getBirthDay(horseId);
uint256 growthTime = current - (birthDay);
require(growthTime > _constant.getMinMatureTime(), "The horse is immature");
uint256 staGrowthTime = current - (_opera2.getBirthDay(stallId));
require(staGrowthTime > _constant.getMinMatureTime(), "The horse is immature");
uint256 mareBrTime = _opera2.getBreedTime(horseId);
uint256 staBreedTime = _opera2.getBreedTime(stallId);
uint256 mareBrSpaTime = current - (mareBrTime);
uint256 staBrSpaTime = current - (staBreedTime);
require(mareBrSpaTime > _constant.getMinMareBrSpaTime() && staBrSpaTime > _constant.getMinStaBrSpaTime(), "Breeding cooldown time cannot breed multiple times");
}
function _breCost(uint256 stallId, uint256 coin, uint256 status) internal returns (bool){
if (status == 2) {
uint256 price = _opera2_1.getHorseRacePrice(stallId);
uint256 coinType = _opera2_1.getHorseRaceCoin(stallId);
require(coin == coinType, "CoinType is not what users need");
address owner = _opera2_1.getHorseRaceLastOwner(stallId);
uint256 real_price = price * (_constant.getBreDiscount()) / (10000);
// 种马费用
_coin.safeTransferFrom(coinType, msg.sender, address(_coin), price);
_coin.safeTransfer(coinType, owner, real_price);
}
// 额外支付费用
_coin.safeTransferFrom1(_constant.getBreCoin1(), msg.sender, address(_coin), _constant.getBreCoin1Amount());
_coin.safeTransferFrom1(_constant.getBreCoin2(), msg.sender, address(_coin), _constant.getBreCoin2Amount());
return true;
}
// 基因算法、颜色
function _initHorse(uint256 horseId, uint256 stallId, uint256 newHorseId, string memory name,
string memory newGene, string memory newColor, uint256 gender) internal {
uint256 current = block.timestamp;
_opera1.setHorseName(newHorseId, name);
_opera1.setHorseGender(newHorseId, gender); // 性别
_opera1.setHorseFatherId(newHorseId, stallId);
_opera1.setHorseMotherId(newHorseId, horseId);
uint256 mGene = _opera2.getHorseMGene(horseId).max(_opera2.getHorseMGene(stallId)); // 主代
mGene = mGene + 1;
uint256 sGene = _opera2.getHorseMGene(horseId).min(_opera2.getHorseMGene(stallId)); // 从代
{
uint256 geneSc1 = _opera2.getHorseGeneSC(horseId); // 迭代系数
uint256 geneSc2 = _opera2.getHorseGeneSC(stallId);
uint256 geneSc = ((geneSc1 * _constant.getBreCoefficient()) / 10000 + (geneSc2 * _constant.getBreCoefficient()) / 10000) / 2;
_opera1.setHorseGeneSc(newHorseId, geneSc);
_opera1.setHorseBreedTime(horseId, current);
_opera1.setHorseBreedTime(stallId, current);
_opera1.setHorseBreedCount(horseId);
_opera1.setHorseBreedCount(stallId);
emit Breeding(msg.sender, horseId, stallId, newHorseId, name, geneSc, gender, current, current, _constant.getResting());
}
_initGrade(horseId, stallId, newHorseId, mGene, sGene, current, newGene, newColor);
emit BreedingOfHorse(horseId, current, _opera2.getBreedCount(horseId));
emit BreedingOfHorse(stallId, current, _opera2.getBreedCount(stallId));
}
function _geneRandom(uint256 offset) internal view returns (uint8) {
bytes32 _hash = blockhash(block.number);
uint8 index = uint8(_hash[offset]) % 4;
return index;
}
function _genderRandom() internal view returns (uint256){
uint256 gender = block.number%2;
return gender;
}
function _colorRandom() internal view returns (string memory) {
// 马匹颜色遗传
string memory newColor = "FFFFFFFF";
{
// 初始颜色值 随机选择,链上增加。
uint32 count = _constant.getInitColorsCount();
if (count > 0) {
bytes32 _hash = blockhash(block.number);
uint8 index = uint8(_hash[0]) % uint8(count);
newColor = _constant.getInitColors(index);
}
}
return newColor;
}
function _geneBreeding(bytes memory mother, bytes memory father) internal view returns (string memory ) {
require(bytes(mother).length == bytes(father).length, "gene length must equal");
uint256 offset = 0;
bytes memory newgene = new bytes(mother.length);
for(offset = 0; offset < mother.length; offset+=2) {
uint8 random = _geneRandom(offset);
if (random == 0) {
newgene[offset] = mother[offset];
newgene[offset+1] = father[offset];
} else if (random == 1) {
newgene[offset] = mother[offset + 1 ];
newgene[offset+1] = father[offset];
} else if (random == 2) {
newgene[offset] = mother[offset ];
newgene[offset+1] = father[offset + 1];
} else if (random == 3) {
newgene[offset] = mother[offset + 1 ];
newgene[offset+1] = father[offset + 1];
}
if (newgene[offset] < newgene[offset+1]) {
bytes1 p = newgene[offset];
newgene[offset] = newgene[offset+1];
newgene[offset+1] = p;
}
}
return string(newgene);
}
function _initGrade(uint256, uint256, uint256 newHorseId, uint256 mGene, uint256 sGene,
uint256 current, string memory newGene, string memory newColor) internal {
uint256 grade = _constant.getInitGrade(); // 设置为初始值
uint256 integral = _constant.getInitIntegral(); // 设置为初始值
_opera1_1.setGrade(newHorseId, grade);
_opera1.setHorseGradeSc(newHorseId, integral);
_opera1.setHorseBirthDay(newHorseId, current);
_opera1.setHorseMGene(newHorseId, mGene);
_opera1.setHorseSGene(newHorseId, sGene);
_opera1.setHorseTraValue(newHorseId, _constant.getMinTraValue());
_opera1.setHorseEnergy(newHorseId, _constant.getMaxEnergy());
_opera1.setHorseGene(newHorseId, newGene);
_opera1.setHorseColor(newHorseId, newColor);
emit Breeding1(newHorseId, current, newColor, newGene, mGene, sGene, _constant.getMinTraValue(),
_constant.getMaxEnergy(), grade, integral);
}
function batchMintHorse(
string[] memory name,
string[] memory style,
uint256 [] memory mainGeneration,
uint256 [] memory slaveGeneration,
uint256 [] memory generationScore,
uint256 [] memory gender,
string [] memory color,
string [] memory gene,
address [] memory to
) public onlyAdmin returns (uint256[] memory){
require(name.length == style.length && name.length == mainGeneration.length && name.length == slaveGeneration.length &&
name.length == generationScore.length && name.length == gender.length && name.length == color.length &&
name.length == gene.length && name.length == to.length);
uint256[] memory newids = new uint256[](name.length);
for(uint j = 0; j < name.length; j++) {
string memory property = _makeProperty(name[j], style[j], gene[j], color[j], gender[j]);
uint256 horseId = _horseTokenAddress.mint(to[j], bytes(property));
_mintOne(name[j], mainGeneration[j], slaveGeneration[j], generationScore[j], gender[j], color[j],
gene[j], horseId, to[j]);
newids[j] = horseId;
}
return newids;
}
function mintHorse(
string memory name,
string memory style,
uint256 mainGeneration,
uint256 slaveGeneration,
uint256 generationScore,
uint256 gender,
string memory color,
string memory gene,
address to
) public onlyAdmin returns (uint256){
string memory property = _makeProperty(name, style, gene, color, gender);
uint256 horseId = _horseTokenAddress.mint(to, bytes(property));
_mintOne(name, mainGeneration, slaveGeneration, generationScore, gender, color, gene, horseId, to);
console.log("mint horse with id :", horseId);
return horseId;
}
function _mintOne(
string memory name,
uint256 mainGeneration,
uint256 slaveGeneration,
uint256 generationScore,
uint256 gender,
string memory color,
string memory gene,
uint256 horseId,
address to) internal {
uint256 current = block.timestamp;
_opera1.setHorseName(horseId, name);
_opera1.setHorseMGene(horseId, mainGeneration);
_opera1.setHorseSGene(horseId, slaveGeneration);
_opera1.setHorseGeneSc(horseId, generationScore);
_opera1.setHorseGender(horseId, gender);
_opera1.setHorseColor(horseId, color);
_opera1.setHorseGene(horseId, gene);
_opera1.setHorseBirthDay(horseId, current);
_opera1.setHorseTraValue(horseId, _constant.getMinTraValue());
_opera1.setHorseGradeSc(horseId, _constant.getInitIntegral());
_opera1_1.setGrade(horseId, _constant.getInitGrade());
_opera1.setHorseEnergy(horseId, _constant.getMaxEnergy());
_opera1.setHorseNameUptCount(horseId, _constant.getModifyNameTimes());
emit Breeding(to, 0, 0, horseId, name, generationScore, gender, current, current, _constant.getResting());
emit Breeding1(horseId, current, color, gene, mainGeneration, slaveGeneration, _constant.getMinTraValue(),
_constant.getMaxEnergy(), _constant.getInitGrade(), _constant.getInitIntegral());
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Bytes.sol";
import "../library/Uint256.sol";
import "../library/String.sol";
import "./Auth.sol";
import "../Interface/IERC721Token.sol";
import "../Interface/IERC721Attr.sol";
contract HorseRaceAttrOpera1 is Program {
using Uint256 for uint256;
using String for string;
using Bytes for bytes;
IERC721Attr private _horseRaceAttrAddress;
IERC721Token private _horseRaceTokenAddress;
// todo: vicotor check if it need move to initialize.
string public _horseRaceName ;//昵称 string
string public _nameUptCount ;//剩余改名次数 uint256
string public _birthDay ;//出生日期 uint256
string public _mainGeneration ; // 主代 uint256
string public _slaveGeneration ;//从代 uint256
string public _generationScore ;//迭代系数 uint256
string public _gender ;//性别 uint256
string public _color ;//皮肤颜色 uint256
string public _gene ;//基因综合评分 uint256
string public _gripGene ;//抓地基因
string public _accGene ;//加速基因
string public _endGene ;//耐力基因
string public _speedGene ;//速度基因
string public _turnToGene ;//转向基因
string public _controlGene ;//操控基因
string public _trainingValue ;//训练值 uint256
string public _trainingTime ;//训练时间 uint256
string public _useTraTime ;//扣除训练值时间 uint256
string public _energy ;//能量 uint256
string public _energyUpdateTime ;//能量恢复时间 uint256
string public _gradeScore ;//评分,参加比赛得到 uint256
string public _gradeScoreMark ;// 评分正负标记。1 正, 2负 uint256
string public _gradeIntegral ;//积分,参加大奖赛得到 uint256
string public _raceScoreUpdateTime ; //积分最后一次更新时间 uint256
string public _father ; //父资产唯一id uint256
string public _mother ; //母资产唯一id uint256
string public _breedCount ; //繁殖总次数 uint256
string public _breedTime ; //最近一次繁殖时间 uint256
string public _gradeIntegralYear ; // 本年度增涨的积分数量
string public _gradeIntegralYearTime ; // 当前记录年度时间
string public _gradeIntegralMonth ; // 本月增涨的积分数量
string public _gradeIntegralMonthTime ; // 当前记录月度时间
string public _gradeIntegralWeek ; // 本周增涨的积分数量
string public _gradeIntegralWeekTime ; // 当前记录周时间
modifier checkGenderValue(uint256 gender) {
if (gender == 0 || gender == 1) {
require(true, "Legal field value");
} else {
require(false, "Invalid field value");
}
_;
}
modifier checkStatusValue(uint256 status) {
if (status == 1 || status == 2 || status == 3 || status == 4 || status == 0) {
require(true, "Legal field value");
} else {
require(false, "Invalid field value");
}
_;
}
function initialize() public initializer {
program_initialize();
_horseRaceName = "horseRaceName";//昵称 string
_nameUptCount = "nameUptCount";//剩余改名次数 uint256
_birthDay = "birthDay";//出生日期 uint256
_mainGeneration = "mainGeneration"; // 主代 uint256
_slaveGeneration = "slaveGeneration";//从代 uint256
_generationScore = "generationScore";//迭代系数 uint256
_gender = "gender";//性别 uint256
_color = "color";//皮肤颜色 uint256
_gene = "gene";//基因综合评分 uint256
_gripGene = "gripGene";//抓地基因
_accGene = "accGene";//加速基因
_endGene = "endGene";//耐力基因
_speedGene = "speedGene";//速度基因
_turnToGene = "turnToGene";//转向基因
_controlGene = "controlGene";//操控基因
_trainingValue = "trainingValue";//训练值 uint256
_trainingTime = "trainingTime";//训练时间 uint256
_useTraTime = "useTraTime";//扣除训练值时间 uint256
_energy = "energy";//能量 uint256
_energyUpdateTime = "energyUpdateTime";//能量恢复时间 uint256
_gradeScore = "gradeScore";//评分,参加比赛得到 uint256
_gradeScoreMark = "gradeScoreMark";// 评分正负标记。1 正, 2负 uint256
_gradeIntegral = "gradeIntegral";//积分,参加大奖赛得到 uint256
_raceScoreUpdateTime = "raceScoreUpdateTime"; //积分最后一次更新时间 uint256
_father = "father"; //父资产唯一id uint256
_mother = "mother"; //母资产唯一id uint256
_breedCount = "breedCount"; //繁殖总次数 uint256
_breedTime = "breedTime"; //最近一次繁殖时间 uint256
_gradeIntegralYear = "gradeIntegralYear"; // 本年度增涨的积分数量
_gradeIntegralYearTime = "gradeIntegralYearTime"; // 当前记录年度时间
_gradeIntegralMonth = "gradeIntegralMonth"; // 本月增涨的积分数量
_gradeIntegralMonthTime = "gradeIntegralMonthTime"; // 当前记录月度时间
_gradeIntegralWeek = "gradeIntegralWeek"; // 本周增涨的积分数量
_gradeIntegralWeekTime = "gradeIntegralWeekTime"; // 当前记录周时间
}
function init(address raceAttrAddress, address horseRaceToken) public onlyAdmin returns (bool) {
_horseRaceAttrAddress = IERC721Attr(raceAttrAddress);
_horseRaceTokenAddress = IERC721Token(horseRaceToken);
return true;
}
function setHorseName(uint256 tokenId, string memory name) public onlyProgram returns (bool) {
bytes memory nameBytes = name.StringToBytes();
bool boo = _horseRaceAttrAddress.getUniques(address(_horseRaceTokenAddress), _horseRaceName, nameBytes);
require(!boo, "Name already used");
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _horseRaceName, nameBytes);
_horseRaceAttrAddress.setUniques(address(_horseRaceTokenAddress), _horseRaceName, nameBytes);
return result;
}
function setHorseNameUptCount(uint256 tokenId, uint256 count) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _nameUptCount, count.Uint256ToBytes());
return result;
}
function setHorseBirthDay(uint256 tokenId, uint256 birthDay) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _birthDay, birthDay.Uint256ToBytes());
return result;
}
// horse mainGeneration
function setHorseMGene(uint256 tokenId, uint256 mainGeneration) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _mainGeneration, mainGeneration.Uint256ToBytes());
return result;
}
function setHorseSGene(uint256 tokenId, uint256 slaveGeneration) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _slaveGeneration, slaveGeneration.Uint256ToBytes());
return result;
}
// 迭代系数
function setHorseGeneSc(uint256 tokenId, uint256 generationScore) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _generationScore, generationScore.Uint256ToBytes());
return result;
}
// 性别
function setHorseGender(uint256 tokenId, uint256 gender) public onlyProgram checkGenderValue(gender) returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gender, gender.Uint256ToBytes());
return result;
}
// 皮肤颜色
function setHorseColor(uint256 tokenId, string memory color) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _color, bytes(color));
return result;
}
//基因综合评分
function setHorseGene(uint256 tokenId, string memory gene) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gene, bytes(gene));
return result;
}
function setHorseGripGene(uint256 tokenId, string memory gene) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gripGene, bytes(gene));
return result;
}
function setHorseAccGene(uint256 tokenId, string memory gene) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _accGene, bytes(gene));
return result;
}
function setHorseEndGene(uint256 tokenId, string memory gene) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _endGene, bytes(gene));
return result;
}
function setHorseSpdGene(uint256 tokenId, string memory gene) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _speedGene, bytes(gene));
return result;
}
function setHorseTurnGene(uint256 tokenId, string memory gene) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _turnToGene, bytes(gene));
return result;
}
function setHorseContGene(uint256 tokenId, string memory gene) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _controlGene, bytes(gene));
return result;
}
// 设置训练值
function setHorseTraValue(uint256 tokenId, uint256 trainingValue) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _trainingValue, trainingValue.Uint256ToBytes());
return result;
}
// 设置训练时间
function setHorseTraTime(uint256 tokenId, uint256 trainingTime) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _trainingTime, trainingTime.Uint256ToBytes());
return result;
}
// 设置扣除训练值时间
function setUseTraTime(uint256 tokenId, uint256 trainingTime) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _useTraTime, trainingTime.Uint256ToBytes());
return result;
}
// 设置能量
function setHorseEnergy(uint256 tokenId, uint256 energy) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _energy, energy.Uint256ToBytes());
return result;
}
// 能量恢复时间
function setHorseEngTime(uint256 tokenId, uint256 energyUpdateTime) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _energyUpdateTime, energyUpdateTime.Uint256ToBytes());
return result;
}
// 马匹评分
function setHorseGradeSc(uint256 tokenId, uint256 gradeScore) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gradeScore, gradeScore.Uint256ToBytes());
return result;
}
// 马匹积分
function setHorseIntegral(uint256 tokenId, uint256 integral) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gradeIntegral, integral.Uint256ToBytes());
return result;
}
// 马匹评分正负值标记
function setHorseScoreMark(uint256 tokenId, uint256 gradeScoreMark) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gradeScoreMark, gradeScoreMark.Uint256ToBytes());
return result;
}
//积分最后一次更新时间
function setHorseScUptTime(uint256 tokenId, uint256 raceScoreUpdateTime) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _raceScoreUpdateTime, raceScoreUpdateTime.Uint256ToBytes());
return result;
}
function setHorseFatherId(uint256 tokenId, uint256 father) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _father, father.Uint256ToBytes());
return result;
}
function setHorseMotherId(uint256 tokenId, uint256 mother) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _mother, mother.Uint256ToBytes());
return result;
}
// 繁殖次数
function setHorseBreedCount(uint256 tokenId) public onlyProgram returns (bool) {
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _breedCount);
uint256 count = bytesInfo.BytesToUint256() + (1);
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _breedCount, count.Uint256ToBytes());
return result;
}
// 繁殖时间
function setHorseBreedTime(uint256 tokenId, uint256 breedTime) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _breedTime, breedTime.Uint256ToBytes());
return result;
}
// 设置
function setHorseDetailIntegral(uint256 tokenId, uint256 totalIntegral, uint256 integralYear, uint256 integralMonth, uint256 integralWeek) public onlyProgram returns (bool) {
bool r = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gradeIntegral, totalIntegral.Uint256ToBytes());
require(r,"set value failed");
r = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gradeIntegralYear, integralYear.Uint256ToBytes());
require(r,"set value failed");
r = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gradeIntegralMonth, integralMonth.Uint256ToBytes());
require(r,"set value failed");
r = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gradeIntegralWeek, integralWeek.Uint256ToBytes());
require(r,"set value failed");
return r;
}
function setHorseIntegralDate(uint256 tokenId, uint256 year, uint256 month, uint256 week) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gradeIntegralYearTime, year.Uint256ToBytes());
result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gradeIntegralMonthTime, month.Uint256ToBytes());
result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _gradeIntegralWeekTime, week.Uint256ToBytes());
return result;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Bytes.sol";
import "../library/Uint256.sol";
import "../library/String.sol";
import "./Auth.sol";
import "../Interface/IERC721Attr.sol";
import "../library/Address.sol";
contract HorseRaceAttrOpera1_1 is Program {
using Address for address;
using Uint256 for uint256;
using String for string;
using Bytes for bytes;
IERC721Attr private _horseRaceAttrAddress;
address private _horseRaceTokenAddress;
string public _headWearId ; //马头饰资产Id uint256
string public _armorId ; //马护甲资产Id uint256
string public _ponytailId ; //马尾饰资产Id uint256
string public _hoofId ; //马蹄饰资产Id uint256
string public _grade ; //马匹等级 uint256
string public _raceCount ; //参赛次数 uint256
string public _winCount ; //获赢次数 uint256
string public _raceId ; // 游戏服生成的竞赛唯一id
string public _raceType ;// 锦标赛/大奖赛/对决
string public _racecourse ;//报名比赛赛场资产唯一id
string public _distance ;//报名比赛赛程
string public _raceUpdateTime ;//报名/取消时间
string public _horseRaceStatus ;
string public _horseRaceDiscount ;
string public _horseRaceReward ;
string public _horseRaceCoin ;
string public _horseRaceLastOwner ; // 最后一次操作者
string public _horseRaceLastPrice ; // 最后一次成交价格
string public _horseRacePrice ; // 出售价格
string public _sellUpdateTime ; // 出售/取消出售时间
string public _studUpdateTime ; // 放入种马场/取消时间
modifier checkStatusValue(uint256 status) {
if (status == 1 || status == 2 || status == 3 || status == 4 || status == 0) {
require(true, "Legal field value");
} else {
require(false, "Invalid field value");
}
_;
}
modifier checkGradeValue(uint256 grade) {
if (grade == 1 || grade == 2 || grade == 3 || grade == 4 || grade == 5 || grade == 0 || grade == 999) {
require(true, "Legal field value");
} else {
require(false, "Invalid field value");
}
_;
}
function initialize() public initializer {
program_initialize();
_headWearId = "headWearId"; //马头饰资产Id uint256
_armorId = "armorId"; //马护甲资产Id uint256
_ponytailId = "ponytailId"; //马尾饰资产Id uint256
_hoofId = "hoofId"; //马蹄饰资产Id uint256
_grade = "grade"; //马匹等级 uint256
_raceCount = "raceCount"; //参赛次数 uint256
_winCount = "winCount"; //获赢次数 uint256
_raceId = "raceId"; // 游戏服生成的竞赛唯一id
_raceType = "raceType";// 锦标赛/大奖赛/对决
_racecourse = "racecourse";//报名比赛赛场资产唯一id
_distance = "distance";//报名比赛赛程
_raceUpdateTime = "raceUpdateTime";//报名/取消时间
_horseRaceStatus = "horseRaceStatus";
_horseRaceDiscount = "horseRaceDiscount";
_horseRaceReward = "horseRaceReward";
_horseRaceCoin = "horseRaceCoin";
_horseRaceLastOwner = "horseRaceLastOwner"; // 最后一次操作者
_horseRaceLastPrice = "horseRaceLastPrice"; // 最后一次成交价格
_horseRacePrice = "horseRacePrice"; // 出售价格
_sellUpdateTime = "sellUpdateTime"; // 出售/取消出售时间
_studUpdateTime = "studUpdateTime"; // 放入种马场/取消时间
}
function init(address raceAttrAddress, address horseRaceToken) public onlyAdmin returns (bool) {
_horseRaceAttrAddress = IERC721Attr(raceAttrAddress);
_horseRaceTokenAddress = horseRaceToken;
return true;
}
function setHorseStatus(uint256 tokenId, uint256 status) public onlyProgram checkStatusValue(status) returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _horseRaceStatus, status.Uint256ToBytes());
return result;
}
function setHorseStatusBatch(uint256[] memory tokenIds, uint256 status) public onlyProgram checkStatusValue(status) returns (bool) {
require(tokenIds.length > 0 && tokenIds.length <= 256, "Cannot check 0 and must be less than 256");
for (uint256 i = 0; i < tokenIds.length; i++) {
_horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenIds[i], _horseRaceStatus, status.Uint256ToBytes());
}
return true;
}
function setHorseCount(uint256 tokenId) public onlyProgram returns (bool) {
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _raceCount);
uint256 count = bytesInfo.BytesToUint256() + (1);
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _raceCount, count.Uint256ToBytes());
return result;
}
function setHeadWearId(uint256 tokenId, uint256 headWearId) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _headWearId, headWearId.Uint256ToBytes());
return result;
}
function setArmorId(uint256 tokenId, uint256 armorId) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _armorId, armorId.Uint256ToBytes());
return result;
}
function setPonytailId(uint256 tokenId, uint256 ponytailId) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _ponytailId, ponytailId.Uint256ToBytes());
return result;
}
function setHoofId(uint256 tokenId, uint256 hoofId) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _hoofId, hoofId.Uint256ToBytes());
return result;
}
function setGrade(uint256 tokenId, uint256 grade) public onlyProgram checkGradeValue(grade) returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _grade, grade.Uint256ToBytes());
return result;
}
function setWinCount(uint256 tokenId) public onlyProgram returns (bool) {
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _winCount);
uint256 winCount = bytesInfo.BytesToUint256() + (1);
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _winCount, winCount.Uint256ToBytes());
return result;
}
function setRacePrice(uint256 tokenId, uint256 price) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _horseRacePrice, price.Uint256ToBytes());
return result;
}
function setRaceDis(uint256 tokenId, uint256 discount) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _horseRaceDiscount, discount.Uint256ToBytes());
return result;
}
function setRaceReward(uint256 tokenId, uint256 reward) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _horseRaceReward, reward.Uint256ToBytes());
return result;
}
function setRaceCoin(uint256 tokenId, uint256 coin) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _horseRaceCoin, coin.Uint256ToBytes());
return result;
}
function setSellUpdateTime(uint256 tokenId) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _sellUpdateTime, block.timestamp.Uint256ToBytes());
return result;
}
function setStudUpdateTime(uint256 tokenId) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _studUpdateTime, block.timestamp.Uint256ToBytes());
return result;
}
function setRaceLastOwner(uint256 tokenId, address addr) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _horseRaceLastOwner, addr.AddressToBytes());
return result;
}
function setRaceLastPrice(uint256 tokenId, uint256 price) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _horseRaceLastPrice, price.Uint256ToBytes());
return result;
}
function setRaceId(uint256 tokenId, uint256 raceId) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _raceId, raceId.Uint256ToBytes());
return result;
}
function setRaceIdBatch(uint256[] memory tokenIds, uint256 raceId) public onlyProgram returns (bool) {
require(tokenIds.length > 0 && tokenIds.length <= 256, "Cannot check 0 and must be less than 256");
for (uint256 i = 0; i < tokenIds.length; i++) {
_horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenIds[i], _raceId, raceId.Uint256ToBytes());
}
return true;
}
function setRaceType(uint256 tokenId, uint256 raceType) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _raceType, raceType.Uint256ToBytes());
return result;
}
function setRacecourse(uint256 tokenId, uint256 racecourse) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _racecourse, racecourse.Uint256ToBytes());
return result;
}
function setDistance(uint256 tokenId, uint256 distance) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _distance, distance.Uint256ToBytes());
return result;
}
function setRaceUpdateTime(uint256 tokenId, uint256 raceUpdateTime) public onlyProgram returns (bool) {
bool result = _horseRaceAttrAddress.setValues(address(_horseRaceTokenAddress), tokenId, _raceUpdateTime, raceUpdateTime.Uint256ToBytes());
return result;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Bytes.sol";
import "./Auth.sol";
import "../Interface/IERC721Token.sol";
import "../Interface/IERC721Attr.sol";
contract HorseRaceAttrOpera2 is Program {
using Bytes for bytes;
IERC721Attr private _horseRaceAttrAddress;
address private _horseRaceTokenAddress;
string public _horseRaceName ;//昵称 string
string public _nameUptCount ;//剩余改名次数 uint256
string public _birthDay ;//出生日期 uint256
string public _mainGeneration ; // 主代 uint256
string public _slaveGeneration ;//从代 uint256
string public _generationScore ;//迭代系数 uint256
string public _gender ;//性别 uint256
string public _color ;//皮肤颜色 uint256
string public _gene ;//基因综合评分 uint256
string public _gripGene ;//抓地基因
string public _accGene ;//加速基因
string public _endGene ;//耐力基因
string public _speedGene ;//速度基因
string public _turnToGene ;//转向基因
string public _controlGene ;//操控基因
string public _trainingValue ;//训练值 uint256
string public _trainingTime ;//训练时间 uint256
string public _useTraTime ;//扣除训练值时间 uint256
string public _energy ;//能量 uint256
string public _energyUpdateTime ;//能量恢复时间 uint256
string public _gradeScore ;//评分,参加比赛得到 uint256
string public _gradeScoreMark ;// 评分正负标记。1 正, 2负 uint256
string public _gradeIntegral ;//积分,参加大奖赛得到 uint256
string public _raceScoreUpdateTime ; //积分最后一次更新时间 uint256
string public _father ; //父资产唯一id uint256
string public _mother ; //母资产唯一id uint256
string public _breedCount ; //繁殖总次数 uint256
string public _breedTime ; //最近一次繁殖时间 uint256
string public _gradeIntegralYear ; // 本年度增涨的积分数量
string public _gradeIntegralYearTime ; // 当前记录年度时间
string public _gradeIntegralMonth ; // 本月增涨的积分数量
string public _gradeIntegralMonthTime; // 当前记录月度时间
string public _gradeIntegralWeek ; // 本周增涨的积分数量
string public _gradeIntegralWeekTime ; // 当前记录周时间
function initialize() public initializer {
program_initialize();
_horseRaceName = "horseRaceName";//昵称 string
_nameUptCount = "nameUptCount";//剩余改名次数 uint256
_birthDay = "birthDay";//出生日期 uint256
_mainGeneration = "mainGeneration"; // 主代 uint256
_slaveGeneration = "slaveGeneration";//从代 uint256
_generationScore = "generationScore";//迭代系数 uint256
_gender = "gender";//性别 uint256
_color = "color";//皮肤颜色 uint256
_gene = "gene";//基因综合评分 uint256
_gripGene = "gripGene";//抓地基因
_accGene = "accGene";//加速基因
_endGene = "endGene";//耐力基因
_speedGene = "speedGene";//速度基因
_turnToGene = "turnToGene";//转向基因
_controlGene = "controlGene";//操控基因
_trainingValue = "trainingValue";//训练值 uint256
_trainingTime = "trainingTime";//训练时间 uint256
_useTraTime = "useTraTime";//扣除训练值时间 uint256
_energy = "energy";//能量 uint256
_energyUpdateTime = "energyUpdateTime";//能量恢复时间 uint256
_gradeScore = "gradeScore";//评分,参加比赛得到 uint256
_gradeScoreMark = "gradeScoreMark";// 评分正负标记。1 正, 2负 uint256
_gradeIntegral = "gradeIntegral";//积分,参加大奖赛得到 uint256
_raceScoreUpdateTime = "raceScoreUpdateTime"; //积分最后一次更新时间 uint256
_father = "father"; //父资产唯一id uint256
_mother = "mother"; //母资产唯一id uint256
_breedCount = "breedCount"; //繁殖总次数 uint256
_breedTime = "breedTime"; //最近一次繁殖时间 uint256
_gradeIntegralYear = "gradeIntegralYear"; // 本年度增涨的积分数量
_gradeIntegralYearTime = "gradeIntegralYearTime"; // 当前记录年度时间
_gradeIntegralMonth = "gradeIntegralMonth"; // 本月增涨的积分数量
_gradeIntegralMonthTime = "gradeIntegralMonthTime"; // 当前记录月度时间
_gradeIntegralWeek = "gradeIntegralWeek"; // 本周增涨的积分数量
_gradeIntegralWeekTime = "gradeIntegralWeekTime"; // 当前记录周时间
}
function init(address raceAttrAddress, address horseRaceToken) public onlyAdmin returns (bool) {
_horseRaceAttrAddress = IERC721Attr(raceAttrAddress);
_horseRaceTokenAddress = horseRaceToken;
return true;
}
function getHorseName(uint256 tokenId) public view returns (string memory){
bytes memory nameBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _horseRaceName);
return nameBytes.BytesToString();
}
function getNameUptCount(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _nameUptCount);
return bytesInfo.BytesToUint256();
}
function getBirthDay(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _birthDay);
return bytesInfo.BytesToUint256();
}
function getHorseMGene(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _mainGeneration);
return bytesInfo.BytesToUint256();
}
function getHorseSGene(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _slaveGeneration);
return bytesInfo.BytesToUint256();
}
function getHorseGeneSC(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _generationScore);
return bytesInfo.BytesToUint256();
}
function getHorseGender(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gender);
return bytesInfo.BytesToUint256();
}
function getHorseColor(uint256 tokenId) public view returns (string memory){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _color);
return string(bytesInfo);
}
function getHorseGene(uint256 tokenId) public view returns (string memory){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gene);
return string(bytesInfo);
}
function getHorseGripGene(uint256 tokenId) public view returns (string memory){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gripGene);
return string(bytesInfo);
}
function getHorseAccGene(uint256 tokenId) public view returns (string memory){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _accGene);
return string(bytesInfo);
}
function getHorseEndGene(uint256 tokenId) public view returns (string memory){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _endGene);
return string(bytesInfo);
}
function getHorseSpdGene(uint256 tokenId) public view returns (string memory){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _speedGene);
return string(bytesInfo);
}
function getHorseTurnGene(uint256 tokenId) public view returns (string memory){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _turnToGene);
return string(bytesInfo);
}
function getHorseContGene(uint256 tokenId) public view returns (string memory){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _controlGene);
return string(bytesInfo);
}
function getTrainingTime(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _trainingTime);
return bytesInfo.BytesToUint256();
}
function getUseTraTime(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _useTraTime);
return bytesInfo.BytesToUint256();
}
function getTrainingValue(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _trainingValue);
return bytesInfo.BytesToUint256();
}
function getEnergy(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _energy);
return bytesInfo.BytesToUint256();
}
function getEnergyUpdateTime(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _energyUpdateTime);
return bytesInfo.BytesToUint256();
}
function getGradeScore(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gradeScore);
return bytesInfo.BytesToUint256();
}
function getIntegral(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gradeIntegral);
return bytesInfo.BytesToUint256();
}
function getGradeScoreMark(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gradeScoreMark);
return bytesInfo.BytesToUint256();
}
function getScoreUpdateTime(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _raceScoreUpdateTime);
return bytesInfo.BytesToUint256();
}
function getFather(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _father);
return bytesInfo.BytesToUint256();
}
function getMother(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _mother);
return bytesInfo.BytesToUint256();
}
function getBreedCount(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _breedCount);
return bytesInfo.BytesToUint256();
}
function getBreedTime(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _breedTime);
return bytesInfo.BytesToUint256();
}
function getIntegralYear(uint256 tokenId) public view returns (uint256) {
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gradeIntegralYear);
return bytesInfo.BytesToUint256();
}
function getIntegralMonth(uint256 tokenId) public view returns (uint256) {
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gradeIntegralMonth);
return bytesInfo.BytesToUint256();
}
function getIntegralWeek(uint256 tokenId) public view returns (uint256) {
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gradeIntegralWeek);
return bytesInfo.BytesToUint256();
}
function getIntegralDate(uint256 tokenId) public view returns (uint256, uint256, uint256) {
bytes memory bytesInfoY = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gradeIntegralYearTime);
uint256 year = bytesInfoY.BytesToUint256();
bytes memory bytesInfoM = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gradeIntegralMonthTime);
uint256 month= bytesInfoM.BytesToUint256();
bytes memory bytesInfoW = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _gradeIntegralWeekTime);
uint256 week = bytesInfoW.BytesToUint256();
return (year, month, week);
}
function getDetailIntegral(uint256 tokenId) public view returns (uint256, uint256, uint256, uint256) {
uint256 total = getIntegral(tokenId);
uint256 integralYear = getIntegralYear(tokenId);
uint256 integralMonth = getIntegralMonth(tokenId);
uint256 integralWeek = getIntegralWeek(tokenId);
return (total, integralYear, integralMonth, integralWeek);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Bytes.sol";
import "./Auth.sol";
import "../Interface/IERC721Token.sol";
import "../Interface/IERC721Attr.sol";
contract HorseRaceAttrOpera2_1 is Program {
using Bytes for bytes;
IERC721Attr private _horseRaceAttrAddress;
address private _horseRaceTokenAddress;
string public _headWearId ; //马头饰资产Id uint256
string public _armorId ; //马护甲资产Id uint256
string public _ponytailId ; //马尾饰资产Id uint256
string public _hoofId ; //马蹄饰资产Id uint256
string public _grade ; //马匹等级 uint256
string public _raceCount ; //参赛次数 uint256
string public _winCount ; //获赢次数 uint256
string public _raceId ; // 游戏服生成的竞赛唯一id
string public _raceType ;// 锦标赛/大奖赛/对决
string public _racecourse ;//报名比赛赛场资产唯一id
string public _distance ;//报名比赛赛程
string public _raceUpdateTime ;//报名/取消时间
string public _horseRaceStatus ;
string public _horseRaceDiscount ;
string public _horseRaceReward ;
string public _horseRaceCoin ;
string public _horseRaceLastOwner ; // 最后一次操作者
string public _horseRaceLastPrice ; // 最后一次成交价格
string public _horseRacePrice ; // 出售价格
string public _sellUpdateTime ; // 出售/取消出售时间
string public _studUpdateTime ; // 放入种马场/取消时间
function initialize() public initializer {
program_initialize();
_headWearId = "headWearId"; //马头饰资产Id uint256
_armorId = "armorId"; //马护甲资产Id uint256
_ponytailId = "ponytailId"; //马尾饰资产Id uint256
_hoofId = "hoofId"; //马蹄饰资产Id uint256
_grade = "grade"; //马匹等级 uint256
_raceCount = "raceCount"; //参赛次数 uint256
_winCount = "winCount"; //获赢次数 uint256
_raceId = "raceId"; // 游戏服生成的竞赛唯一id
_raceType = "raceType";// 锦标赛/大奖赛/对决
_racecourse = "racecourse";//报名比赛赛场资产唯一id
_distance = "distance";//报名比赛赛程
_raceUpdateTime = "raceUpdateTime";//报名/取消时间
_horseRaceStatus = "horseRaceStatus";
_horseRaceDiscount = "horseRaceDiscount";
_horseRaceReward = "horseRaceReward";
_horseRaceCoin = "horseRaceCoin";
_horseRaceLastOwner = "horseRaceLastOwner"; // 最后一次操作者
_horseRaceLastPrice = "horseRaceLastPrice"; // 最后一次成交价格
_horseRacePrice = "horseRacePrice"; // 出售价格
_sellUpdateTime = "sellUpdateTime"; // 出售/取消出售时间
_studUpdateTime = "studUpdateTime"; // 放入种马场/取消时间
}
function init(address raceAttrAddress, address horseRaceToken) public onlyAdmin returns (bool) {
_horseRaceAttrAddress = IERC721Attr(raceAttrAddress);
_horseRaceTokenAddress = horseRaceToken;
return true;
}
function getHeadWearId(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _headWearId);
return bytesInfo.BytesToUint256();
}
function getArmorId(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _armorId);
return bytesInfo.BytesToUint256();
}
function getPonytailId(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _ponytailId);
return bytesInfo.BytesToUint256();
}
function getHoofId(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _hoofId);
return bytesInfo.BytesToUint256();
}
function getGrade(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _grade);
return bytesInfo.BytesToUint256();
}
function getRaceCount(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _raceCount);
return bytesInfo.BytesToUint256();
}
function getWinCount(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _winCount);
return bytesInfo.BytesToUint256();
}
function getHorseRaceLastOwner(uint256 tokenId) public view returns (address){
bytes memory ownerBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _horseRaceLastOwner);
return ownerBytes.BytesToAddress();
}
function getHorseRaceStatus(uint256 tokenId) public view returns (uint256){
bytes memory statusBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _horseRaceStatus);
return statusBytes.BytesToUint256();
}
function getHorseRaceCoin(uint256 tokenId) public view returns (uint256){
bytes memory coinBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _horseRaceCoin);
return coinBytes.BytesToUint256();
}
function getHorseRacePrice(uint256 tokenId) public view returns (uint256){
bytes memory priceBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _horseRacePrice);
return priceBytes.BytesToUint256();
}
function getHorseRaceDiscount(uint256 tokenId) public view returns (uint256){
bytes memory DisBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _horseRaceDiscount);
return DisBytes.BytesToUint256();
}
function getHorseRaceReward(uint256 tokenId) public view returns (uint256){
bytes memory rewBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _horseRaceReward);
return rewBytes.BytesToUint256();
}
function getHorseRaceLastPrice(uint256 tokenId) public view returns (uint256){
bytes memory priceBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _horseRaceLastPrice);
return priceBytes.BytesToUint256();
}
function getSellUpdateTime(uint256 tokenId) public view returns (uint256){
bytes memory priceBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _sellUpdateTime);
return priceBytes.BytesToUint256();
}
function getStudUpdateTime(uint256 tokenId) public view returns (uint256){
bytes memory priceBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _studUpdateTime);
return priceBytes.BytesToUint256();
}
function getRaceId(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _raceId);
return bytesInfo.BytesToUint256();
}
function getRaceType(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _raceType);
return bytesInfo.BytesToUint256();
}
function getRacecourse(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _racecourse);
return bytesInfo.BytesToUint256();
}
function getDistance(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _distance);
return bytesInfo.BytesToUint256();
}
function getRaceUpdateTime(uint256 tokenId) public view returns (uint256){
bytes memory bytesInfo = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenId, _raceUpdateTime);
return bytesInfo.BytesToUint256();
}
function checkStatus(uint256[] memory tokenIds, uint256 status) public view returns (bool){
require(tokenIds.length > 0 && tokenIds.length <= 256, "Cannot check 0 and must be less than 256");
for (uint256 i = 0; i < tokenIds.length; i++) {
bytes memory statusBytes = _horseRaceAttrAddress.getValue(address(_horseRaceTokenAddress), tokenIds[i], _horseRaceStatus);
if (statusBytes.BytesToUint256() != status) {
return false;
}
}
return true;
}
function checkGameInfo(uint256[] memory tokenIds, uint256 types, uint256 racecourseId,
uint256 level, uint256 distance) public view returns (bool){
require(tokenIds.length > 0 && tokenIds.length <= 256, "Cannot check 0 and must be less than 256");
for (uint256 i = 0; i < tokenIds.length; i++) {
if (getRaceType(tokenIds[i]) != types || getRacecourse(tokenIds[i]) != racecourseId
|| getDistance(tokenIds[i]) != distance || getGrade(tokenIds[i]) != level) {
return false;
}
}
return true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../Interface/IERC721Token.sol";
import "../Interface/ICoin.sol";
import "../Interface/IConstant.sol";
import "./Auth.sol";
import "../library/Bytes.sol";
import "hardhat/console.sol";
interface IHorseEquipOpera {
function setEquipStatus(uint256 tokenId, uint256 status) external returns (bool);
function setEquipOfHorseId(uint256 tokenId, uint256 horseId) external returns (bool);
function getHorseEquipTypes(uint256 tokenId) external returns (uint256);
function getHorseEquipStatus(uint256 tokenId) external returns (uint256);
}
interface IHorseRaceOpera {
function setHorseName(uint256 tokenId, string calldata name) external returns (bool);
function setUseTraTime(uint256 tokenId, uint256 trainingTime) external returns (bool);
function setHorseNameUptCount(uint256 tokenId, uint256 count) external returns (bool);// 性别
function setHorseTraValue(uint256 tokenId, uint256 trainingValue) external returns (bool);
function setHorseTraTime(uint256 tokenId, uint256 trainingTime) external returns (bool);
function setHeadWearId(uint256 tokenId, uint256 headWearId) external returns (bool);
function setGrade(uint256 tokenId, uint256 grade) external returns (bool);
function setArmorId(uint256 tokenId, uint256 armorId) external returns (bool);
function setPonytailId(uint256 tokenId, uint256 ponytailId) external returns (bool);
function setHoofId(uint256 tokenId, uint256 hoofId) external returns (bool);
function getNameUptCount(uint256 tokenId) external returns (uint256);
function getTrainingTime(uint256 tokenId) external returns (uint256);
function getTrainingValue(uint256 tokenId) external returns (uint256);
function getHeadWearId(uint256 tokenId) external returns (uint256);
function getArmorId(uint256 tokenId) external returns (uint256);
function getPonytailId(uint256 tokenId) external returns (uint256);
function getHoofId(uint256 tokenId) external returns (uint256);
function getUseTraTime(uint256 tokenId) external returns (uint256);
function setHorseGripGene(uint256 tokenId, string calldata gene) external returns (bool);
function setHorseAccGene(uint256 tokenId, string calldata gene) external returns (bool);
function setHorseEndGene(uint256 tokenId, string calldata gene) external returns (bool);
function setHorseSpdGene(uint256 tokenId, string calldata gene) external returns (bool);
function setHorseTurnGene(uint256 tokenId, string calldata gene) external returns (bool);
function setHorseContGene(uint256 tokenId, string calldata gene) external returns (bool);
function getHorseRaceStatus(uint256 tokenId) external view returns (uint256);
}
contract HorseRaceExtra1 is Program {
using Math for uint256;
using Bytes for bytes;
ICoin private _coin;
IHorseRaceOpera private _opera;
IHorseRaceOpera private _opera1_1;
IHorseRaceOpera private _opera2;
IHorseRaceOpera private _opera2_1;
IHorseEquipOpera private _equipOpera;
IERC721Token private _horseTokenAddress;
IERC721Token private _equipTokenAddress;
address private _feeAccount;
IConstant private _constant; // 常量合约地址
event InitHorseGrade(uint256 horseId, uint256 grade);
event TrainingHorses(address account, uint256 tokenId, uint256 time, uint256 value);
event UptHorseName(uint256 tokenId, string name, uint256 count);
event HorseDeco(address account, uint256 tokenId, uint256 types, uint256 equipId, uint256 time);
event HorseDecoOfEquip(uint256 equipId, uint256 status, uint256 tokenId);
event UnloadEquip(address account, uint256 tokenId, uint256 status); // 装备替换过程中卸载上一件装备
event UnloadEquipOfHorse(address account, uint256 horseId, uint256 types, uint256 status);// 装备替换过程中卸载上一件装备
event SetHorseGene(uint256 tokenId, string gripGene, string accGene, string endGene, string speedGene,
string turnToGene, string controlGene);
event HorseTransfer(address from, address to, uint256 tokenId, uint256 time);
modifier checkOwner(uint256 tokenId) {
console.log("check owner horse id is ", tokenId);
require(_horseTokenAddress.ownerOf(tokenId) == msg.sender, "only owner can do it!");
_;
}
modifier checkEquipOwner(uint256 equipId) {
require(_equipTokenAddress.ownerOf(equipId) == msg.sender, "only owner can do it!");
_;
}
modifier senderIsToken() {
require(msg.sender == address(_horseTokenAddress), "only token contract can do it");
_;
}
function initialize() public initializer {
program_initialize();
}
function initHorseRaceAttrAddress(
address operaAddr, address opera1_1, address opera2,
address opera2_1, address equipOpera, address horseToken,
address equipToken, address constAddr, address coinAddress, address feeAccount
) public onlyAdmin returns (bool){
_opera = IHorseRaceOpera(operaAddr);
_opera1_1 = IHorseRaceOpera(opera1_1);
_opera2 = IHorseRaceOpera(opera2);
_opera2_1 = IHorseRaceOpera(opera2_1);
_equipOpera = IHorseEquipOpera(equipOpera);
_horseTokenAddress = IERC721Token(horseToken);
_equipTokenAddress = IERC721Token(equipToken);
_coin = ICoin(coinAddress);
_constant = IConstant(constAddr);
_feeAccount = feeAccount;
return true;
}
function uptHorseName(uint256 tokenId, string memory name, bytes memory sign) public checkOwner(tokenId) returns (bool) {
require(sign.Decode(name) == _constant.getAccount(), "Signature verification failure");
uint256 count = _opera2.getNameUptCount(tokenId);
require(count > 0, "The number of edits has been used up");
_opera.setHorseName(tokenId, name);
_opera.setHorseNameUptCount(tokenId, count - 1);
emit UptHorseName(tokenId, name, count - (1));
return true;
}
// 训练马匹
function trainingHorses(uint256 tokenId) public checkOwner(tokenId) returns (bool) {
uint256 lastTraTime = _opera2.getTrainingTime(tokenId);
uint256 current = block.timestamp;
uint256 spacing = current - (lastTraTime);
require(spacing > _constant.getTraTime(), "Exceeded the training limit");
_coin.safeTransferFrom1(_constant.getTraToken(), msg.sender, address(_coin), _constant.getTraTokenAmount());
// 计算马匹当前训练值
uint256 traingUntTime = _constant.getUntTime();
uint256 oldValue = _opera2.getTrainingValue(tokenId);
uint256 subValue = (current - lastTraTime) / traingUntTime;
if (oldValue <= subValue) {
subValue = oldValue; // 最多减去当前已有的训练值,避免溢出.
}
oldValue = oldValue - (subValue);
oldValue = oldValue.max(_constant.getMinTraValue());
// 修改马匹训练值
uint256 newValue = oldValue + (_constant.getTraAddValue());
newValue = newValue.min(_constant.getMaxTraValue());
_opera.setHorseTraValue(tokenId, newValue);
_opera.setHorseTraTime(tokenId, block.timestamp);
emit TrainingHorses(msg.sender, tokenId, block.timestamp, newValue);
return true;
}
// 马匹装饰
function horseDeco(uint256 horseId, uint256 equipId) public checkOwner(horseId) checkEquipOwner(equipId) returns (bool){
uint256 equipType = _equipOpera.getHorseEquipTypes(equipId);
uint256 status = _equipOpera.getHorseEquipStatus(equipId);
require(status == 0, "Abnormal equipment status");
if (equipType == 1) {
uint256 head = _opera2_1.getHeadWearId(horseId);
console.log("deco head to horse", equipId);
_opera1_1.setHeadWearId(horseId, equipId);
if (head > 0) {
_equipOpera.setEquipStatus(head, 0);
_equipOpera.setEquipOfHorseId(head, 0);
emit UnloadEquipOfHorse(msg.sender, horseId, equipType, 0);
emit UnloadEquip(msg.sender, head, 0);
}
} else if (equipType == 2) {
uint256 armor = _opera2_1.getArmorId(horseId);
console.log("deco armor to horse", equipId);
_opera1_1.setArmorId(horseId, equipId);
if (armor > 0) {
_equipOpera.setEquipStatus(armor, 0);
_equipOpera.setEquipOfHorseId(armor, 0);
emit UnloadEquipOfHorse(msg.sender, horseId, equipType, 0);
emit UnloadEquip(msg.sender, armor, 0);
}
} else if (equipType == 3) {
uint256 ponytail = _opera2_1.getPonytailId(horseId);
console.log("deco ponytail to horse", equipId);
_opera1_1.setPonytailId(horseId, equipId);
if (ponytail > 0) {
_equipOpera.setEquipStatus(ponytail, 0);
_equipOpera.setEquipOfHorseId(ponytail, 0);
emit UnloadEquipOfHorse(msg.sender, horseId, equipType, 0);
emit UnloadEquip(msg.sender, ponytail, 0);
}
} else {
uint256 hoof = _opera2_1.getHoofId(horseId);
console.log("deco hoof to horse", equipId);
_opera1_1.setHoofId(horseId, equipId);
if (hoof > 0) {
_equipOpera.setEquipStatus(hoof, 0);
_equipOpera.setEquipOfHorseId(hoof, 0);
emit UnloadEquipOfHorse(msg.sender, horseId, equipType, 0);
emit UnloadEquip(msg.sender, hoof, 0);
}
}
_equipOpera.setEquipStatus(equipId, 2);
_equipOpera.setEquipOfHorseId(equipId, horseId);
emit HorseDeco(msg.sender, horseId, equipType, equipId, block.timestamp);
emit HorseDecoOfEquip(equipId, 2, horseId);
return true;
}
function setHorseGene(
uint256 horseId,
string memory gripGene,
string memory accGene,
string memory endGene,
string memory speedGene,
string memory turnToGene,
string memory controlGene
) public onlyProgram {
_opera.setHorseGripGene(horseId, gripGene);
_opera.setHorseAccGene(horseId, accGene);
_opera.setHorseEndGene(horseId, endGene);
_opera.setHorseSpdGene(horseId, speedGene);
_opera.setHorseTurnGene(horseId, turnToGene);
_opera.setHorseContGene(horseId, controlGene);
emit SetHorseGene(horseId, gripGene, accGene, endGene, speedGene, turnToGene, controlGene);
}
// 批量初始化马匹等级
function initHorseGrade(uint256[] memory horseId, uint256[] memory comp) public onlyProgram {
require(horseId.length == comp.length && horseId.length < 256, "The array length should not exceed 256");
for (uint256 i = 0; i < horseId.length; i++) {
_setGrade(comp[i], horseId[i]);
}
}
function _setGrade(uint256 score, uint256 horseId) internal returns (uint256){
// address owner = _horseTokenAddress.ownerOf(horseId); // check token exists.
uint256 grade;
if (score < 20) {
grade = 999;
} else if (score < 30) {
grade = 5;
} else if (score < 40) {
grade = 4;
} else if (score < 50) {
grade = 3;
} else if (score < 60) {
grade = 2;
} else {
grade = 1;
}
_opera1_1.setGrade(horseId, grade);
emit InitHorseGrade(horseId, grade);
return grade;
}
function beforeTransfer(address from, address to, uint256 tokenId) public senderIsToken returns (bool) {
// no need more handler.
if (_constant.isOfficialContract(from) || _constant.isOfficialContract(to)) {
//console.log("no need handler for equip extra contract transfer");
} else {
uint256 status = _opera2_1.getHorseRaceStatus(tokenId);
uint256 resting = _constant.getResting();
require(status == resting, "only resting horse could transfer");
// 检查马匹装备
uint256 horseId = tokenId;
{
uint256 head = _opera2_1.getHeadWearId(horseId);
if (head > 0) {
console.log("unload head equip", head);
_equipOpera.setEquipStatus(head, 0);
_equipOpera.setEquipOfHorseId(head, 0);
emit UnloadEquipOfHorse(msg.sender, horseId, 1, 0);
emit UnloadEquip(msg.sender, head, 0);
}
}
{
uint256 armor = _opera2_1.getArmorId(horseId);
if (armor > 0) {
console.log("unload armor equip", armor);
_equipOpera.setEquipStatus(armor, 0);
_equipOpera.setEquipOfHorseId(armor, 0);
emit UnloadEquipOfHorse(msg.sender, horseId, 2, 0);
emit UnloadEquip(msg.sender, armor, 0);
}
}
{
uint256 ponytail = _opera2_1.getPonytailId(horseId);
if (ponytail > 0) {
console.log("unload ponytail equip", ponytail);
_equipOpera.setEquipStatus(ponytail, 0);
_equipOpera.setEquipOfHorseId(ponytail, 0);
emit UnloadEquipOfHorse(msg.sender, horseId, 3, 0);
emit UnloadEquip(msg.sender, ponytail, 0);
}
}
{
uint256 hoof = _opera2_1.getHoofId(horseId);
if (hoof > 0) {
console.log("unload hoof equip", hoof);
_equipOpera.setEquipStatus(hoof, 0);
_equipOpera.setEquipOfHorseId(hoof, 0);
emit UnloadEquipOfHorse(msg.sender, horseId, 4, 0);
emit UnloadEquip(msg.sender, hoof, 0);
}
}
}
return true;
}
function afterTransfer(address from, address to, uint256 tokenId) public senderIsToken returns (bool) {
// no need more handler.
if (_constant.isOfficialContract(from) || _constant.isOfficialContract(to)) {
//console.log("no need handler for equip extra contract transfer");
} else {
console.log("emit event horseTransfer");
emit HorseTransfer(from, to, tokenId, block.timestamp);
}
return true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../Interface/ICoin.sol";
import "../Interface/ICoin721.sol";
import "./Auth.sol";
interface IERC721Token {
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function safeMint(address to) external returns (uint256);
}
interface IConstant {
function getFeeRateOfHorse() external returns (uint256);
function getOnSale() external returns (uint256);
function getResting() external returns (uint256);
function getBreeding() external returns (uint256);
function getMinDiscountOfHorse() external returns (uint256);
function getMaxRewardOfHorse() external returns (uint256);
function getMinSellUptTime() external returns (uint256);
function getMinMatureTime() external returns (uint256);
function getMinStudUptTime() external returns (uint256);
function getModifyNameTimes() external returns (uint256);
}
interface IHorseRaceOpera {
function setHorseStatus(uint256 tokenId, uint256 status) external returns (bool);
function setGrade(uint256 tokenId, uint256 grade) external returns (bool);
function setHorseNameUptCount(uint256 tokenId, uint256 count) external returns (bool);
function setRacePrice(uint256 tokenId, uint256 price) external returns (bool);
function setRaceDis(uint256 tokenId, uint256 discount) external returns (bool);
function setRaceReward(uint256 tokenId, uint256 reward) external returns (bool);
function setRaceCoin(uint256 tokenId, uint256 coin) external returns (bool);
function setSellUpdateTime(uint256 tokenId) external returns (bool);
function setStudUpdateTime(uint256 tokenId) external returns (bool);
function setRaceLastOwner(uint256 tokenId, address addr) external returns (bool);
function setRaceLastPrice(uint256 tokenId, uint256 price) external returns (bool);
function getBirthDay(uint256 tokenId) external returns (uint256);
function getNameUptCount(uint256 tokenId) external returns (uint256);
function getHeadWearId(uint256 tokenId) external returns (uint256);
function getArmorId(uint256 tokenId) external returns (uint256);
function getPonytailId(uint256 tokenId) external returns (uint256);
function getHoofId(uint256 tokenId) external returns (uint256);
function getHorseGender(uint256 tokenId) external returns (uint256);
function getHorseRaceLastOwner(uint256 tokenId) external returns (address);
function getHorseRaceStatus(uint256 tokenId) external returns (uint256);
function getHorseRaceCoin(uint256 tokenId) external returns (uint256);
function getHorseRacePrice(uint256 tokenId) external returns (uint256);
function getHorseRaceDiscount(uint256 tokenId) external returns (uint256);
function getHorseRaceReward(uint256 tokenId) external returns (uint256);
function getSellUpdateTime(uint256 tokenId) external returns (uint256);
function getStudUpdateTime(uint256 tokenId) external returns (uint256);
}
contract HorseRaceExtra2 is Program {
using Math for uint256;
ICoin private _coin;
ICoin721 private _coin721;
IHorseRaceOpera private _opera1;
IHorseRaceOpera private _opera1_1;
IHorseRaceOpera private _opera2;
IHorseRaceOpera private _opera2_1;
IERC721Token private _horseTokenAddress;
address private _feeAccount;
IConstant private _constant; // 常量合约地址
event SellHorse(address account, uint256 tokenId, uint256 coin, uint256 price, uint256 time, uint256 status);
event SireHorse(address account, uint256 tokenId, uint256 coin, uint256 price, uint256 time, uint256 status);
event CancelSellHorse(address account, uint256 tokenId, uint256 time, uint256 status);
event CancelSireHorse(address account, uint256 tokenId, uint256 time, uint256 status);
event BuyHorse(address account, uint256 tokenId, uint256 coin, uint256 price, uint256 status, uint256 remainUptNameCount);
modifier checkOwner(uint256 tokenId) {
require(_horseTokenAddress.ownerOf(tokenId) == msg.sender, "only owner can do it!");
_;
}
function initialize() public initializer {
program_initialize();
}
function initHorseRaceAttrAddress(
address opera1, address opera1_1, address opera2, address opera2_1,
address coinAddress, address coin721Addr, address tokenAddr, address constAddr, address feeAccount
) public onlyAdmin returns (bool){
_opera1 = IHorseRaceOpera(opera1);
_opera1_1 = IHorseRaceOpera(opera1_1);
_opera2 = IHorseRaceOpera(opera2);
_opera2_1 = IHorseRaceOpera(opera2_1);
_horseTokenAddress = IERC721Token(tokenAddr);
_coin = ICoin(coinAddress);
_coin721 = ICoin721(coin721Addr);
_constant = IConstant(constAddr);
_feeAccount = feeAccount;
return true;
}
function batchSellHorse(uint256 [] memory horseId, uint256 [] memory price, uint256 [] memory coin) public {
require(horseId.length == price.length && horseId.length == coin.length, "batch sell horse param length not equal");
require(horseId.length < 100, "params length should little than 100");
for(uint i = 0; i < horseId.length; i++) {
sellHorse(horseId[i], price[i], coin[i]);
}
}
function batchSellHorseOnePrice(uint256 [] memory horseId, uint256 price, uint256 coin) public {
require(horseId.length < 100, "params length should little than 100");
for(uint i = 0; i < horseId.length; i++) {
sellHorse(horseId[i], price, coin);
}
}
// 马匹出售
function sellHorse(uint256 horseId, uint256 price, uint256 coin) public checkOwner(horseId) {
require(_opera2_1.getHorseRaceStatus(horseId) == 0, "Horses that must be at rest can be sold");
require(_opera2_1.getHeadWearId(horseId) == 0 && _opera2_1.getArmorId(horseId) == 0
&& _opera2_1.getPonytailId(horseId) == 0 && _opera2_1.getHoofId(horseId) == 0, "Can't bring equipment to sell together");
uint256 current = block.timestamp;
uint256 sellUptTime = _opera2_1.getSellUpdateTime(horseId);
uint256 spacing = current - (sellUptTime);
require(spacing > _constant.getMinSellUptTime(), "Operation too fast");
_horseTokenAddress.safeTransferFrom(msg.sender, address(_coin721), horseId);
_opera1_1.setHorseStatus(horseId, _constant.getOnSale());
_opera1_1.setRaceDis(horseId, _constant.getMinDiscountOfHorse());
_opera1_1.setRaceReward(horseId, _constant.getMaxRewardOfHorse());
_opera1_1.setRaceCoin(horseId, coin);
_opera1_1.setRaceLastOwner(horseId, msg.sender);
_opera1_1.setRacePrice(horseId, price);
_opera1_1.setSellUpdateTime(horseId);
emit SellHorse(msg.sender, horseId, coin, price, block.timestamp, _constant.getOnSale());
}
function batchCancelSellHorse(uint256 [] memory horseId) public {
for(uint i = 0; i < horseId.length; i++) {
cancelSellHorse(horseId[i]);
}
}
// 马匹取消出售
function cancelSellHorse(uint256 horseId) public {
require(_opera2_1.getHorseRaceStatus(horseId) == 1, "The asset status is abnormal");
uint256 current = block.timestamp;
uint256 sellUptTime = _opera2_1.getSellUpdateTime(horseId);
uint256 spacing = current - (sellUptTime);
require(spacing > _constant.getMinSellUptTime(), "Operation too fast");
address owner = _opera2_1.getHorseRaceLastOwner(horseId);
require(owner == msg.sender, "Can only cancel own order");
_coin721.safeTransferFrom(address(_horseTokenAddress), address(_coin721), msg.sender, horseId);
_opera1_1.setHorseStatus(horseId, _constant.getResting());
_opera1_1.setSellUpdateTime(horseId);
emit CancelSellHorse(msg.sender, horseId, block.timestamp, _constant.getResting());
}
// 马匹放入育马场
function sireHorse(uint256 horseId, uint256 price, uint256 coin) public checkOwner(horseId) {
require(_opera2.getHorseGender(horseId) == 1, "The horse must be a stallion");
require(_opera2_1.getHorseRaceStatus(horseId) == 0, "Horses that must be at rest can be sold");
require(_opera2_1.getHeadWearId(horseId) == 0 && _opera2_1.getArmorId(horseId) == 0
&& _opera2_1.getPonytailId(horseId) == 0 && _opera2_1.getHoofId(horseId) == 0, "Can't bring equipment to sell together");
uint256 current = block.timestamp;
uint256 studUptTime = _opera2_1.getStudUpdateTime(horseId);
uint256 birthDay = _opera2.getBirthDay(horseId);
uint256 spacing = current - (studUptTime);
uint256 growthTime = current - (birthDay);
require(spacing > _constant.getMinStudUptTime(), "Operation too fast");
require(growthTime > _constant.getMinMatureTime(), "The horse is immature");
_horseTokenAddress.safeTransferFrom(msg.sender, address(_coin721), horseId);
_opera1_1.setHorseStatus(horseId, 2);
_opera1_1.setRaceLastOwner(horseId, msg.sender);
_opera1_1.setStudUpdateTime(horseId);
_opera1_1.setRaceCoin(horseId, coin);
_opera1_1.setRacePrice(horseId, price);
emit SireHorse(msg.sender, horseId, coin, price, block.timestamp, _constant.getBreeding());
}
// 马匹育马场取出
function cancelSireHorse(uint256 horseId) public {
require(_opera2_1.getHorseRaceStatus(horseId) == 2, "Horses that must be at rest can be sold");
uint256 current = block.timestamp;
uint256 studUptTime = _opera2_1.getStudUpdateTime(horseId);
uint256 spacing = current - (studUptTime);
require(spacing > _constant.getMinStudUptTime(), "Operation too fast");
address owner = _opera2_1.getHorseRaceLastOwner(horseId);
require(owner == msg.sender, "Can only cancel own order");
_coin721.safeTransferFrom(address(_horseTokenAddress), address(_coin721), msg.sender, horseId);
_opera1_1.setHorseStatus(horseId, _constant.getResting());
_opera1_1.setStudUpdateTime(horseId);
emit CancelSireHorse(msg.sender, horseId, block.timestamp, _constant.getResting());
}
// 购买马匹
function buy(uint256 coin, uint256 horseId) public {
address owner = _opera2_1.getHorseRaceLastOwner(horseId);
require(owner != msg.sender, "Not allowed to purchase own orders!");
uint256 status = _opera2_1.getHorseRaceStatus(horseId);
require(status == 1, "This token is not selling!");
uint256 coinType = _opera2_1.getHorseRaceCoin(horseId);
require(coinType == coin, "This coin is not selling!");
uint256 price = _opera2_1.getHorseRacePrice(horseId);
uint256 discount = _opera2_1.getHorseRaceDiscount(horseId);
uint256 real_dis = discount.max(_constant.getMinDiscountOfHorse());
uint256 real_price = price * (real_dis) / (10000);
// 购买者转给coin合约
_coin.safeTransferFrom(coinType, msg.sender, address(_coin), real_price);
_buy(horseId, coin, owner, msg.sender, real_price);
_opera1_1.setRaceLastPrice(horseId, price);
_opera1_1.setHorseStatus(horseId, _constant.getResting());
_opera1_1.setRaceLastOwner(horseId, msg.sender);
_opera1.setHorseNameUptCount(horseId, _constant.getModifyNameTimes());
emit BuyHorse(msg.sender, horseId, coin, real_price, _constant.getResting(), _constant.getModifyNameTimes());
}
function _buy(
uint256 tokenId,
uint256 coin,
address from, // 这里是出售者地址
address to,
// uint256 price,
uint256 real_price
) internal {
// uint256 reward = _opera.getHorseEquipReward(tokenId);
// uint256 real_reward = reward.min(_maxReward);
// uint256 rewardDiscount = price.mul(real_reward).div(10000);
uint256 fee_to_pay = real_price * (_constant.getFeeRateOfHorse()) / (10000);
// transfer the handling fee to the set handling fee account
_coin.safeTransfer(coin, _feeAccount, fee_to_pay);
// transfer the benefits to the account of the transaction initiator
_coin.safeTransfer(coin, from, real_price - (fee_to_pay));
// if (rewardDiscount > 0) {
// _coin.safeTransferFrom(_rewardCoin, owner, to, rewardDiscount);
// }
_coin721.safeTransferFrom(address(_horseTokenAddress), address(_coin721), to, tokenId);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../Interface/IERC721Attr.sol";
import "../Interface/IERC721Token.sol";
import "../library/Bytes.sol";
import "../library/Uint256.sol";
import "./Auth.sol";
contract RacecourseAttrOperaContract is Program {
using Uint256 for uint256;
using Bytes for bytes;
IERC721Attr private _attrAddress;
string public _horseId;//报名的马匹id
function initialize() public initializer {
program_initialize();
_horseId = "horseId";//报名的马匹id
}
function init(address attrAddress) public onlyAdmin returns (bool) {
_attrAddress = IERC721Attr(attrAddress);
return true;
}
function setHorseId(uint256 tokenId, uint256 horseId) public onlyProgram returns (bool) {
bool result = _attrAddress.setArrayValue(tokenId, _horseId, horseId.Uint256ToBytes());
return result;
}
// 取消比赛后,清除已经报名的马匹信息
function delHorseId(uint256 tokenId) public onlyProgram returns (bool) {
bool result = _attrAddress.delArrayValue(tokenId, _horseId);
return result;
}
// 取消报名后,清除对应的马匹信息
function delHorseIdOne(uint256 tokenId, uint256 horseId) public onlyProgram returns (bool) {
bool result = _attrAddress.removeArrayValue(tokenId, _horseId, horseId.Uint256ToBytes());
return result;
}
function delHorseIdBatch(uint256[] memory tokenIds) public onlyProgram returns (bool) {
require(tokenIds.length > 0 && tokenIds.length <= 256, "Cannot del 0 and must be less than 256");
for (uint256 i = 0; i < tokenIds.length; i++) {
_attrAddress.delArrayValue(tokenIds[i], _horseId);
}
return true;
}
function getHorseId(uint256 tokenId) public view returns (uint256[] memory) {
return _attrAddress.getArrayValue(tokenId, _horseId);
}
function checkHorseId(uint256 tokenId, uint256 horseId) external view returns (bool){
bool result = _attrAddress.checkArrayValue(tokenId, _horseId, horseId.Uint256ToBytes());
return result;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "./Auth.sol";
contract UserLoginContract is Admin {
mapping(address => mapping(string => bool)) private _token;
mapping(address => mapping(string => uint256)) private _tokenExpTime;
function initialize() public initializer {
admin_initialize();
}
function reg(string memory token, uint256 time) public {
_token[msg.sender][token] = true;
_tokenExpTime[msg.sender][token] = block.timestamp + (time);
}
function logout(string memory token) public {
_token[msg.sender][token] = false;
_tokenExpTime[msg.sender][token] = block.timestamp;
}
function checkToken(address account, string memory token) public view returns (bool){
if (_token[account][token] && _tokenExpTime[account][token] > block.timestamp) {
return true;
}
return false;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
library Address {
function AddressToBytes(address source) internal pure returns (bytes memory) {
return abi.encodePacked(source);
}
function ToAsciiString(address x) internal pure returns (string memory) {
bytes memory s = new bytes(40);
for (uint i = 0; i < 20; i++) {
bytes1 b = bytes1(uint8(uint(uint160(x)) / (2 ** (8 * (19 - i)))));
bytes1 hi = bytes1(uint8(b) / 16);
bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
s[2 * i] = char(hi);
s[2 * i + 1] = char(lo);
}
return string(s);
}
function char(bytes1 b) internal pure returns (bytes1 c) {
if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
else return bytes1(uint8(b) + 0x57);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
// OpenZeppelin/utils/Context.sol
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
contract ArrayCheck {
uint256 internal BATCH_COUNT = 256;
modifier checkArraySizeUint256(uint256[] memory x) {
require(x.length > 0 && x.length <= BATCH_COUNT, "Too many elements in the array");
_;
}
modifier checkArraySizeAddress(address[] memory x) {
require(x.length > 0 && x.length <= BATCH_COUNT, "Too many elements in the array");
_;
}
modifier checkArraySizeString(string[] memory x) {
require(x.length > 0 && x.length <= BATCH_COUNT, "Too many elements in the array");
_;
}
modifier checkArraySize1(uint256 len1) {
require(len1 > 0 && len1 <= BATCH_COUNT, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize2(uint256 len1, uint256 len2) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize3(uint256 len1, uint256 len2, uint256 len3) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2 && len2 == len3, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize4(uint256 len1, uint256 len2, uint256 len3, uint256 len4) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2 && len2 == len3 && len3 == len4, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize5(uint256 len1, uint256 len2, uint256 len3, uint256 len4, uint256 len5) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2 && len2 == len3 && len3 == len4 && len4 == len5, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize6(uint256 len1, uint256 len2, uint256 len3, uint256 len4, uint256 len5, uint256 len6) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2 && len2 == len3 && len3 == len4 && len4 == len5 && len5 == len6, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize7(uint256 len1, uint256 len2, uint256 len3, uint256 len4, uint256 len5, uint256 len6, uint256 len7) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2 && len2 == len3 && len3 == len4 && len4 == len5 && len5 == len6 && len6 == len7, "The size of These Arrays must be equal");
_;
}
}
contract Admin is Ownable, ArrayCheck {
mapping(address => bool) private _admins;
modifier onlyAdmin() {
/*
if (!_admins[msg.sender]) {
console.log("onlyAdmin", address(this), msg.sender);
}
*/
require(_admins[msg.sender], "Only admin can call it");
_;
}
constructor(){
_admins[msg.sender] = true;
// console.log("addAdmin", address(this), msg.sender);
}
function addAdmins(address[] memory admins_) public onlyOwner checkArraySizeAddress(admins_) {
for (uint256 i = 0; i < admins_.length; i++) {
addAdmin(admins_[i]);
}
}
function delAdmins(address[] memory admins_) public onlyOwner checkArraySizeAddress(admins_) {
for (uint256 i = 0; i < admins_.length; i++) {
delAdmin(admins_[i]);
}
}
function addAdmin(address admin_) public onlyOwner {
_admins[admin_] = true;
// console.log("addAdmin", address(this), _admin);
}
function delAdmin(address admin_) public onlyOwner {
_admins[admin_] = false;
// console.log("delAdmin", address(this), _admin);
}
function isAdmin(address _addr) public view returns (bool) {
return _admins[_addr];
}
}
contract Program is Admin {
// using Address for address;
mapping(address => bool) private _programs;
modifier onlyProgram() {
require(_programs[msg.sender], "Only program can call it");
_;
}
function addPrograms(address[] memory programs_) public onlyOwner checkArraySizeAddress(programs_) {
for (uint256 i = 0; i < programs_.length; i++) {
addProgram(programs_[i]);
}
}
function delPrograms(address[] memory programs_) public onlyOwner checkArraySizeAddress(programs_) {
for (uint256 i = 0; i < programs_.length; i++) {
delProgram(programs_[i]);
}
}
function addProgram(address _program) public onlyOwner {
//require(_program.isContract(), "Only contract can be a program");
_programs[_program] = true;
}
function delProgram(address program_) public onlyOwner {
_programs[program_] = false;
}
function isProgram(address program_) public view returns (bool) {
return _programs[program_];
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../Interface/BaseInterface.sol";
//import "hardhat/console.sol";
uint256 constant PRICE_UNIT = 10000;
uint256 constant PERCENT_UNIT = 10000;
library Bytes {
function BytesToUint256(bytes memory b) internal pure returns (uint256){
uint256 number;
for (uint i = 0; i < b.length; i++) {
number = number + uint8(b[i]) * (2 ** (8 * (b.length - (i + 1))));
}
return number;
}
function BytesToString(bytes memory source) internal pure returns (string memory result) {
return string(source);
}
function BytesToAddress(bytes memory bys) internal pure returns (address addr){
assembly {
addr := mload(add(bys, 20))
}
}
function Decode(bytes memory signedString, string memory d) public pure returns (address){
bytes32 r = bytesToBytes32(slice(signedString, 0, 32));
bytes32 s = bytesToBytes32(slice(signedString, 32, 32));
bytes1 v = slice(signedString, 64, 1)[0];
bytes32 dd = keccak256(abi.encodePacked(d));
return ecrecoverDecode(r, s, v, dd);
}
function Decode(bytes memory signedString, address acc, uint256 t, string memory d) public pure returns (address){
bytes32 r = bytesToBytes32(slice(signedString, 0, 32));
bytes32 s = bytesToBytes32(slice(signedString, 32, 32));
bytes1 v = slice(signedString, 64, 1)[0];
bytes32 dd = keccak256(abi.encodePacked(acc,t,d));
return ecrecoverDecode(r, s, v, dd);
}
function slice(bytes memory data, uint start, uint len) internal pure returns (bytes memory){
bytes memory b = new bytes(len);
for (uint i = 0; i < len; i++) {
b[i] = data[i + start];
}
return b;
}
function ecrecoverDecode(bytes32 r, bytes32 s, bytes1 v1, bytes32 d) internal pure returns (address addr){
uint8 v = uint8(v1);
if (v == 0 || v == 1) {
v = v+27;
}
addr = ecrecover(d, v, r, s);
}
function bytesToBytes32(bytes memory source) internal pure returns (bytes32 result){
assembly{
result := mload(add(source, 32))
}
}
}
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
*/
library Counters {
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}
// OpenZeppelin/utils/Strings.sol
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
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);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
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);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed 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);
}
}
// OpenZeppelin/utils/Address.sol
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
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");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
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");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20Token {
using Address for address;
function safeTransfer(
IERC20Token token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20Token token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20Token token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20Token token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20Token token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20Token token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
\ No newline at end of file
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
library Bytes {
function BytesToUint256(bytes memory b) internal pure returns (uint256){
uint256 number;
for (uint i = 0; i < b.length; i++) {
number = number + uint8(b[i]) * (2 ** (8 * (b.length - (i + 1))));
}
return number;
}
function BytesToString(bytes memory source) internal pure returns (string memory result) {
return string(source);
}
function BytesToAddress(bytes memory bys) internal pure returns (address addr){
assembly {
addr := mload(add(bys, 20))
}
}
function Decode(bytes memory signedString, string memory d) internal pure returns (address){
bytes32 r = bytesToBytes32(slice(signedString, 0, 32));
bytes32 s = bytesToBytes32(slice(signedString, 32, 32));
uint8 v = uint8(signedString[64]);
bytes32 dd = keccak256(abi.encodePacked(d));
return ecrecoverDecode(r, s, v, dd);
}
function slice(bytes memory data, uint start, uint len) internal pure returns (bytes memory){
bytes memory b = new bytes(len);
for (uint i = 0; i < len; i++) {
b[i] = data[i + start];
}
return b;
}
function ecrecoverDecode(bytes32 r, bytes32 s, uint8 v1, bytes32 d) internal pure returns (address addr){
uint8 v = uint8(v1);
if (v == 0 || v == 1) {
v = v+27;
}
addr = ecrecover(d, v, r, s);
}
function bytesToBytes32(bytes memory source) internal pure returns (bytes32 result){
assembly{
result := mload(add(source, 32))
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "./BaseLib.sol";
import "./Auth.sol";
contract ERC20Token is Context, IERC20Token {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor (string memory n, string memory s, uint8 d) {
_name = n;
_symbol = s;
_decimals = d;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return _decimals;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
abstract contract ERC20TokenMinable is IERC20TokenMinable, ERC20Token, Program {
uint256 public maxTotalSupply;
uint256 public maxMintAmount;
uint256 public mintAmount = 0;
constructor (string memory name_, string memory symbol_, uint8 decimals_, uint8 unitDecimal_, uint256 maxTotalSupply_, uint256 maxMintAmount_, uint256 initAmount_, address initTo_) ERC20Token(name_, symbol_, decimals_) {
uint256 unit = 10 ** unitDecimal_;
maxTotalSupply = maxTotalSupply_ * unit;
maxMintAmount = maxMintAmount_ * unit;
if (maxMintAmount > maxTotalSupply) {
maxMintAmount = maxTotalSupply;
}
if (initAmount_ > 0)
{
_mint(initTo_ != address(0) ? initTo_ : msg.sender, initAmount_ * unit);
}
}
function mint(address to, uint256 amount) public override onlyProgram returns(bool) {
uint256 needMint = mintAmount + (amount);
if (needMint <= maxMintAmount)
{
uint256 realMint = needMint - (mintAmount);
_mint(to, realMint);
mintAmount = mintAmount + (realMint);
return true;
}
return false;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "./BaseLib.sol";
import "./Auth.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721Token is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping from token ID to URI
mapping(uint256 => bytes) private _uris;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : string(_uris[tokenId]);
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
function _safeMint(address to) internal virtual returns (uint256) {
return _safeMint(to, "");
}
function _safeMint(address to, bytes memory _data) internal virtual returns (uint256) {
_tokenIdCounter.increment();
uint256 tokenId = _tokenIdCounter.current();
_safeMint(to, tokenId, _data);
return tokenId;
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId, _data);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId, bytes memory _data) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
_uris[tokenId] = _data;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits a {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
abstract contract ERC721TokenMinable is IERC721TokenMinable, ERC721Token, Program {
constructor (string memory name, string memory symbol) ERC721Token(name, symbol) {
}
function mint(address to, bytes memory _data) public override onlyAdmin returns (uint256) {
return _safeMint(to, _data);
}
function mint(uint256 len, address to) public override onlyAdmin returns (uint256[] memory) {
return mint(len, to, bytes(""));
}
function mint(address to) public override onlyAdmin returns (uint256) {
return mint(to, bytes(""));
}
function mint(uint256 len, address to, string memory _data) public onlyAdmin returns (uint256[] memory) {
return mint(len, to, bytes(_data));
}
function mint(address to, string memory _data) public onlyAdmin returns (uint256) {
return mint(to, bytes(_data));
}
function mint(uint256 len, address to, bytes[] memory _data) public override onlyAdmin checkArraySize1(_data.length) returns (uint256[] memory) {
uint256[] memory ids = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
ids[i] = mint(to, _data[i]);
}
return ids;
}
function mint(uint256 len, address[] memory to, bytes[] memory _data) public override onlyAdmin checkArraySize2(to.length, _data.length) returns (uint256[] memory) {
uint256[] memory ids = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
ids[i] = mint(to[i], _data[i]);
}
return ids;
}
function mint(uint256 len, address to, bytes memory _data) public override onlyAdmin returns (uint256[] memory) {
uint256[] memory ids = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
ids[i] = mint(to, _data);
}
return ids;
}
function mint(uint256 len, address to, string[] memory _data) public onlyAdmin checkArraySize1(_data.length) returns (uint256[] memory) {
uint256[] memory ids = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
ids[i] = mint(to, _data[i]);
}
return ids;
}
function mint(uint256 len, address[] memory to, string[] memory _data) public onlyAdmin checkArraySize2(to.length, _data.length) returns (uint256[] memory) {
uint256[] memory ids = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
ids[i] = mint(to[i], _data[i]);
}
return ids;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
library String {
function StringToBytes(string memory source) internal pure returns (bytes memory result) {
return bytes(source);
}
function ParseAddr(string memory _a) internal pure returns (address _parsedAddress) {
bytes memory tmp = bytes(_a);
uint160 iaddr = 0;
uint160 b1;
uint160 b2;
for (uint i = 2; i < 2 + 2 * 20; i += 2) {
iaddr *= 256;
b1 = uint160(uint8(tmp[i]));
b2 = uint160(uint8(tmp[i + 1]));
if ((b1 >= 97) && (b1 <= 102)) {
b1 -= 87;
} else if ((b1 >= 65) && (b1 <= 70)) {
b1 -= 55;
} else if ((b1 >= 48) && (b1 <= 57)) {
b1 -= 48;
}
if ((b2 >= 97) && (b2 <= 102)) {
b2 -= 87;
} else if ((b2 >= 65) && (b2 <= 70)) {
b2 -= 55;
} else if ((b2 >= 48) && (b2 <= 57)) {
b2 -= 48;
}
iaddr += (b1 * 16 + b2);
}
return address(iaddr);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
library Uint256 {
function Uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {
b = new bytes(32);
assembly {mstore(add(b, 32), x)}
}
function BytesToUint256(bytes memory b) internal pure returns (uint256){
uint256 number;
for (uint i = 0; i < b.length; i++) {
number = number + uint8(b[i]) * (2 ** (8 * (b.length - (i + 1))));
}
return number;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract MinterAble is Initializable, OwnableUpgradeable {
mapping(address => bool) private minters;
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyMiner() {
require(minters[msg.sender], "!miner");
_;
}
function minter_initialize() public initializer {
__Ownable_init(msg.sender); // Initialize with the owner
}
function addMinter(address _minter) public onlyOwner {
minters[_minter] = true;
}
function removeMinter(address _minter) public onlyOwner {
minters[_minter] = false;
}
}
contract ArrayCheck is Initializable {
uint256 internal BATCH_COUNT;
function ac_initialize() public onlyInitializing {
BATCH_COUNT = 256;
}
modifier checkArraySizeUint256(uint256[] memory x) {
require(x.length > 0 && x.length <= BATCH_COUNT, "Too many elements in the array");
_;
}
modifier checkArraySizeAddress(address[] memory x) {
require(x.length > 0 && x.length <= BATCH_COUNT, "Too many elements in the array");
_;
}
modifier checkArraySizeString(string[] memory x) {
require(x.length > 0 && x.length <= BATCH_COUNT, "Too many elements in the array");
_;
}
modifier checkArraySize1(uint256 len1) {
require(len1 > 0 && len1 <= BATCH_COUNT, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize2(uint256 len1, uint256 len2) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize3(uint256 len1, uint256 len2, uint256 len3) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2 && len2 == len3, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize4(uint256 len1, uint256 len2, uint256 len3, uint256 len4) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2 && len2 == len3 && len3 == len4, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize5(uint256 len1, uint256 len2, uint256 len3, uint256 len4, uint256 len5) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2 && len2 == len3 && len3 == len4 && len4 == len5, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize6(uint256 len1, uint256 len2, uint256 len3, uint256 len4, uint256 len5, uint256 len6) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2 && len2 == len3 && len3 == len4 && len4 == len5 && len5 == len6, "The size of These Arrays must be equal");
_;
}
modifier checkArraySize7(uint256 len1, uint256 len2, uint256 len3, uint256 len4, uint256 len5, uint256 len6, uint256 len7) {
require(len1 > 0 && len1 <= BATCH_COUNT && len1 == len2 && len2 == len3 && len3 == len4 && len4 == len5 && len5 == len6 && len6 == len7, "The size of These Arrays must be equal");
_;
}
}
contract Admin is Initializable, OwnableUpgradeable, ArrayCheck {
mapping(address => bool) private _admins;
modifier onlyAdmin() {
/*
if (!_admins[msg.sender]) {
console.log("onlyAdmin", address(this), msg.sender);
}
*/
require(_admins[msg.sender], "Only admin can call it");
_;
}
function admin_initialize() internal onlyInitializing {
__Ownable_init(msg.sender); // Initialize with the owner
_admins[msg.sender] = true; // Set the initial owner as admin
ac_initialize();
}
function addAdmins(address[] memory admins_) public onlyOwner checkArraySizeAddress(admins_) {
for (uint256 i = 0; i < admins_.length; i++) {
addAdmin(admins_[i]);
}
}
function delAdmins(address[] memory admins_) public onlyOwner checkArraySizeAddress(admins_) {
for (uint256 i = 0; i < admins_.length; i++) {
delAdmin(admins_[i]);
}
}
function addAdmin(address admin_) public onlyOwner {
_admins[admin_] = true;
// console.log("addAdmin", address(this), _admin);
}
function delAdmin(address admin_) public onlyOwner {
_admins[admin_] = false;
// console.log("delAdmin", address(this), _admin);
}
function isAdmin(address _addr) public view returns (bool) {
return _admins[_addr];
}
}
contract Program is Admin {
// using Address for address;
mapping(address => bool) private _programs;
modifier onlyProgram() {
require(_programs[msg.sender], "Only program can call it");
_;
}
function program_initialize() internal onlyInitializing {
admin_initialize();
}
function addPrograms(address[] memory programs_) public onlyOwner checkArraySizeAddress(programs_) {
for (uint256 i = 0; i < programs_.length; i++) {
addProgram(programs_[i]);
}
}
function delPrograms(address[] memory programs_) public onlyOwner checkArraySizeAddress(programs_) {
for (uint256 i = 0; i < programs_.length; i++) {
delProgram(programs_[i]);
}
}
function addProgram(address _program) public onlyOwner {
//require(_program.isContract(), "Only contract can be a program");
_programs[_program] = true;
}
function delProgram(address program_) public onlyOwner {
_programs[program_] = false;
}
function isProgram(address program_) public view returns (bool) {
return _programs[program_];
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/BaseLib.sol";
import "../library/UpgradeableAuth.sol";
interface IMysteryBox {
function nftAddress(string memory) external view returns(address);
function sellPrice(string memory, address) external view returns(uint256);
function nftToken(string memory _name, uint256 idx) external view returns(uint256);
function totalSupply(string memory) external view returns(uint256);
function soldCount(string memory) external view returns(uint256);
function moneyBackChance(string memory) external view returns(uint256);
function probability(string memory, string memory) external view returns(uint256);
function set(string[] memory _names, address[] memory _nft, uint256[] memory _moneyBackChance) external;
function setPrice(string memory _name, address[] memory _tokens, uint256[] memory _prices) external;
function setProbability(string memory _name, string[] memory _types, uint256[] memory _probabilities) external;
function addToken(string memory _name, uint256 start, uint256 end) external;
function addToken(string memory _name, uint256[] memory _tokens) external;
function removeToken(string memory _name, uint256 count) external;
function giveToken(string memory _name, uint256 idx) external returns(uint256);
}
contract MysteryBox is IMysteryBox, Program {
mapping(string => address) public override nftAddress;
mapping(string => mapping(address => uint256)) public override sellPrice;
mapping(string => uint256) public override soldCount;
mapping(string => uint256) public override moneyBackChance;
mapping(string => mapping(string => uint256)) public override probability;
mapping(string => uint256[]) private _nftToken;
function initialize() public initializer {
program_initialize();
}
function totalSupply(string memory _name) public view override returns(uint256) {
return _nftToken[_name].length;
}
function nftToken(string memory _name, uint256 idx) public onlyProgram view override returns(uint256) {
return idx < _nftToken[_name].length ? _nftToken[_name][idx] : 0;
}
function set(string[] memory _names, address[] memory _nft, uint256[] memory _moneyBackChance) public override onlyProgram
checkArraySize3(_names.length, _nft.length, _moneyBackChance.length) {
for (uint256 i = 0; i < _names.length; i++) {
string memory _name = _names[i];
nftAddress[_name] = _nft[i];
moneyBackChance[_name] = _moneyBackChance[i];
}
}
function setPrice(string memory _name, address[] memory _tokens, uint256[] memory _prices) public override onlyProgram
checkArraySize2(_tokens.length, _prices.length) {
for (uint256 i = 0; i < _tokens.length; i++) {
sellPrice[_name][_tokens[i]] = _prices[i];
}
}
function setProbability(string memory _name, string[] memory _types, uint256[] memory _probabilities) public override onlyProgram
checkArraySize2(_types.length, _probabilities.length) {
for (uint256 i = 0; i < _types.length; i++) {
probability[_name][_types[i]] = _probabilities[i];
}
}
function addToken(string memory _name, uint256 start, uint256 end) public override onlyProgram {
require(end >= start && end <= (start + BATCH_COUNT), "Too many elements in the array");
for (uint256 i = start; i <= end; i++) {
_nftToken[_name].push(i);
}
}
function addToken(string memory _name, uint256[] memory _tokens) public override onlyProgram checkArraySizeUint256(_tokens) {
for (uint256 i = 0; i < _tokens.length; i++) {
_nftToken[_name].push(_tokens[i]);
}
}
function removeToken(string memory _name, uint256 count) public override onlyProgram {
for (uint256 i = 0; i < count; i++) {
_nftToken[_name].pop();
}
}
function giveToken(string memory _name, uint256 idx) public override onlyProgram returns(uint256) {
if (idx >= _nftToken[_name].length) {
return 0;
}
uint256 nft_id = _nftToken[_name][idx];
_nftToken[_name][idx] = 0;
soldCount[_name]++;
return nft_id;
}
}
interface IMysteryData {
function boxCount(address _account) external view returns(uint256);
function nftAddress(address _account, uint256 idx) external view returns(address);
function tokenAddress(address _account, uint256 idx) external view returns(address);
function createdTime(address _account, uint256 idx) external view returns(uint256);
function nftToken(address _account, uint256 idx) external view returns(uint256);
function amountMoneyBack(address _account, uint256 idx) external view returns(uint256);
function add(address _account, address tokenAddr, address nftAddr, uint256 token_id, uint256 amount) external;
function remove(address _account) external returns(address, address, uint256, uint256, uint256);
}
contract MysteryData is IMysteryData, Program {
mapping(address => address[]) public override nftAddress;
mapping(address => address[]) public override tokenAddress;
mapping(address => uint256[]) public override createdTime;
mapping(address => uint256[]) private _nftToken;
mapping(address => uint256[]) private _amountMoneyBack;
function initialize() public initializer {
program_initialize();
}
function boxCount(address _account) public view override returns(uint256) {
return _nftToken[_account].length;
}
function nftToken(address _account, uint256 idx) public onlyProgram view override returns(uint256) {
return idx < _nftToken[_account].length ? _nftToken[_account][idx] : 0;
}
function amountMoneyBack(address _account, uint256 idx) public onlyProgram view override returns(uint256) {
return idx < _amountMoneyBack[_account].length ? _amountMoneyBack[_account][idx] : 0;
}
function add(address _account, address tokenAddr, address nftAddr, uint256 token_id, uint256 amount) public override onlyProgram {
nftAddress[_account].push(nftAddr);
tokenAddress[_account].push(tokenAddr);
_nftToken[_account].push(token_id);
_amountMoneyBack[_account].push(amount);
createdTime[_account].push(block.timestamp);
}
function remove(address _account) public override onlyProgram returns(address, address, uint256, uint256, uint256) {
require(_nftToken[_account].length > 0, "No mystery data can be removed");
uint256 idx = _nftToken[_account].length - 1;
address nftAddr = nftAddress[_account][idx];
address tokenAddr = tokenAddress[_account][idx];
uint256 token_id = _nftToken[_account][idx];
uint256 amount = _amountMoneyBack[_account][idx];
uint256 time = createdTime[_account][idx];
nftAddress[_account].pop();
tokenAddress[_account].pop();
createdTime[_account].pop();
_nftToken[_account].pop();
_amountMoneyBack[_account].pop();
return (nftAddr, tokenAddr, token_id, amount, time);
}
}
interface IWhitelist {
function enable() external view returns(bool);
function inList(address _account) external view returns(uint256);
function usedCount(address _account) external view returns(uint256);
function used(address _account) external;
}
contract Whitelist is IWhitelist, Program {
mapping(address => uint256) private _whitelist;
mapping(address => uint256) private _usedInList;
mapping(address => uint256) private _usedOutList;
bool private _enable;
function initialize() public initializer {
program_initialize();
}
function enable() public onlyProgram view override returns(bool) {
return _enable;
}
function enable(bool b) public onlyAdmin {
_enable = b;
}
function add(address[] memory _accounts, uint256[] memory v) public onlyAdmin checkArraySize2(_accounts.length, v.length) {
for (uint256 i = 0; i < _accounts.length; i++) {
_whitelist[_accounts[i]] = v[i];
}
}
function add(address[] memory _accounts, uint256 v) public onlyAdmin checkArraySizeAddress(_accounts) {
for (uint256 i = 0; i < _accounts.length; i++) {
_whitelist[_accounts[i]] = v;
}
}
function remove(address[] memory _accounts) public onlyAdmin checkArraySizeAddress(_accounts) {
for (uint256 i = 0; i < _accounts.length; i++) {
_whitelist[_accounts[i]] = 0;
}
}
function inList(address _account) public onlyProgram view override returns(uint256) {
return _whitelist[_account];
}
function usedCount(address _account) public onlyProgram view override returns(uint256) {
return _enable && inList(_account) > 0 ? _usedInList[_account] : _usedOutList[_account];
}
function used(address _account) public onlyProgram override {
if (_enable && inList(_account) > 0) {
_usedInList[_account]++;
} else {
_usedOutList[_account]++;
}
}
}
interface IRandom {
function rand(address _acc, uint256 _time, string memory _rand, bytes memory _sign) external returns(uint256);
}
contract Random is Program {
using Bytes for bytes;
address private signAccount;
uint256 private signExpTime;
function initialize() public initializer {
program_initialize();
signExpTime = 1 minutes;
}
function setSettings(address _signAccount, uint256 _signExpTime) public onlyAdmin {
signAccount = _signAccount;
signExpTime = _signExpTime;
}
function rand(address _acc, uint256 _time, string memory _rand, bytes memory _sign) public onlyProgram view returns(uint256) {
return _randV1(_acc, _time, _rand, _sign);
}
function _randV1(address _acc, uint256 _time, string memory _rand, bytes memory) internal view returns(uint256) {
return uint256(keccak256(abi.encodePacked(_acc, _time, _rand, block.coinbase,
block.difficulty, block.timestamp, blockhash(block.number))));
}
function _randV2(address _acc, uint256 _time, string memory _rand, bytes memory _sign) internal view returns(uint256) {
require(_sign.Decode(_acc, _time, _rand) == signAccount, "Check sign error");
require((_time + signExpTime) < block.timestamp, "Check sign expired");
return uint256(keccak256(abi.encodePacked(_acc, _time, _rand, block.coinbase,
block.difficulty, block.timestamp, blockhash(block.number))));
}
}
interface INFTMysteryBoxOffering {
function totalSupply(string memory _name) external view returns(uint256);
function soldCount(string memory _name) external view returns(uint256);
function moneyBackChance(string memory _name) external view returns(uint256);
function soldPrice(string memory _name, address _token) external view returns(uint256);
function probability(string memory _name, string memory _type) external view returns(uint256);
function discountPrice(string memory _name, address _token) external view returns(uint256);
function getDiscount() external view returns(uint256);
function getOpenResult(string memory _openId) external view returns(uint256[] memory, string[] memory);
function isSoldOut(string memory _name) external view returns(bool);
function getBoxCount(string memory _name) external view returns(uint256,uint256,uint256);
function isWhitelistEnable() external view returns (bool);
function inWhitelist() external view returns (bool);
function isLimitBuy(address _account) external view returns(bool);
function getLimitCount(address _account) external view returns(uint256,uint256,uint256);
function buy(string memory _name, address _tokenAddr, string memory _rnd, uint256 _time, bytes memory _sign) external;
function buy(string memory _name, address _tokenAddr) external;
function buyAndOpen(string memory _openId, string memory _name, address _tokenAddr, string memory _rnd, uint256 _time, bytes memory _sign) external returns(uint256[] memory, string[] memory);
function buyAndOpen(string memory _openId, string memory _name, address _tokenAddr) external returns(uint256[] memory, string[] memory);
function openAll(string memory _openId) external returns(uint256[] memory, string[] memory);
function openOne(string memory _openId) external returns(uint256, string memory);
}
contract NFTMysteryBoxOffering is INFTMysteryBoxOffering, Program {
using SafeERC20Token for IERC20Token;
using SafeERC20Token for IERC20TokenMinable;
IRandom private random;
IMysteryBox private mysteryBox;
IMysteryData private mysteryData;
IWhitelist private whitelist;
IERC20TokenMinable private rewardToken;
address private tokenAccount;
address private nftAccount;
bool private rewardMint;
uint256 private openExpiredTime ;
uint256 private limitWhitelist;
uint256 private limitCommonUser;
uint256 private discountWhitelist ;
uint256 private discountCommonUser ;
uint256 private maxRewardAmount ;
uint256 private rewardedAmount ;
uint256 private rewardPercent ;
mapping(address => mapping(string => uint256[])) private openedNftId;
mapping(address => mapping(string => string[])) private openedNftUri;
event Buy(address indexed nftAddress, address indexed tokenAddress, uint256 price, uint256 discount, uint256 amount, uint256 amountReward);
event Open(address indexed nftAddress, address indexed tokenAddress, address indexed account, uint256 token_id, uint256 amountBack);
function initialize() public initializer {
program_initialize();
rewardMint = false;
openExpiredTime = 7 days;
limitWhitelist = 200;
limitCommonUser = 300;
discountWhitelist = 8500;
discountCommonUser = 10000;
maxRewardAmount = 10500000 * PRICE_UNIT;
rewardedAmount = 0;
rewardPercent = 1000;
}
function setSettings(uint256 rewardPercent_, uint256 maxRewardAmount_, bool rewardMint_, uint256 openExpiredTime_, uint256 limitWhitelist_, uint256 limitCommonUser_, uint256 discountWhitelist_, uint256 discountCommonUser_) public onlyAdmin {
rewardPercent = rewardPercent_;
maxRewardAmount = maxRewardAmount_;
rewardMint = rewardMint_;
openExpiredTime = openExpiredTime_;
limitWhitelist = limitWhitelist_;
limitCommonUser = limitCommonUser_;
discountWhitelist = discountWhitelist_;
discountCommonUser = discountCommonUser_;
}
function setContracts(address random_, address mysteryBox_, address mysteryData_, address whitelist_,
address rewardToken_) public onlyAdmin {
random = IRandom(random_);
mysteryBox = IMysteryBox(mysteryBox_);
mysteryData = IMysteryData(mysteryData_);
whitelist = IWhitelist(whitelist_);
rewardToken = IERC20TokenMinable(rewardToken_);
}
function setAccounts(address tokenAccount_, address nftAccount_) public onlyAdmin {
tokenAccount = tokenAccount_;
nftAccount = nftAccount_;
}
function nftAddress(string memory _name) public onlyAdmin view returns(address) {
return mysteryBox.nftAddress(_name);
}
function nftToken(string memory _name, uint256 idx) public onlyAdmin view returns(uint256) {
return mysteryBox.nftToken(_name, idx);
}
function totalSupply(string memory _name) public override view returns(uint256) {
return mysteryBox.totalSupply(_name);
}
function soldCount(string memory _name) public override view returns(uint256) {
return mysteryBox.soldCount(_name);
}
function moneyBackChance(string memory _name) public override view returns(uint256) {
return mysteryBox.moneyBackChance(_name);
}
function soldPrice(string memory _name, address _token) public override view returns(uint256) {
return mysteryBox.sellPrice(_name, _token);
}
function probability(string memory _name, string memory _type) public override view returns(uint256) {
return mysteryBox.probability(_name, _type);
}
function setBox(string[] memory _names, address[] memory _nft, uint256[] memory _moneyBackChance) public onlyAdmin {
mysteryBox.set(_names, _nft, _moneyBackChance);
}
function setPrice(string memory _name, address[] memory _tokens, uint256[] memory _prices) public onlyAdmin {
mysteryBox.setPrice(_name, _tokens, _prices);
}
function setProbability(string memory _name, string[] memory _types, uint256[] memory _probabilities) public onlyAdmin {
mysteryBox.setProbability(_name, _types, _probabilities);
}
function addToken(string memory _name, uint256 start, uint256 end) public onlyAdmin {
mysteryBox.addToken(_name, start, end);
IERC721Token _nft = IERC721Token(mysteryBox.nftAddress(_name));
for (uint256 i = start; i <= end; i++) {
address owner = _nft.ownerOf(i);
if (owner != address(0) && (owner != nftAccount)) {
_nft.safeTransferFrom(owner, nftAccount, i);
}
}
}
function addToken(string memory _name, uint256[] memory _tokens) public onlyAdmin checkArraySizeUint256(_tokens) {
mysteryBox.addToken(_name, _tokens);
IERC721Token _nft = IERC721Token(mysteryBox.nftAddress(_name));
for (uint256 i = 0; i <= _tokens.length; i++) {
uint256 NFT_id = _tokens[i];
address owner = _nft.ownerOf(NFT_id);
if (owner != address(0) && (owner != nftAccount)) {
_nft.safeTransferFrom(owner, nftAccount, NFT_id);
}
}
}
function removeToken(string memory _name, uint256 count, address to) public onlyAdmin {
uint256 len = mysteryBox.totalSupply(_name);
IERC721Token _nft = IERC721Token(mysteryBox.nftAddress(_name));
require(count <= len, "Remove count is error");
for (uint256 i = 1; i <= count; i++) {
uint256 NFT_id = mysteryBox.nftToken(_name, len - i);
if (NFT_id > 0) {
address owner = _nft.ownerOf(NFT_id);
if (owner != address(0) && (owner != nftAccount)) {
_nft.safeTransferFrom(nftAccount, to, NFT_id);
}
}
}
mysteryBox.removeToken(_name, count);
}
function buy(string memory _name, address _tokenAddr, string memory _rnd, uint256 _time, bytes memory _sign) public override {
require(!isLimitBuy(msg.sender), "It reaches max buying limit");
uint256 rnd_num = random.rand(msg.sender, _time, _rnd, _sign);
require(rnd_num > 0, "Rand check is error");
uint256 total = mysteryBox.totalSupply(_name);
uint256 sold = mysteryBox.soldCount(_name);
require(sold < total, "The mystery which you want sold out");
uint256 left = total - sold;
uint256 idx = _getNotEmptyBox(_name, rnd_num % left);
_deal(_name, idx, IERC20Token(_tokenAddr), msg.sender, rnd_num);
}
function buy(string memory _name, address _tokenAddr) public override {
buy(_name, _tokenAddr, "", block.timestamp, "");
}
function buyAndOpen(string memory _openId, string memory _name, address _tokenAddr, string memory _rnd, uint256 _time, bytes memory _sign) public override returns(uint256[] memory, string[] memory) {
buy(_name, _tokenAddr, _rnd, _time, _sign);
return openAll(_openId);
}
function buyAndOpen(string memory _openId, string memory _name, address _tokenAddr) public override returns(uint256[] memory, string[] memory) {
return buyAndOpen(_openId, _name, _tokenAddr, "", block.timestamp, "");
}
function openAll(string memory _openId) public override returns(uint256[] memory, string[] memory) {
uint256 len = mysteryData.boxCount(msg.sender);
uint256[] memory ids = new uint256[](len);
string[] memory uris = new string[](len);
for (uint256 i = 0; i < len; i++) {
(ids[i], uris[i]) = openOne(_openId);
}
return (ids, uris);
}
function openOne(string memory _openId) public override returns(uint256, string memory) {
uint256 len = mysteryData.boxCount(msg.sender);
if (len == 0) {
return (0, "");
}
uint256 idx = len - 1;
IERC721Token _nft = IERC721Token(mysteryData.nftAddress(msg.sender, idx));
IERC20Token _token = IERC20Token(mysteryData.tokenAddress(msg.sender, idx));
uint256 token_id = mysteryData.nftToken(msg.sender, idx);
if (token_id > 0)
{
_nft.safeTransferFrom(nftAccount, msg.sender, token_id);
}
uint256 amountBack = mysteryData.amountMoneyBack(msg.sender, idx);
if (amountBack > 0 && (mysteryData.createdTime(msg.sender, idx) + openExpiredTime) >= block.timestamp) {
_token.safeTransferFrom(tokenAccount, msg.sender, amountBack);
}
mysteryData.remove(msg.sender);
openedNftId[msg.sender][_openId].push(token_id);
openedNftUri[msg.sender][_openId].push(_nft.tokenURI(token_id));
emit Open(address(_nft), address(_token), msg.sender, token_id, amountBack);
return (token_id, _nft.tokenURI(token_id));
}
function getOpenResult(string memory _openId) public override view returns(uint256[] memory, string[] memory) {
return (openedNftId[msg.sender][_openId], openedNftUri[msg.sender][_openId]);
}
function _deal(string memory _name, uint256 idx, IERC20Token token, address _account, uint256 rnd_num) internal {
uint256 token_id = mysteryBox.nftToken(_name, idx);
require(token_id > 0, "NFT is not exist");
(uint256 price,uint256 discount,uint256 amount, uint256 moneyBack) = _getPriceAmount(_name, token, rnd_num);
mysteryData.add(_account, address(token), mysteryBox.nftAddress(_name), token_id, moneyBack);
mysteryBox.giveToken(_name, idx);
whitelist.used(msg.sender);
require(token.balanceOf(_account) >= amount, "You have not enough money");
token.safeTransferFrom(_account, tokenAccount, amount);
uint256 amountReward = 0;
if (address(rewardToken) != address(0) && (amount > moneyBack)) {
uint256 needReward = (amount - moneyBack) * rewardPercent / (10 ** token.decimals());
if ((rewardedAmount + needReward) < maxRewardAmount) {
rewardedAmount = rewardedAmount + needReward;
amountReward = (needReward * (10 ** rewardToken.decimals())) / PRICE_UNIT;
if (rewardMint) {
rewardToken.mint(_account, amountReward);
} else {
rewardToken.safeTransferFrom(tokenAccount, _account, amountReward);
}
}
}
emit Buy(mysteryBox.nftAddress(_name), address(token), price, discount, amount, amountReward);
}
function _getPriceAmount(string memory _name, IERC20Token token, uint256 rnd_num) internal view returns(uint256,uint256,uint256,uint256) {
uint256 price = mysteryBox.sellPrice(_name, address(token));
require(price > 0, "Unsupported token to buy");
uint256 discount = _getDiscount(msg.sender);
uint256 amount = (price * (10 ** token.decimals()) / PRICE_UNIT) * discount / PERCENT_UNIT;
uint256 moneyBack = rnd_num % PERCENT_UNIT < mysteryBox.moneyBackChance(_name) ? amount : 0;
return (price, discount, amount, moneyBack);
}
function _getNotEmptyBox(string memory _name, uint256 idx) internal view returns(uint256) {
uint256 len = mysteryBox.totalSupply(_name);
uint256 k = 0;
for (uint256 i = 0; i < len; i++) {
if (mysteryBox.nftToken(_name, i) > 0) {
if (k == idx) {
return i;
}
k++;
}
}
return len;
}
function discountPrice(string memory _name, address _token) public override view returns(uint256) {
return soldPrice(_name, _token) * getDiscount() / PERCENT_UNIT;
}
function getDiscount() public override view returns(uint256) {
return _getDiscount(msg.sender);
}
function _getDiscount(address _account) internal view returns(uint256) {
return whitelist.enable() ? (whitelist.inList(_account) > 0 ? discountWhitelist : PERCENT_UNIT) : discountCommonUser;
}
function isSoldOut(string memory _name) public override view returns(bool) {
return soldCount(_name) >= totalSupply(_name);
}
function getBoxCount(string memory _name) public override view returns(uint256,uint256,uint256) {
uint256 totalSupply_ = totalSupply(_name);
uint256 soldCount_ = soldCount(_name);
return ((totalSupply_ - soldCount_), totalSupply_, soldCount_);
}
function isWhitelistEnable() public override view returns (bool) {
return whitelist.enable();
}
function inWhitelist() public override view returns (bool) {
return whitelist.inList(msg.sender) > 0;
}
function isLimitBuy(address _account) public override view returns(bool) {
uint256 usedCount = whitelist.usedCount(_account);
return whitelist.enable() ? (whitelist.inList(_account) > 0 ? (usedCount >= limitWhitelist) : true) : (usedCount >= limitCommonUser);
}
function getLimitCount(address _account) public override view returns(uint256, uint256, uint256) {
uint256 usedCount = whitelist.usedCount(_account);
uint256 limitCount = whitelist.inList(_account) > 0 ? limitWhitelist : limitCommonUser;
return (limitCount - usedCount, limitCount, usedCount);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/BaseLib.sol";
import "../library/UpgradeableAuth.sol";
contract RaceBonusDistribute is IRaceBonusDistribute, Program {
using SafeERC20Token for IERC20TokenMinable;
IERC721Token public bonusNFT;
uint256 public rewardPercentOfRaceCourse;
uint256[] public rewardPercentOfWinners;
address[] public rewardAddressOfOthers;
uint256[] public rewardPercentOfOthers;
IRaceBonusPool[] public bonusPool;
event Distribute(address indexed _raceCourse, uint256[] _tokenIds, uint256 _money);
function initialize() public initializer {
program_initialize();
}
function setSettings(uint256 _rewardPercentOfRaceCourse, uint256[] memory _rewardPercentOfWinners,
address[] memory _rewardAddressOfOthers, uint256[] memory _rewardPercentOfOthers, IRaceBonusPool[] memory _bonusPool, address nfttoken) public onlyAdmin {
rewardPercentOfRaceCourse = _rewardPercentOfRaceCourse;
rewardPercentOfWinners = _rewardPercentOfWinners;
rewardAddressOfOthers = _rewardAddressOfOthers;
rewardPercentOfOthers = _rewardPercentOfOthers;
bonusPool = _bonusPool;
bonusNFT = IERC721Token(nfttoken);
}
function distribute(address _raceCourse, uint256[] memory _tokenIds, uint256 _money) public override onlyProgram checkArraySizeUint256(_tokenIds) returns (uint256, address[] memory, uint256[] memory) {
uint256 len = _tokenIds.length + rewardAddressOfOthers.length + 1;
address[] memory lstAddress = new address[](len);
uint256[] memory lstAmount = new uint256[](len);
uint256 count = 0;
lstAddress[count] = _raceCourse;
lstAmount[count] = _money * rewardPercentOfRaceCourse / 10000;
count++;
//bonusToken.safeTransferFrom(tokenAccount, _raceCourse, _money.mul(rewardPercentOfRaceCourse).div(10000));
for (uint256 k = 0; k < _tokenIds.length; k++) {
uint256 percent = rewardPercentOfWinners[k];
if (percent > 0) {
lstAddress[count] = bonusNFT.ownerOf(_tokenIds[k]);
lstAmount[count] = _money * percent / 10000;
count++;
//bonusToken.safeTransferFrom(tokenAccount, bonusNFT.ownerOf(_tokenIds[k]), _money.mul(percent).div(10000));
}
}
for (uint256 i = 0; i < rewardAddressOfOthers.length; i++) {
uint256 percent = rewardPercentOfOthers[i];
if (percent > 0) {
lstAddress[count] = rewardAddressOfOthers[i];
lstAmount[count] = _money * percent / 10000;
count++;
//bonusToken.safeTransferFrom(tokenAccount, rewardAddressOfOthers[i], _money.mul(percent).div(10000));
}
}
for (uint256 i = 0; i < bonusPool.length; i++) {
bonusPool[i].distribute(_raceCourse, _tokenIds, _money, count, lstAddress, lstAmount);
}
emit Distribute(_raceCourse, _tokenIds, _money);
return (count, lstAddress, lstAmount);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/BaseLib.sol";
import "../library/UpgradeableAuth.sol";
interface IRaceBonusData {
function totalMoney(address,uint256) external returns(uint256);
function activityCount(address,uint256,uint256) external returns(uint256);
function isUnclaim(address,uint256,uint256) external returns(bool);
function isReward(address,uint256,uint256) external returns(bool);
function rewardCount(address,uint256) external returns(uint256);
function addActivity(address _nftAddr, uint256 _year, uint256[] memory _tokenIds, uint256 _money) external;
function claim(address _nftAddr, uint256 _year, uint256 _tokenId) external;
function sync(address _nftAddr, uint256 _year, uint256 _tokenId) external;
}
contract RaceBonusData is IRaceBonusData, Program {
mapping(address => mapping(uint256 => uint256)) public override totalMoney;
mapping(address => mapping(uint256 => mapping(uint256 => uint256))) public override activityCount;
mapping(address => mapping(uint256 => mapping(uint256 => bool))) public override isReward;
mapping(address => mapping(uint256 => mapping(uint256 => bool))) public override isUnclaim;
mapping(address => mapping(uint256 => uint256)) public override rewardCount;
uint256 public ACTIVITY_LIMIT;
function initialize() public initializer {
program_initialize();
ACTIVITY_LIMIT = 300;
}
function setSettings(uint256 _activityLimit) public onlyAdmin {
ACTIVITY_LIMIT = _activityLimit;
}
function addActivity(address _nftAddr, uint256 _year, uint256[] memory _tokenIds, uint256 _money) public override onlyProgram checkArraySizeUint256(_tokenIds) {
totalMoney[_nftAddr][_year] = totalMoney[_nftAddr][_year] + (_money);
for (uint256 i = 0; i < _tokenIds.length; i++) {
uint256 _tokenId = _tokenIds[i];
activityCount[_nftAddr][_year][_tokenId] = activityCount[_nftAddr][_year][_tokenId] + (1);
sync(_nftAddr, _year, _tokenId);
}
}
function claim(address _nftAddr, uint256 _year, uint256 _tokenId) public override onlyProgram {
isUnclaim[_nftAddr][_year][_tokenId] = false;
}
function sync(address _nftAddr, uint256 _year, uint256 _tokenId) public override onlyProgram {
bool needReward = (activityCount[_nftAddr][_year][_tokenId] >= ACTIVITY_LIMIT);
if (isReward[_nftAddr][_year][_tokenId] != needReward) {
isReward[_nftAddr][_year][_tokenId] = needReward;
isUnclaim[_nftAddr][_year][_tokenId] = needReward;
if (needReward) {
rewardCount[_nftAddr][_year] = rewardCount[_nftAddr][_year] + (1);
} else {
rewardCount[_nftAddr][_year] = rewardCount[_nftAddr][_year]- (1);
}
}
}
}
contract RaceBonusPool is IRaceBonusPool, Program {
using SafeERC20Token for IERC20TokenMinable;
IRaceBonusData private bonusData;
IERC20TokenMinable public bonusToken;
IERC721Token public bonusNFT;
address public tokenAccount;
uint256 public startTime ;
uint256 public durationUnit ;
uint256 public durationBonus ;
event Distribute(address indexed _raceCourse, uint256[] _tokenIds, uint256 _money);
event Claim(address indexed account, uint256 amount);
function initialize() public initializer {
program_initialize();
startTime = 0;
durationUnit = 1 days;
durationBonus = 365.25 days;
}
function setSettings(uint256 _durationUnit, uint256 _durationBonus) public onlyAdmin {
durationUnit = _durationUnit;
durationBonus = _durationBonus * durationUnit;
}
function setContracts(address _bonusData, address _bonusToken, address _bonusNFT,
address _tokenAccount) public onlyAdmin {
bonusData = IRaceBonusData(_bonusData);
bonusToken = IERC20TokenMinable(_bonusToken);
bonusNFT = IERC721Token(_bonusNFT);
tokenAccount = _tokenAccount;
}
function distribute(address _raceCourse, uint256[] memory _tokenIds, uint256 _money, uint256, address[] memory, uint256[] memory) public override onlyProgram checkArraySizeUint256(_tokenIds) {
if (startTime == 0) {
startTime = block.timestamp / durationUnit * durationUnit;
}
uint256 _year = _getYear(block.timestamp);
bonusData.addActivity(address(bonusNFT), _year, _tokenIds, _money);
emit Distribute(_raceCourse, _tokenIds, _money);
}
function claim(uint256 nft_id) public override {
require(bonusNFT.ownerOf(nft_id) == msg.sender, "You must be the owner of the NFT");
uint256 _year = _getYear(block.timestamp);
bonusData.sync(address(bonusNFT), _year, nft_id);
for (uint i = 0; i < _year; i++) {
bonusData.sync(address(bonusNFT), i, nft_id);
uint256 yearMoney = bonusData.totalMoney(address(bonusNFT), i);
uint256 yearCount = bonusData.rewardCount(address(bonusNFT), i);
if (bonusData.isUnclaim(address(bonusNFT), i, nft_id) && yearMoney > 0 && yearCount > 0) {
uint256 rewardAmount = yearMoney/yearCount;
bonusToken.safeTransferFrom(tokenAccount, msg.sender, rewardAmount);
bonusToken.mint(msg.sender, rewardAmount);
bonusData.claim(address(bonusNFT), i, nft_id);
}
}
}
function _getYear(uint256 t) public view returns(uint256) {
if (t <= startTime) {
return 0;
}
return ((t / durationUnit) * durationUnit - startTime) / durationBonus;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Auth.sol";
contract TestTxTime is Admin{
uint256[] public txTime;
uint256[] public blockTime;
function lenTime() public view returns(uint256) {
return txTime.length;
}
function getTime(uint256 i) public view returns(uint256,uint256) {
return (blockTime[i], txTime[i]);
}
function test(uint256 t) public onlyAdmin {
blockTime.push(block.timestamp * 1000);
txTime.push(t);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/ERC20Token.sol";
uint8 constant DECIMAL_TOKEN = 18;
uint256 constant Thousand = 10 ** 3;
uint256 constant MILLION = 10 ** 6;
uint256 constant BILLION = 10 ** 9;
abstract contract BaseERC20TokenMinable is ERC20TokenMinable {
constructor(string memory name, string memory symbol, uint256 maxTotalSupply, uint256 maxMintAmount, uint256 initAmount) ERC20TokenMinable(name, symbol, DECIMAL_TOKEN, DECIMAL_TOKEN, maxTotalSupply, maxMintAmount, initAmount, address(0)) {}
}
contract MetaToken is BaseERC20TokenMinable {
constructor() BaseERC20TokenMinable("v01.META.TEST", "v01.META.TEST", 210 * MILLION, 73500 * Thousand, 136500 * Thousand) {}
}
contract RaceToken is BaseERC20TokenMinable {
constructor() BaseERC20TokenMinable("v01.RACE.TEST", "v01.RACE.TEST", 10 * BILLION, 9900 * MILLION, 100 * MILLION) {}
}
contract UsdtToken is BaseERC20TokenMinable {
constructor() BaseERC20TokenMinable("v01.USDT.TEST", "v01.USDT.TEST", 10 * BILLION, 0, 10 * BILLION) {}
}
\ No newline at end of file
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/ERC721Token.sol";
abstract contract BaseERC721TokenMinable is ERC721TokenMinable {
IERC721BeforeTransfer private _beforeTransfer;
IERC721AfterTransfer private _afterTransfer;
constructor(string memory name_, string memory symbol_) ERC721TokenMinable(name_, symbol_) {}
function registerTransferHandler(address beforehandler, address afterhandler) public onlyAdmin {
_beforeTransfer = IERC721BeforeTransfer(beforehandler);
_afterTransfer = IERC721AfterTransfer(afterhandler);
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
override(ERC721Token)
{
if (address(_beforeTransfer) != address(0) )
{
require(_beforeTransfer.beforeTransfer(from, to, tokenId), "stop transfer before ttransfer check failed");
}
super._beforeTokenTransfer(from, to, tokenId);
}
function _afterTokenTransfer(address from, address to, uint256 tokenId)
internal
override(ERC721Token)
{
super._afterTokenTransfer(from, to, tokenId);
if (address(_afterTransfer) != address(0) )
{
require(_afterTransfer.afterTransfer(from, to, tokenId), "stop transfer after transfer check failed");
}
}
}
contract HorseToken is BaseERC721TokenMinable {
constructor() BaseERC721TokenMinable("v01.HORSE.TEST", "v01.HORSE.TEST") {}
}
contract EquipToken is BaseERC721TokenMinable {
constructor() BaseERC721TokenMinable("v01.EQUIP.TEST", "v01.EQUIP.TEST") {}
}
contract ArenaToken is BaseERC721TokenMinable {
constructor() BaseERC721TokenMinable("v01.Arena.TEST", "v01.Arena.TEST") {}
}
#!/bin/bash
network=${1:-"httest"}
if [ ! -e "./.secret" ]
then
echo "You must set DEPLOY_PRIVATE_KEY and NAME_SIGNER_KEY in .secret file"
exit
fi
if [ -e ".env" ]
then
cp .env .env_bak
rm -rf .env
fi
cat .secret >> .env
echo "" >> .env
cat "./config/$network.cfg" >> .env
npx hardhat run scripts/deploy/deployUpgradeable.js --network $network
rm -rf .env
......@@ -36,7 +36,16 @@ module.exports = {
solidity: {
compilers: [
{
version: "0.8.4",
version: "0.8.22",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
{
version: "0.8.20",
settings: {
optimizer: {
enabled: true,
......
{
"name": "upgradableContracts",
"name": "upgradablecontract",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"@openzeppelin/contracts": "^5.3.0",
"@openzeppelin/contracts-upgradeable": "^5.3.0",
"dotenv": "^16.5.0"
},
"devDependencies": {
......@@ -2388,6 +2390,21 @@
"node": ">= 12"
}
},
"node_modules/@openzeppelin/contracts": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.3.0.tgz",
"integrity": "sha512-zj/KGoW7zxWUE8qOI++rUM18v+VeLTTzKs/DJFkSzHpQFPD/jKKF0TrMxBfGLl3kpdELCNccvB3zmofSzm4nlA==",
"license": "MIT"
},
"node_modules/@openzeppelin/contracts-upgradeable": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.3.0.tgz",
"integrity": "sha512-yVzSSyTMWO6rapGI5tuqkcLpcGGXA0UA1vScyV5EhE5yw8By3Ewex9rDUw8lfVw0iTkvR/egjfcW5vpk03lqZg==",
"license": "MIT",
"peerDependencies": {
"@openzeppelin/contracts": "5.3.0"
}
},
"node_modules/@openzeppelin/defender-sdk-base-client": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-2.5.0.tgz",
......
/* eslint-disable prefer-const */
/* eslint-disable dot-notation */
/* eslint-disable no-unused-vars */
/* eslint-disable eqeqeq */
/* eslint-disable camelcase */
/* eslint-disable no-lone-blocks */
// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// When running the script with `npx hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
const HORSE_GENE = {
DARLEY_ARABIAN: ["VVEEAADDTTHH"],
GODOLPHIN_ARABIAN: [
"VVEEAADDTThh",
"VVEEAADDttHH",
"VVEEAAddTTHH",
"VVEEaaDDTTHH",
"VVeeAADDTTHH",
"vvEEAADDTTHH",
],
BYERLY_TURK: [
"VVEEAADDtthh",
"VVEEAAddTThh",
"VVEEaaDDTThh",
"VVeeAADDTThh",
"vvEEAADDTThh",
"VVEEAAddttHH",
"VVEEaaDDttHH",
"VVeeAADDttHH",
"vvEEAADDttHH",
"VVEEaaddTTHH",
"VVeeAAddTTHH",
"vvEEAAddTTHH",
"VVeeaaDDTTHH",
"vvEEaaDDTTHH",
"vveeAADDTTHH",
],
SATOSHI_NAKAMOTO: [
"VVEEAAddtthh",
"VVEEaaDDtthh",
"VVEEaaddTThh",
"VVEEaaddttHH",
"VVeeAADDtthh",
"VVeeAAddTThh",
"VVeeAAddttHH",
"VVeeaaDDTThh",
"VVeeaaDDttHH",
"VVeeaaddTTHH",
"vvEEAADDtthh",
"vvEEAAddTThh",
"vvEEAAddttHH",
"vvEEaaddTTHH",
"vvEEaaDDTThh",
"vvEEaaDDttHH",
"vveeAADDTThh",
"vveeAADDttHH",
"vveeAAddTTHH",
"vveeaaDDTTHH",
],
};
const ADDR_MINT_RECEIVER = process.env.ADDR_MINT_RECEIVER;
const ADDR_BONUS_POOL = process.env.ADDR_BONUS_POOL;
const ADDR_BONUS_BURNED = process.env.ADDR_BONUS_BURNED;
const ADDR_BONUS_PLATFORM = process.env.ADDR_BONUS_PLATFORM;
const ADDR_FEE_RECEIVER = process.env.ADDR_FEE_RECEIVER;
const ADDR_USDT_TOKEN = process.env.ADDR_USDT_TOKEN;
const ADDR_API_SERVER = process.env.ADDR_API_SERVER;
// 装备类型
// 1 马头饰
// 2 马护甲
// 3 马尾饰
// 4 马蹄饰(暂未使用)
// 装备款式
// 1 - 5
// 1、 圣诞 套装
// 2、 庄重 套装
// 3、 淡雅 套装
// 4、 华丽 套装
// 5、 喜庆 套装
const BATCH_HORSE_COUNT = 10;
const BATCH_EQUIP_COUNT = 50;
const EQUIP_TYPE_COUNT = 3;
const EQUIP_STYLE_COUNT = 5;
const GAME_DISTANCE = {
1200: { fee: 5, award: 20 },
2400: { fee: 10, award: 20 },
3600: { fee: 15, award: 20 },
};
const HORSE_GENE_PROBABILITIES = [
[3000, 2000, 4000, 1000],
[4000, 2600, 2800, 600],
[4800, 3000, 1900, 300],
[5500, 3300, 1100, 100],
];
const MYSTERY_BOX_NAMES = ["PLATINUM", "GOLD", "SILVER", "BRONZE"];
const MYSTERY_BOX_PRICES = [400, 300, 200, 100];
const MYSTERY_BOX_HORSE_TYPES = [
"SATOSHI_NAKAMOTO",
"BYERLY_TURK",
"GODOLPHIN_ARABIAN",
"DARLEY_ARABIAN",
];
const MYSTERY_BOX_HORSE_COUNT = [100, 100, 100, 100];
const RELY_ON_ADMIN_MAP = [
{ contract: "EquipToken", params: ["EquipExtra"] },
{ contract: "HorseToken", params: ["RaceExtra"] },
{ contract: "ArenaToken", params: ["ArenaExtra"] },
];
const RELY_ON_MINTER_MAP = [
{ contract: "Coin", params: ["EquipExtra"] },
{ contract: "Coin", params: ["RaceExtra"] },
{ contract: "Coin", params: ["RaceExtra1"] },
{ contract: "Coin", params: ["RaceExtra2"] },
{ contract: "Coin", params: ["ArenaExtra"] },
{ contract: "Coin", params: ["ArenaExtra1"] },
{ contract: "Coin", params: ["ArenaExtra2"] },
{ contract: "Coin", params: ["ArenaExtra3"] },
{ contract: "Coin721", params: ["EquipExtra"] },
{ contract: "Coin721", params: ["RaceExtra2"] },
];
const RELY_ON_PROGRAM_MAP = [
{ contract: "EquipAttr", params: ["EquipExtra"] },
{ contract: "EquipAttr", params: ["RaceExtra1"] },
{ contract: "RaceAttr1", params: ["ArenaExtra1"] },
{ contract: "RaceAttr1", params: ["RaceExtra2"] },
{ contract: "RaceAttr1", params: ["RaceExtra1"] },
{ contract: "RaceAttr1", params: ["RaceExtra"] },
{ contract: "RaceAttr1_1", params: ["EquipExtra"] },
{ contract: "RaceAttr1_1", params: ["RaceExtra"] },
{ contract: "RaceAttr1_1", params: ["RaceExtra1"] },
{ contract: "RaceAttr1_1", params: ["RaceExtra2"] },
{ contract: "RaceAttr1_1", params: ["ArenaExtra"] },
{ contract: "RaceAttr1_1", params: ["ArenaExtra1"] },
{ contract: "RaceAttr1_1", params: ["ArenaExtra2"] },
{ contract: "RaceAttr1_1", params: ["ArenaExtra3"] },
{ contract: "ArenaAttr", params: ["ArenaExtra"] },
{ contract: "ArenaAttr", params: ["ArenaExtra1"] },
{ contract: "ArenaAttr", params: ["ArenaExtra2"] },
{ contract: "ArenaAttr", params: ["ArenaExtra3"] },
{ contract: "RaceNFTAttr", params: ["EquipAttr"] },
{ contract: "RaceNFTAttr", params: ["RaceAttr1"] },
{ contract: "RaceNFTAttr", params: ["RaceAttr1_1"] },
{ contract: "RaceNFTAttr", params: ["ArenaAttr"] },
{ contract: "RaceBonusDistribute", params: ["ArenaExtra1"] },
{ contract: "RaceBonusPool", params: ["RaceBonusDistribute"] },
{ contract: "RaceBonusData", params: ["RaceBonusPool"] },
{ contract: "RaceToken", params: ["ArenaExtra1"] },
{ contract: "HorseCourseAttr", params: ["ArenaExtra3"] },
{ contract: "HorseCourseAttrOpera", params: ["ArenaExtra3"] },
{ contract: "HorseCourseAttr", params: ["HorseCourseAttrOpera"] },
];
const OFFICIAL_CONTRACT_MAP = [
{ contract: "Constant", params: ["Coin721"] },
{ contract: "Constant", params: ["EquipExtra"] },
{ contract: "Constant", params: ["RaceExtra"] },
{ contract: "Constant", params: ["RaceExtra1"] },
{ contract: "Constant", params: ["RaceExtra2"] },
{ contract: "Constant", params: ["ArenaExtra"] },
{ contract: "Constant", params: ["ArenaExtra1"] },
{ contract: "Constant", params: ["ArenaExtra2"] },
{ contract: "Constant", params: ["ArenaExtra3"] },
];
const TRANSFER_HANDLER_MAP = [
{ contract: "ArenaToken", params: ["ArenaExtra"] },
{ contract: "EquipToken", params: ["EquipExtra"] },
{ contract: "HorseToken", params: ["RaceExtra1"] },
];
const accounts = [{ address: ADDR_API_SERVER }];
const API_SERVER_PROGRAM_MAP = [
{ contract: "ArenaExtra", params: [{ address: ADDR_API_SERVER }] },
{ contract: "ArenaExtra1", params: [{ address: ADDR_API_SERVER }] },
{ contract: "ArenaExtra2", params: [{ address: ADDR_API_SERVER }] },
{ contract: "ArenaExtra3", params: [{ address: ADDR_API_SERVER }] },
{ contract: "HorseCourseAttr", params: [{ address: ADDR_API_SERVER }] },
{ contract: "HorseCourseAttrOpera", params: [{ address: ADDR_API_SERVER }] },
{ contract: "RaceExtra1", params: [{ address: ADDR_API_SERVER }] },
];
const API_SERVER_ADMIN_MAP = [
{ contract: "RaceExtra1", params: [{ address: ADDR_API_SERVER }] },
{ contract: "Constant", params: [{ address: ADDR_API_SERVER }] },
];
let ContractMap = new Map();
async function deployContract(
contractPath,
contractName,
addAdmin,
addrProgram,
contractOptions
) {
const factory = await hre.ethers.getContractFactory(
contractPath,
contractOptions
);
let args = [];
for (let i = 5; i < arguments.length; i++) {
args.push(arguments[i]);
}
const contract = await factory.deploy.apply(factory, args);
// const contract = await factory.deploy();
await contract.deployed();
console.log(
"DeployedContract:",
contract.address,
"for",
contractName,
contractPath + "(" + args.join(",") + ")"
);
ContractMap.set(contractName, contract);
if (addAdmin) {
// await _addAdminSender(contract);
}
if (addrProgram != undefined) {
await contract.addProgram(addrProgram);
}
return contract;
}
async function getContract(contractPath, address) {
return await hre.ethers.getContractAt(contractPath, address);
}
async function settingBonusDistribute(distribute, nftHorse, bonusPool) {
const percentForArenaOwner = 800; // 8%
const percentForWinners = [
4000, 2000, 960, 640, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
const set = await distribute.setSettings(
percentForArenaOwner,
percentForWinners,
[ADDR_BONUS_POOL, ADDR_BONUS_BURNED, ADDR_BONUS_PLATFORM],
[500, 200, 500],
[bonusPool],
nftHorse
);
await set.wait();
console.log("SettingBonusDistribute finished.");
return distribute;
}
async function settingBonusPool(contract, bonusData, metaToken, horseNft) {
const set = await contract.setContracts(
bonusData,
metaToken,
horseNft,
ADDR_BONUS_POOL
);
await set.wait();
console.log("SettingBonusPool finished.");
}
async function deployBonus(metaToken, horseNft) {
const distribute = await deployContract(
"RaceBonusDistribute",
"RaceBonusDistribute",
true
);
const raceBonusPool = await deployContract(
"RaceBonusPool",
"RaceBonusPool",
true
);
const raceBonusData = await deployContract(
"RaceBonusData",
"RaceBonusData",
true
);
await settingBonusPool(
raceBonusPool,
raceBonusData.address,
metaToken.address,
horseNft.address
);
await settingBonusDistribute(
distribute,
horseNft.address,
raceBonusPool.address
);
console.log(
"DeployBonus: setting finished",
distribute.address,
raceBonusData.address,
raceBonusPool.address
);
return {
distribute: distribute,
raceBonusData: raceBonusData,
raceBonusPool: raceBonusPool,
};
}
async function setMysteryBoxData(NFTMysteryBoxOffering, horseNFT, priceToken) {
await NFTMysteryBoxOffering.setBox(
MYSTERY_BOX_NAMES,
[horseNFT, horseNFT, horseNFT, horseNFT],
[1000, 1000, 1000, 1000]
);
console.log("SetMysteryBoxData: setBox finished.");
for (let i = 0; i < 4; i++) {
const prices = [MYSTERY_BOX_PRICES[i]];
const tokens = [priceToken];
const probabilities = [0, 0, 0, 0];
for (let j = 0; j < 4; j++) {
probabilities[j] = HORSE_GENE_PROBABILITIES[i][j];
}
await NFTMysteryBoxOffering.setPrice(MYSTERY_BOX_NAMES[i], tokens, prices);
console.log(
"SetMysteryBoxData: setPrice " + MYSTERY_BOX_NAMES[i] + " finished."
);
await NFTMysteryBoxOffering.setProbability(
MYSTERY_BOX_NAMES[i],
MYSTERY_BOX_HORSE_TYPES,
probabilities
);
console.log(
"SetMysteryBoxData: setProbability " + MYSTERY_BOX_NAMES[i] + " finished."
);
}
}
async function addMysteryBoxToken(address) {
const NFTMysteryBoxOffering = await getContract(
"NFTMysteryBoxOffering",
address
);
console.log("addMysteryBoxToken: " + address);
let k = 1;
for (let i = 0; i < MYSTERY_BOX_HORSE_COUNT.length; i++) {
for (let j = 0; j < MYSTERY_BOX_HORSE_COUNT.length; j++) {
const count =
(HORSE_GENE_PROBABILITIES[j][i] * MYSTERY_BOX_HORSE_COUNT[j]) / 10000;
const start = k;
const end = k + count - 1;
console.log(
"addMysteryBoxToken: addToken start " +
MYSTERY_BOX_NAMES[j] +
" " +
start +
"," +
end
);
await NFTMysteryBoxOffering["addToken(string,uint256,uint256)"](
MYSTERY_BOX_NAMES[j],
start,
end
);
console.log(
"addMysteryBoxToken: addToken ended " +
MYSTERY_BOX_NAMES[j] +
" " +
start +
"," +
end
);
k += count;
}
}
}
async function deployMysteryBox(rewardToken, horseNFT, priceToken) {
const NFTMysteryBoxOffering = await deployContract(
"NFTMysteryBoxOffering",
"NFTMysteryBoxOffering"
);
const Random = await deployContract(
"Random",
"Random",
false,
NFTMysteryBoxOffering.address
);
const Whitelist = await deployContract(
"Whitelist",
"Whitelist",
false,
NFTMysteryBoxOffering.address
);
const MysteryBox = await deployContract(
"MysteryBox",
"MysteryBox",
false,
NFTMysteryBoxOffering.address
);
const MysteryData = await deployContract(
"MysteryData",
"MysteryData",
false,
NFTMysteryBoxOffering.address
);
await NFTMysteryBoxOffering.setContracts(
Random.address,
MysteryBox.address,
MysteryData.address,
Whitelist.address,
rewardToken
);
console.log("DeployMysteryBox: setContracts finished.");
await NFTMysteryBoxOffering.setAccounts(
ADDR_MINT_RECEIVER,
ADDR_MINT_RECEIVER
);
console.log("DeployMysteryBox: setAccounts finished.");
await setMysteryBoxData(NFTMysteryBoxOffering, horseNFT, priceToken);
console.log("DeployMysteryBox: setMysteryBoxData finished.");
console.log("DeployMysteryBox: finished.");
}
async function initialDeploy() {
await deployContract("UserLoginContract", "UserLogin", true);
const constant = await deployConstant();
const metaToken = await deployContract("MetaToken", "MetaToken", true);
const raceToken = await deployContract("RaceToken", "RaceToken", true);
let AddrUsdtToken = ADDR_USDT_TOKEN;
if (ADDR_USDT_TOKEN === "" || ADDR_USDT_TOKEN === undefined) {
const usdtToken = await deployContract("UsdtToken", "UsdtToken", true);
AddrUsdtToken = usdtToken.address;
}
const coin = await deployCoin(
metaToken.address,
raceToken.address,
AddrUsdtToken
);
const equipNft = await deployContract("EquipToken", "EquipToken");
const horseNft = await deployContract("HorseToken", "HorseToken");
const arenaNft = await deployContract("ArenaToken", "ArenaToken");
const coin721 = await deployCoin721(
equipNft.address,
horseNft.address,
arenaNft.address
);
await deployMysteryBox(metaToken.address, horseNft.address, AddrUsdtToken);
const bonus = await deployBonus(metaToken, horseNft);
const nftAttr = await deployNFTAttr(
equipNft.address,
horseNft.address,
arenaNft.address
);
const equipAttr = await deployNftAttrOpera(
"HorseEquipAttrOperaContract",
"EquipAttr",
nftAttr.address,
equipNft.address
);
const arenaAttr = await deployNftAttrOpera(
"HorseArenaAttrOperaContract",
"ArenaAttr",
nftAttr.address,
arenaNft.address
);
const raceAttr1 = await deployNftAttrOpera(
"HorseRaceAttrOpera1",
"RaceAttr1",
nftAttr.address,
horseNft.address
);
const raceAttr1_1 = await deployNftAttrOpera(
"HorseRaceAttrOpera1_1",
"RaceAttr1_1",
nftAttr.address,
horseNft.address
);
const raceAttr2 = await deployNftAttrOpera(
"HorseRaceAttrOpera2",
"RaceAttr2",
nftAttr.address,
horseNft.address
);
const raceAttr2_1 = await deployNftAttrOpera(
"HorseRaceAttrOpera2_1",
"RaceAttr2_1",
nftAttr.address,
horseNft.address
);
const raceCourseAttr = await deployRaceCourseAttr();
const raceCourseAttrOp = await deployRaceCourseAttrOpera(
raceCourseAttr.address
);
const libBytes = await deployContract(
"contracts/library/Bytes.sol:Bytes",
"Bytes"
);
const contractOptions = {
libraries: {
Bytes: libBytes.address,
},
};
await deployEquipExtra(
coin.address,
coin721,
equipAttr.address,
equipNft.address,
ADDR_FEE_RECEIVER,
constant.address,
raceAttr1_1.address
);
await deployRaceExtra(
contractOptions,
raceAttr1.address,
raceAttr1_1.address,
horseNft.address,
raceAttr2.address,
raceAttr2_1.address,
coin.address,
coin721,
constant.address,
ADDR_FEE_RECEIVER,
equipAttr.address,
equipNft.address
);
await deployRaceExtra1(
contractOptions,
raceAttr1.address,
raceAttr1_1.address,
horseNft.address,
raceAttr2.address,
raceAttr2_1.address,
coin.address,
coin721,
constant.address,
ADDR_FEE_RECEIVER,
equipAttr.address,
equipNft.address
);
await deployRaceExtra2(
contractOptions,
raceAttr1.address,
raceAttr1_1.address,
horseNft.address,
raceAttr2.address,
raceAttr2_1.address,
coin.address,
coin721,
constant.address,
ADDR_FEE_RECEIVER,
equipAttr.address,
equipNft.address
);
await deployArenaExtra(
contractOptions,
arenaAttr.address,
raceCourseAttrOp.address,
arenaNft.address,
coin.address,
constant.address,
ADDR_FEE_RECEIVER,
raceAttr1.address,
raceAttr1_1.address,
raceAttr2.address,
raceAttr2_1.address,
horseNft.address,
bonus.distribute.address
);
await deployArenaExtra1(
contractOptions,
arenaAttr.address,
raceCourseAttrOp.address,
arenaNft.address,
coin.address,
constant.address,
ADDR_FEE_RECEIVER,
raceAttr1.address,
raceAttr1_1.address,
raceAttr2.address,
raceAttr2_1.address,
horseNft.address,
metaToken.address,
raceToken.address,
bonus.distribute.address
);
await deployArenaExtra2(
contractOptions,
arenaAttr.address,
raceCourseAttrOp.address,
arenaNft.address,
coin.address,
constant.address,
ADDR_FEE_RECEIVER,
raceAttr1.address,
raceAttr1_1.address,
raceAttr2.address,
raceAttr2_1.address,
horseNft.address
);
await deployArenaExtra3(
contractOptions,
arenaAttr.address,
raceCourseAttrOp.address,
arenaNft.address,
coin.address,
constant.address,
ADDR_FEE_RECEIVER,
raceAttr1.address,
raceAttr1_1.address,
raceAttr2.address,
raceAttr2_1.address,
horseNft.address
);
await _batchOperate("addMinter", RELY_ON_MINTER_MAP);
console.log("SetPermission addMinter finished.");
await _batchOperate("addAdmin", RELY_ON_ADMIN_MAP);
console.log("SetPermission addAdmin finished.");
await _batchOperate("addProgram", RELY_ON_PROGRAM_MAP);
console.log("SetPermission addProgram finished.");
await _batchOperate("registerTransferHandler", TRANSFER_HANDLER_MAP);
console.log("SetTransferHandler finished.");
await _batchOperate("addOfficialContract", OFFICIAL_CONTRACT_MAP);
console.log("AddOfficial finished.");
}
async function deployConstant() {
const contract = await deployContract("Constant", "Constant", true);
for (let k in GAME_DISTANCE) {
await contract.setApplyGameAmount(k, GAME_DISTANCE[k].fee);
await contract.setAwardGameAmount(k, GAME_DISTANCE[k].award);
}
return contract;
}
async function deployCoin(metaToken, raceToken, usdtToken) {
const contract = await deployContract("Coin", "Coin", true);
const tokenId = [1, 2, 3];
const tokenAddress = [metaToken, raceToken, usdtToken];
const tokenPrice = [1, 1, 10000];
const addTokens = await contract.add(tokenId, tokenAddress, tokenPrice);
await addTokens.wait();
console.log("deployCoin: addTokens(" + tokenAddress.join(",") + ")");
return contract;
}
async function deployCoin721(equipNft, horseNft, arenaNft) {
const contract = await deployContract("Coin721", "Coin721", true);
const tokenAddress = [equipNft, horseNft, arenaNft];
const addTokens = await contract.add(tokenAddress);
await addTokens.wait();
console.log("deployCoin721: addTokens(" + tokenAddress.join(",") + ")");
return contract;
}
async function _setEquipFields(attrContract, equipNft) {
const fields = [
"horseEquipTypes",
"horseEquipStyle",
"horseEquipStatus",
"horseEquipPrice",
"horseEquipOfUid",
"horseEquipOfHorseId",
"horseEquipDiscount",
"horseEquipReward",
"horseEquipCoin",
"horseEquipLastOwner",
"horseEquipLastPrice",
"lastOperaTime",
];
const ftypes = [1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1];
const fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
const setfield = await attrContract.setFiled(
equipNft,
fields,
ftypes,
fauths
);
await setfield.wait();
}
async function _setHorseFields(attrContract, horseNft) {
let fields = [
"horseRaceName",
"nameUptCount",
"birthDay",
"mainGeneration",
"slaveGeneration",
"generationScore",
"gender",
"color",
"gene",
"gripGene",
];
let ftypes = [2, 1, 1, 1, 1, 1, 1, 1, 1, 1];
let fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
let setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = [
"accGene",
"endGene",
"speedGene",
"turnToGene",
"controlGene",
"trainingValue",
"trainingTime",
"useTraTime",
"energy",
"energyUpdateTime",
];
ftypes = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = [
"gradeScore",
"gradeIntegral",
"gradeScoreMark",
"raceScoreUpdateTime",
"father",
"mother",
"breedCount",
"breedTime",
"gradeIntegralYear",
"gradeIntegralYearTime",
];
ftypes = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = [
"gradeIntegralMonth",
"gradeIntegralMonthTime",
"gradeIntegralWeek",
"gradeIntegralWeekTime",
];
ftypes = [1, 1, 1, 1];
fauths = [2, 2, 2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = [
"headWearId",
"armorId",
"ponytailId",
"hoofId",
"grade",
"raceCount",
"winCount",
"raceId",
"raceType",
"racecourse",
];
ftypes = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = [
"distance",
"raceUpdateTime",
"horseRaceStatus",
"horseRaceDiscount",
"horseRaceReward",
"horseRaceCoin",
"horseRaceLastOwner",
"horseRaceLastPrice",
"horseRacePrice",
];
ftypes = [1, 1, 1, 1, 1, 1, 1, 1, 1];
fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = ["sellUpdateTime", "studUpdateTime"];
ftypes = [1, 1];
fauths = [2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
}
async function _setArenaFields(attrContract, arenaNft) {
const fields = [
"name",
"createTime",
"ownerType",
"isClose",
"raceCount",
"lastRaceTime",
"totalRaceCount",
"mortAmount",
"gameId",
"horseIds",
];
const ftypes = [2, 1, 1, 1, 1, 1, 1, 1, 1, 1];
const fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
const setfield = await attrContract.setFiled(
arenaNft,
fields,
ftypes,
fauths
);
await setfield.wait();
}
async function deployNFTAttr(equipNft, horseNft, arenaNft) {
const contract = await deployContract("ERC721Attr", "RaceNFTAttr", true);
await _setEquipFields(contract, equipNft);
await _setHorseFields(contract, horseNft);
await _setArenaFields(contract, arenaNft);
return contract;
}
async function deployNftAttrOpera(contractPath, contractName, nftAttr, nft) {
const contract = await deployContract(contractPath, contractName, true);
const init = await contract.init(nftAttr, nft);
await init.wait();
return contract;
}
async function deployRaceCourseAttr() {
const contract = await deployContract("ERC721Attr", "HorseCourseAttr", true);
return contract;
}
async function deployRaceCourseAttrOpera(raceCourseAttr) {
const contract = await deployContract(
"RacecourseAttrOperaContract",
"HorseCourseAttrOpera",
true
);
const init = await contract.init(raceCourseAttr);
await init.wait();
return contract;
}
async function deployEquipExtra(
coin,
coin721,
equipAttrOpera,
equipNft,
feeAddr,
constant,
raceHorseAttr1_1
) {
const contract = await deployContract(
"HorseEquipContract",
"EquipExtra",
true
);
const init = await contract.initHorseEquipAttrAddress(
coin,
coin721.address,
equipAttrOpera,
equipNft,
feeAddr,
constant,
raceHorseAttr1_1
);
await init.wait();
return contract;
}
async function deployRaceExtra(
contractOptions,
raceAttr1,
raceAttr1_1,
horseNft,
raceAttr2,
raceAttr2_1,
coin,
coin721,
constant,
feeAddr,
equipAttr,
equipNft
) {
const contract = await deployContract(
"HorseRaceContract",
"RaceExtra",
true,
undefined,
contractOptions
);
const init = await contract.initHorseRaceAttrAddress(
raceAttr1,
raceAttr1_1,
horseNft,
raceAttr2,
raceAttr2_1,
coin,
constant,
feeAddr
);
await init.wait();
return contract;
}
async function deployRaceExtra1(
contractOptions,
raceAttr1,
raceAttr1_1,
horseNft,
raceAttr2,
raceAttr2_1,
coin,
coin721,
constant,
feeAddr,
equipAttr,
equipNft
) {
const contract = await deployContract(
"HorseRaceExtra1",
"RaceExtra1",
true,
undefined,
contractOptions
);
const init = await contract.initHorseRaceAttrAddress(
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
equipAttr,
horseNft,
equipNft,
constant,
coin,
feeAddr
);
await init.wait();
return contract;
}
async function deployRaceExtra2(
contractOptions,
raceAttr1,
raceAttr1_1,
horseNft,
raceAttr2,
raceAttr2_1,
coin,
coin721,
constant,
feeAddr,
equipAttr,
equipNft
) {
const contract = await deployContract("HorseRaceExtra2", "RaceExtra2", true);
const init = await contract.initHorseRaceAttrAddress(
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
coin,
coin721.address,
horseNft,
constant,
feeAddr
);
await init.wait();
return contract;
}
async function deployArenaExtra(
contractOptions,
arenaAttr,
courseAttr,
arenaNft,
coin,
constant,
feeAddr,
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
horseNft,
distribute
) {
const contract = await deployContract(
"HorseArenaContract",
"ArenaExtra",
true,
undefined,
contractOptions
);
const init = await contract.init(arenaAttr, arenaNft, coin, constant);
await init.wait();
return contract;
}
async function deployArenaExtra1(
contractOptions,
arenaAttr,
courseAttr,
arenaNft,
coin,
constant,
feeAddr,
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
horseNft,
metaToken,
raceToken,
distribute
) {
const contract = await deployContract("HorseArenaExtra", "ArenaExtra1", true);
const init = await contract.init(
arenaAttr,
coin,
courseAttr,
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
horseNft,
arenaNft,
constant,
metaToken,
raceToken
);
await init.wait();
await contract.setDistribute(distribute);
return contract;
}
async function deployArenaExtra2(
contractOptions,
arenaAttr,
courseAttr,
arenaNft,
coin,
constant,
feeAddr,
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
horseNft
) {
const contract = await deployContract(
"HorseArenaExtra2",
"ArenaExtra2",
true
);
const init = await contract.init(
arenaAttr,
coin,
horseNft,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
constant
);
await init.wait();
return contract;
}
async function deployArenaExtra3(
contractOptions,
arenaAttr,
courseAttr,
arenaNft,
coin,
constant,
feeAddr,
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
horseNft
) {
const contract = await deployContract(
"HorseArenaExtra3",
"ArenaExtra3",
true
);
const init = await contract.init(
arenaAttr,
courseAttr,
raceAttr1_1,
raceAttr2_1,
constant
);
await init.wait();
return contract;
}
function _allColor() {
const colors = [];
colors.push("FF00FFFF"); // 紫色
colors.push("FF5A00FF"); // 棕色
colors.push("00FFFFFF"); // 青色
colors.push("FFFFFFFF"); // 原色
return colors;
}
async function mintHorse(horseRaceAddr, toAddr, styleName, start, count) {
let horseIdx = start;
const prefix = "MR";
const horseRaceContract = await hre.ethers.getContractAt(
"HorseRaceContract",
horseRaceAddr
);
let pCount = BATCH_HORSE_COUNT;
let total = 0;
const geneList = HORSE_GENE[styleName];
const colors = _allColor();
for (total = 0; total < count; ) {
if (count - total > BATCH_HORSE_COUNT) {
pCount = BATCH_HORSE_COUNT;
} else {
pCount = count - total;
}
console.log("Mint horse count ", pCount);
const name = [];
const style = [];
const mainGeneration = [];
const slaveGeneration = [];
const generationScore = [];
const gender = [];
const color = [];
const gene = [];
const to = [];
for (let i = 1; i <= pCount; i++, horseIdx++) {
const cname = prefix + "-" + horseIdx;
name.push(cname);
style.push(styleName);
mainGeneration.push(0);
slaveGeneration.push(0);
generationScore.push(10000);
to.push(toAddr);
if (i % 2 == 0) {
gender.push(1); // male
} else {
gender.push(0); // female
}
const initGene = geneList[i % geneList.length];
const nColor = colors[i % colors.length];
color.push(nColor);
gene.push(initGene);
}
const mint = await horseRaceContract.batchMintHorse(
name,
style,
mainGeneration,
slaveGeneration,
generationScore,
gender,
color,
gene,
to
);
await mint.wait();
console.log(
"Batch mint horse to",
toAddr,
styleName,
total,
total + pCount
);
total += pCount;
}
console.log(
"Mint horse with style ",
styleName,
" finished, total ",
start,
total
);
}
async function batchMintHorseToPool(horseRaceAddr) {
let start = 1;
for (let i = 0; i < MYSTERY_BOX_HORSE_COUNT.length; i++) {
let count = 0;
for (let j = 0; j < MYSTERY_BOX_HORSE_COUNT.length; j++) {
count +=
(HORSE_GENE_PROBABILITIES[j][i] * MYSTERY_BOX_HORSE_COUNT[i]) / 10000;
}
await mintHorse(
horseRaceAddr,
ADDR_MINT_RECEIVER,
MYSTERY_BOX_HORSE_TYPES[i],
start,
count
);
start += count;
}
}
async function mintArena() {
const accounts = await hre.ethers.getSigners();
const metaToken = ContractMap.get("MetaToken");
const coinContract = ContractMap.get("Coin");
const constantContract = ContractMap.get("Constant");
const depositAmount = await constantContract.getMortAmount();
const decimals = await metaToken.decimals();
const deposit = depositAmount * 10 ** decimals;
// 购买赛场需要抵押 meta token
const balance = await metaToken.balanceOf(accounts[0].address);
console.log("User have meta token %d and need deposit %d.", balance, deposit);
const approve = await metaToken.approve(coinContract.address, balance);
await approve.wait();
const signer = process.env.NAME_SIGNER_KEY;
const arenaName = "MetaRace";
const hash = hre.ethers.utils.solidityKeccak256(["string"], [arenaName]);
const signingKey = new hre.ethers.utils.SigningKey(signer);
const signature = await signingKey.signDigest(hash);
const rawSign = await hre.ethers.utils.joinSignature(signature);
const horseArenaContract = ContractMap.get("ArenaExtra");
await horseArenaContract.mintOfficialArena(arenaName, rawSign);
console.log("Mint arena end.");
}
async function mintEquip(count) {
const equipExtra = ContractMap.get("EquipExtra");
let lstEquipType = [];
let lstEquipStyle = [];
if (count < 0) {
for (let i = 0; i < -count; i++) {
lstEquipType.push((i % EQUIP_TYPE_COUNT) + 1);
lstEquipStyle.push((i % EQUIP_STYLE_COUNT) + 1);
}
} else if (count > 0) {
for (let equipType = 1; equipType <= EQUIP_TYPE_COUNT; equipType++) {
for (let equipStyle = 1; equipStyle <= EQUIP_STYLE_COUNT; equipStyle++) {
for (let i = 0; i < count; i++) {
lstEquipType.push(equipType);
lstEquipStyle.push(equipStyle);
}
}
}
}
if (lstEquipType.length > 0) {
for (let i = 0; i < lstEquipType.length; i += BATCH_EQUIP_COUNT) {
let lstType = [];
let lstStyle = [];
let to = [];
let n =
i + BATCH_EQUIP_COUNT <= lstEquipType.length
? BATCH_EQUIP_COUNT
: lstEquipType.length - i;
for (let j = 0; j < n; j++) {
lstType[j] = lstEquipType[i + j];
lstStyle[j] = lstEquipStyle[i + j];
to[j] = ADDR_MINT_RECEIVER;
console.log(
"Mint equip with type = %d and style = %d.",
lstType[j],
lstStyle[j]
);
}
await equipExtra.batchMintEquip(to, lstType, lstStyle);
}
}
}
async function addInitColor() {
/*
color = "FF00FFFF"; // 紫色
color = "FF5A00FF"; // 棕色
color = "00FFFFFF"; // 青色
color = "FFFFFFFF"; // 原色
*/
const constant = ContractMap.get("Constant");
const colorList = _allColor();
for (const color of colorList) {
console.log("Added color", color);
await constant.addColor(color);
}
const count = await constant.getInitColorsCount();
// console.log("got init color count is ", count);
for (let i = 0; i < count; i++) {
const color = await constant.getInitColors(i);
console.log("Check color", color, "at", i);
}
}
async function _batchOperate(fn, lst) {
for (let i = 0; i < lst.length; i++) {
const item = lst[i];
let contract = ContractMap.get(item.contract);
if (item.contractPath && item.contractAddr) {
contract = await getContract(item.contractPath, item.contractAddr);
}
const isString = typeof item.params[0] == "string";
let addr = isString
? ContractMap.get(item.params[0]).address
: item.params[0].address;
if (addr) {
let args;
switch (fn) {
case "registerTransferHandler":
args = [addr, addr];
break;
default:
args = [addr];
}
await _callContract(
item.contract,
contract,
fn,
item.params,
args,
false
);
}
}
}
async function _callContract(name, contract, fn, params, args, isCall) {
const isString = typeof params[0] == "string";
let result;
switch (fn) {
case "registerTransferHandler":
result = await contract[fn].apply(contract, args);
break;
default:
result = await contract[fn].apply(contract, args);
}
if (!isCall) {
await result.wait();
console.log(
fn + "(" + name + "," + args[0] + (isString ? "," + params[0] : "") + ")"
);
} else {
console.log(
fn +
"(" +
name +
"," +
args[0] +
(isString ? "," + params[0] : "") +
") = " +
result
);
}
return result;
}
async function _checkOperate(fn, lst, fnSet) {
for (let i = 0; i < lst.length; i++) {
const item = lst[i];
const contract = await getContract(item.contractPath, item.contractAddr);
const isString = typeof item.params[0] == "string";
let addr = isString
? ContractMap.get(item.params[0]).address
: item.params[0].address;
if (addr) {
const result = await _callContract(
item.contract,
contract,
fn,
item.params,
[addr],
true
);
if (!result && fnSet) {
let args;
switch (fnSet) {
case "registerTransferHandler":
args = [addr, addr];
break;
default:
args = [addr];
}
await _callContract(
item.contract,
contract,
fnSet,
item.params,
args,
false
);
}
}
}
}
async function addOfficial() {
await _batchOperate("addOfficialContract", OFFICIAL_CONTRACT_MAP);
console.log("AddOfficial finished.");
}
async function setTransferHandler() {
await _batchOperate("registerTransferHandler", TRANSFER_HANDLER_MAP);
console.log("SetTransferHandler finished.");
}
async function checkPrivilege() {
const accounts = [{ address: ADDR_API_SERVER }];
const ProgramMap = [
{
contractPath: "HorseArenaExtra",
contractAddr: "0x05a757bf7C1811fC750879b68DC6a8c7bd2D8759",
contract: "ArenaExtra1",
params: accounts,
},
{
contractPath: "HorseArenaExtra3",
contractAddr: "0x9B8D70d2993b15F4DeA04e9C4A22183C05f0ec6f",
contract: "ArenaExtra3",
params: accounts,
},
{
contractPath: "HorseRaceExtra1",
contractAddr: "0xAE154d855c7e0aa9eF3f432A1051518f23167A63",
contract: "RaceExtra1",
params: accounts,
},
];
await _checkOperate("isProgram", ProgramMap, "addProgram");
const AdminMap = [
{
contractPath: "Constant",
contractAddr: "0x05De106a835E438AA02E103008Cc1dCD9425321d",
contract: "Constant",
params: accounts,
},
];
await _checkOperate("isAdmin", AdminMap, "addAdmin");
}
async function initialSetting() {
// await modifyConstant(contractMap);
await _batchOperate("addProgram", API_SERVER_PROGRAM_MAP);
await _batchOperate("addAdmin", API_SERVER_ADMIN_MAP);
await addInitColor();
}
function printContractMap() {
console.log("----- contract address list: ");
ContractMap.forEach(function (v, k) {
console.log("ContractAddr:", v.address, "for", k);
});
console.log("----- contract address list end. ");
}
async function main() {
if (!ADDR_MINT_RECEIVER) {
console.log("Please set TOKEN721_RECEIVER in .env file first.");
return;
}
console.log("Initial deploy started");
// Hardhat always runs the compile task when running scripts with its command
// line interface.
//
// We get the contract list to deploy
await initialDeploy();
await initialSetting();
await mintArena();
await mintEquip(10);
console.log("Initial deploy finished");
printContractMap();
// await batchMintHorseToPool(ContractMap.get("RaceExtra").address);
// await addMysteryBoxToken(ContractMap.get("NFTMysteryBoxOffering").address);
// printContractMap();
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
/* eslint-disable prefer-const */
/* eslint-disable dot-notation */
/* eslint-disable no-unused-vars */
/* eslint-disable eqeqeq */
/* eslint-disable camelcase */
/* eslint-disable no-lone-blocks */
// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// When running the script with `npx hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
const { ContractFactory } = require("ethers");
const hre = require("hardhat");
// const { upgrades } = require("@openzeppelin/hardhat-upgrades");
const HORSE_GENE = {
DARLEY_ARABIAN: ["VVEEAADDTTHH"],
GODOLPHIN_ARABIAN: [
"VVEEAADDTThh",
"VVEEAADDttHH",
"VVEEAAddTTHH",
"VVEEaaDDTTHH",
"VVeeAADDTTHH",
"vvEEAADDTTHH",
],
BYERLY_TURK: [
"VVEEAADDtthh",
"VVEEAAddTThh",
"VVEEaaDDTThh",
"VVeeAADDTThh",
"vvEEAADDTThh",
"VVEEAAddttHH",
"VVEEaaDDttHH",
"VVeeAADDttHH",
"vvEEAADDttHH",
"VVEEaaddTTHH",
"VVeeAAddTTHH",
"vvEEAAddTTHH",
"VVeeaaDDTTHH",
"vvEEaaDDTTHH",
"vveeAADDTTHH",
],
SATOSHI_NAKAMOTO: [
"VVEEAAddtthh",
"VVEEaaDDtthh",
"VVEEaaddTThh",
"VVEEaaddttHH",
"VVeeAADDtthh",
"VVeeAAddTThh",
"VVeeAAddttHH",
"VVeeaaDDTThh",
"VVeeaaDDttHH",
"VVeeaaddTTHH",
"vvEEAADDtthh",
"vvEEAAddTThh",
"vvEEAAddttHH",
"vvEEaaddTTHH",
"vvEEaaDDTThh",
"vvEEaaDDttHH",
"vveeAADDTThh",
"vveeAADDttHH",
"vveeAAddTTHH",
"vveeaaDDTTHH",
],
};
const ADDR_MINT_RECEIVER = process.env.ADDR_MINT_RECEIVER;
const ADDR_BONUS_POOL = process.env.ADDR_BONUS_POOL;
const ADDR_BONUS_BURNED = process.env.ADDR_BONUS_BURNED;
const ADDR_BONUS_PLATFORM = process.env.ADDR_BONUS_PLATFORM;
const ADDR_FEE_RECEIVER = process.env.ADDR_FEE_RECEIVER;
const ADDR_USDT_TOKEN = process.env.ADDR_USDT_TOKEN;
const ADDR_API_SERVER = process.env.ADDR_API_SERVER;
// 装备类型
// 1 马头饰
// 2 马护甲
// 3 马尾饰
// 4 马蹄饰(暂未使用)
// 装备款式
// 1 - 5
// 1、 圣诞 套装
// 2、 庄重 套装
// 3、 淡雅 套装
// 4、 华丽 套装
// 5、 喜庆 套装
const BATCH_HORSE_COUNT = 10;
const BATCH_EQUIP_COUNT = 50;
const EQUIP_TYPE_COUNT = 3;
const EQUIP_STYLE_COUNT = 5;
const GAME_DISTANCE = {
1200: { fee: 5, award: 20 },
2400: { fee: 10, award: 20 },
3600: { fee: 15, award: 20 },
};
const HORSE_GENE_PROBABILITIES = [
[3000, 2000, 4000, 1000],
[4000, 2600, 2800, 600],
[4800, 3000, 1900, 300],
[5500, 3300, 1100, 100],
];
const MYSTERY_BOX_NAMES = ["PLATINUM", "GOLD", "SILVER", "BRONZE"];
const MYSTERY_BOX_PRICES = [400, 300, 200, 100];
const MYSTERY_BOX_HORSE_TYPES = [
"SATOSHI_NAKAMOTO",
"BYERLY_TURK",
"GODOLPHIN_ARABIAN",
"DARLEY_ARABIAN",
];
const MYSTERY_BOX_HORSE_COUNT = [100, 100, 100, 100];
const RELY_ON_ADMIN_MAP = [
{ contract: "EquipToken", params: ["EquipExtra"] },
{ contract: "HorseToken", params: ["RaceExtra"] },
{ contract: "ArenaToken", params: ["ArenaExtra"] },
];
const RELY_ON_MINTER_MAP = [
{ contract: "Coin", params: ["EquipExtra"] },
{ contract: "Coin", params: ["RaceExtra"] },
{ contract: "Coin", params: ["RaceExtra1"] },
{ contract: "Coin", params: ["RaceExtra2"] },
{ contract: "Coin", params: ["ArenaExtra"] },
{ contract: "Coin", params: ["ArenaExtra1"] },
{ contract: "Coin", params: ["ArenaExtra2"] },
{ contract: "Coin", params: ["ArenaExtra3"] },
{ contract: "Coin721", params: ["EquipExtra"] },
{ contract: "Coin721", params: ["RaceExtra2"] },
];
const RELY_ON_PROGRAM_MAP = [
{ contract: "EquipAttr", params: ["EquipExtra"] },
{ contract: "EquipAttr", params: ["RaceExtra1"] },
{ contract: "RaceAttr1", params: ["ArenaExtra1"] },
{ contract: "RaceAttr1", params: ["RaceExtra2"] },
{ contract: "RaceAttr1", params: ["RaceExtra1"] },
{ contract: "RaceAttr1", params: ["RaceExtra"] },
{ contract: "RaceAttr1_1", params: ["EquipExtra"] },
{ contract: "RaceAttr1_1", params: ["RaceExtra"] },
{ contract: "RaceAttr1_1", params: ["RaceExtra1"] },
{ contract: "RaceAttr1_1", params: ["RaceExtra2"] },
{ contract: "RaceAttr1_1", params: ["ArenaExtra"] },
{ contract: "RaceAttr1_1", params: ["ArenaExtra1"] },
{ contract: "RaceAttr1_1", params: ["ArenaExtra2"] },
{ contract: "RaceAttr1_1", params: ["ArenaExtra3"] },
{ contract: "ArenaAttr", params: ["ArenaExtra"] },
{ contract: "ArenaAttr", params: ["ArenaExtra1"] },
{ contract: "ArenaAttr", params: ["ArenaExtra2"] },
{ contract: "ArenaAttr", params: ["ArenaExtra3"] },
{ contract: "RaceNFTAttr", params: ["EquipAttr"] },
{ contract: "RaceNFTAttr", params: ["RaceAttr1"] },
{ contract: "RaceNFTAttr", params: ["RaceAttr1_1"] },
{ contract: "RaceNFTAttr", params: ["ArenaAttr"] },
{ contract: "RaceBonusDistribute", params: ["ArenaExtra1"] },
{ contract: "RaceBonusPool", params: ["RaceBonusDistribute"] },
{ contract: "RaceBonusData", params: ["RaceBonusPool"] },
{ contract: "RaceToken", params: ["ArenaExtra1"] },
{ contract: "HorseCourseAttr", params: ["ArenaExtra3"] },
{ contract: "HorseCourseAttrOpera", params: ["ArenaExtra3"] },
{ contract: "HorseCourseAttr", params: ["HorseCourseAttrOpera"] },
];
const OFFICIAL_CONTRACT_MAP = [
{ contract: "Constant", params: ["Coin721"] },
{ contract: "Constant", params: ["EquipExtra"] },
{ contract: "Constant", params: ["RaceExtra"] },
{ contract: "Constant", params: ["RaceExtra1"] },
{ contract: "Constant", params: ["RaceExtra2"] },
{ contract: "Constant", params: ["ArenaExtra"] },
{ contract: "Constant", params: ["ArenaExtra1"] },
{ contract: "Constant", params: ["ArenaExtra2"] },
{ contract: "Constant", params: ["ArenaExtra3"] },
];
const TRANSFER_HANDLER_MAP = [
{ contract: "ArenaToken", params: ["ArenaExtra"] },
{ contract: "EquipToken", params: ["EquipExtra"] },
{ contract: "HorseToken", params: ["RaceExtra1"] },
];
const accounts = [{ address: ADDR_API_SERVER }];
const API_SERVER_PROGRAM_MAP = [
{ contract: "ArenaExtra", params: [{ address: ADDR_API_SERVER }] },
{ contract: "ArenaExtra1", params: [{ address: ADDR_API_SERVER }] },
{ contract: "ArenaExtra2", params: [{ address: ADDR_API_SERVER }] },
{ contract: "ArenaExtra3", params: [{ address: ADDR_API_SERVER }] },
{ contract: "HorseCourseAttr", params: [{ address: ADDR_API_SERVER }] },
{ contract: "HorseCourseAttrOpera", params: [{ address: ADDR_API_SERVER }] },
{ contract: "RaceExtra1", params: [{ address: ADDR_API_SERVER }] },
];
const API_SERVER_ADMIN_MAP = [
{ contract: "RaceExtra1", params: [{ address: ADDR_API_SERVER }] },
{ contract: "Constant", params: [{ address: ADDR_API_SERVER }] },
];
let ContractMap = new Map();
async function deployUpgradeContract(
contractPath,
contractName,
addAdmin,
addrProgram,
contractOptions
) {
const factory = await hre.ethers.getContractFactory(
contractPath,
contractOptions
);
let args = [];
for (let i = 5; i < arguments.length; i++) {
args.push(arguments[i]);
}
const contract = await upgrades.deployProxy(factory, [], {
initializer: "initialize", // Specify the initializer function
unsafeAllowLinkedLibraries: true,
});
await contract.waitForDeployment();
var contractAddr = await contract.getAddress();
contract.address = contractAddr;
console.log(
"DeployedContractProxy:",
contractAddr,
"for",
contractName,
contractPath + "(" + args.join(",") + ")"
);
ContractMap.set(contractName, contract);
if (addAdmin) {
// await _addAdminSender(contract);
}
if (addrProgram != undefined) {
await contract.addProgram(addrProgram);
}
return contract;
}
async function deployContract(
contractPath,
contractName,
addAdmin,
addrProgram,
contractOptions
) {
const factory = await hre.ethers.getContractFactory(
contractPath,
contractOptions
);
let args = [];
for (let i = 5; i < arguments.length; i++) {
args.push(arguments[i]);
}
const contract = await factory.deploy.apply(factory, args);
await contract.waitForDeployment();
var contractAddr = await contract.getAddress();
contract.address = contractAddr;
console.log(
"DeployedContract:",
contractAddr,
"for",
contractName,
contractPath + "(" + args.join(",") + ")"
);
ContractMap.set(contractName, contract);
if (addAdmin) {
// await _addAdminSender(contract);
}
if (addrProgram != undefined) {
await contract.addProgram(addrProgram);
}
return contract;
}
async function getContract(contractPath, address) {
return await hre.ethers.getContractAt(contractPath, address);
}
async function settingBonusDistribute(distribute, nftHorse, bonusPool) {
const percentForArenaOwner = 800; // 8%
const percentForWinners = [
4000, 2000, 960, 640, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
const set = await distribute.setSettings(
percentForArenaOwner,
percentForWinners,
[ADDR_BONUS_POOL, ADDR_BONUS_BURNED, ADDR_BONUS_PLATFORM],
[500, 200, 500],
[bonusPool],
nftHorse
);
await set.wait();
console.log("SettingBonusDistribute finished.");
return distribute;
}
async function settingBonusPool(contract, bonusData, metaToken, horseNft) {
const set = await contract.setContracts(
bonusData,
metaToken,
horseNft,
ADDR_BONUS_POOL
);
await set.wait();
console.log("SettingBonusPool finished.");
}
async function deployBonus(metaToken, horseNft) {
const distribute = await deployUpgradeContract(
"RaceBonusDistribute",
"RaceBonusDistribute",
true
);
const raceBonusPool = await deployUpgradeContract(
"RaceBonusPool",
"RaceBonusPool",
true
);
const raceBonusData = await deployUpgradeContract(
"RaceBonusData",
"RaceBonusData",
true
);
await settingBonusPool(
raceBonusPool,
getContractAddr(raceBonusData),
getContractAddr(metaToken),
getContractAddr(horseNft)
);
await settingBonusDistribute(
distribute,
getContractAddr(horseNft),
getContractAddr(raceBonusPool)
);
console.log(
"DeployBonus: setting finished",
getContractAddr(distribute),
getContractAddr(raceBonusData),
getContractAddr(raceBonusPool)
);
return {
distribute: distribute,
raceBonusData: raceBonusData,
raceBonusPool: raceBonusPool,
};
}
async function setMysteryBoxData(NFTMysteryBoxOffering, horseNFT, priceToken) {
await NFTMysteryBoxOffering.setBox(
MYSTERY_BOX_NAMES,
[horseNFT, horseNFT, horseNFT, horseNFT],
[1000, 1000, 1000, 1000]
);
console.log("SetMysteryBoxData: setBox finished.");
for (let i = 0; i < 4; i++) {
const prices = [MYSTERY_BOX_PRICES[i]];
const tokens = [priceToken];
const probabilities = [0, 0, 0, 0];
for (let j = 0; j < 4; j++) {
probabilities[j] = HORSE_GENE_PROBABILITIES[i][j];
}
await NFTMysteryBoxOffering.setPrice(MYSTERY_BOX_NAMES[i], tokens, prices);
console.log(
"SetMysteryBoxData: setPrice " + MYSTERY_BOX_NAMES[i] + " finished."
);
await NFTMysteryBoxOffering.setProbability(
MYSTERY_BOX_NAMES[i],
MYSTERY_BOX_HORSE_TYPES,
probabilities
);
console.log(
"SetMysteryBoxData: setProbability " + MYSTERY_BOX_NAMES[i] + " finished."
);
}
}
async function addMysteryBoxToken(address) {
const NFTMysteryBoxOffering = await getContract(
"NFTMysteryBoxOffering",
address
);
console.log("addMysteryBoxToken: " + address);
let k = 1;
for (let i = 0; i < MYSTERY_BOX_HORSE_COUNT.length; i++) {
for (let j = 0; j < MYSTERY_BOX_HORSE_COUNT.length; j++) {
const count =
(HORSE_GENE_PROBABILITIES[j][i] * MYSTERY_BOX_HORSE_COUNT[j]) / 10000;
const start = k;
const end = k + count - 1;
console.log(
"addMysteryBoxToken: addToken start " +
MYSTERY_BOX_NAMES[j] +
" " +
start +
"," +
end
);
await NFTMysteryBoxOffering["addToken(string,uint256,uint256)"](
MYSTERY_BOX_NAMES[j],
start,
end
);
console.log(
"addMysteryBoxToken: addToken ended " +
MYSTERY_BOX_NAMES[j] +
" " +
start +
"," +
end
);
k += count;
}
}
}
async function deployMysteryBox(rewardToken, horseNFT, priceToken) {
const NFTMysteryBoxOffering = await deployUpgradeContract(
"NFTMysteryBoxOffering",
"NFTMysteryBoxOffering"
);
const Random = await deployUpgradeContract(
"Random",
"Random",
false,
getContractAddr(NFTMysteryBoxOffering)
);
const Whitelist = await deployUpgradeContract(
"Whitelist",
"Whitelist",
false,
getContractAddr(NFTMysteryBoxOffering)
);
const MysteryBox = await deployUpgradeContract(
"MysteryBox",
"MysteryBox",
false,
getContractAddr(NFTMysteryBoxOffering)
);
const MysteryData = await deployUpgradeContract(
"MysteryData",
"MysteryData",
false,
getContractAddr(NFTMysteryBoxOffering)
);
await NFTMysteryBoxOffering.setContracts(
getContractAddr(Random),
getContractAddr(MysteryBox),
getContractAddr(MysteryData),
getContractAddr(Whitelist),
rewardToken
);
console.log("DeployMysteryBox: setContracts finished.");
await NFTMysteryBoxOffering.setAccounts(
ADDR_MINT_RECEIVER,
ADDR_MINT_RECEIVER
);
console.log("DeployMysteryBox: setAccounts finished.");
await setMysteryBoxData(NFTMysteryBoxOffering, horseNFT, priceToken);
console.log("DeployMysteryBox: setMysteryBoxData finished.");
console.log("DeployMysteryBox: finished.");
}
function getContractAddr(contract) {
console.log("contract addr is ", contract.address);
return contract.address;
// var addr ;
// contract.getAddress().then((address) => {
// addr = address;
// });
// return addr
}
async function initialDeploy() {
await deployUpgradeContract("UserLoginContract", "UserLogin", true);
const constant = await deployConstant();
const metaToken = await deployContract("MetaToken", "MetaToken", true);
const raceToken = await deployContract("RaceToken", "RaceToken", true);
let AddrUsdtToken = ADDR_USDT_TOKEN;
if (ADDR_USDT_TOKEN === "" || ADDR_USDT_TOKEN === undefined) {
const usdtToken = await deployContract("UsdtToken", "UsdtToken", true);
AddrUsdtToken = getContractAddr(usdtToken);
}
const coin = await deployCoin(
getContractAddr(metaToken),
getContractAddr(raceToken),
AddrUsdtToken
);
const equipNft = await deployContract("EquipToken", "EquipToken");
const horseNft = await deployContract("HorseToken", "HorseToken");
const arenaNft = await deployContract("ArenaToken", "ArenaToken");
const coin721 = await deployCoin721(
getContractAddr(equipNft),
getContractAddr(horseNft),
getContractAddr(arenaNft)
);
await deployMysteryBox(getContractAddr(metaToken), getContractAddr( horseNft), AddrUsdtToken);
const bonus = await deployBonus(metaToken, horseNft);
const nftAttr = await deployNFTAttr(
getContractAddr(equipNft),
getContractAddr(horseNft),
getContractAddr(arenaNft)
);
const equipAttr = await deployNftAttrOpera(
"HorseEquipAttrOperaContract",
"EquipAttr",
getContractAddr(nftAttr),
getContractAddr(equipNft)
);
const arenaAttr = await deployNftAttrOpera(
"HorseArenaAttrOperaContract",
"ArenaAttr",
getContractAddr(nftAttr),
getContractAddr(arenaNft)
);
const raceAttr1 = await deployNftAttrOpera(
"HorseRaceAttrOpera1",
"RaceAttr1",
getContractAddr(nftAttr),
getContractAddr(horseNft)
);
const raceAttr1_1 = await deployNftAttrOpera(
"HorseRaceAttrOpera1_1",
"RaceAttr1_1",
getContractAddr(nftAttr),
getContractAddr(horseNft)
);
const raceAttr2 = await deployNftAttrOpera(
"HorseRaceAttrOpera2",
"RaceAttr2",
getContractAddr(nftAttr),
getContractAddr(horseNft)
);
const raceAttr2_1 = await deployNftAttrOpera(
"HorseRaceAttrOpera2_1",
"RaceAttr2_1",
getContractAddr(nftAttr),
getContractAddr(horseNft)
);
const raceCourseAttr = await deployRaceCourseAttr();
const raceCourseAttrOp = await deployRaceCourseAttrOpera(
getContractAddr(raceCourseAttr)
);
const libBytes = await deployContract(
"contracts/library/Bytes.sol:Bytes",
"Bytes"
);
const contractOptions = {
libraries: {
Bytes: getContractAddr(libBytes),
},
};
const emptyContractOptions = {
};
await deployEquipExtra(
await coin.getAddress(),
coin721,
getContractAddr(equipAttr),
getContractAddr(equipNft),
ADDR_FEE_RECEIVER,
getContractAddr(constant),
getContractAddr(raceAttr1_1)
);
await deployRaceExtra(
emptyContractOptions,
getContractAddr(raceAttr1),
getContractAddr(raceAttr1_1),
getContractAddr(horseNft),
getContractAddr(raceAttr2),
getContractAddr(raceAttr2_1),
getContractAddr(coin),
coin721,
getContractAddr(constant),
ADDR_FEE_RECEIVER,
getContractAddr(equipAttr),
getContractAddr(equipNft)
);
await deployRaceExtra1(
emptyContractOptions,
getContractAddr(raceAttr1),
getContractAddr(raceAttr1_1),
getContractAddr(horseNft),
getContractAddr(raceAttr2),
getContractAddr(raceAttr2_1),
getContractAddr(coin),
coin721,
getContractAddr(constant),
ADDR_FEE_RECEIVER,
getContractAddr(equipAttr),
getContractAddr(equipNft)
);
await deployRaceExtra2(
contractOptions,
getContractAddr(raceAttr1),
getContractAddr(raceAttr1_1),
getContractAddr(horseNft),
getContractAddr(raceAttr2),
getContractAddr(raceAttr2_1),
getContractAddr(coin),
coin721,
getContractAddr(constant),
ADDR_FEE_RECEIVER,
getContractAddr(equipAttr),
getContractAddr(equipNft)
);
await deployArenaExtra(
emptyContractOptions,
getContractAddr(arenaAttr),
getContractAddr(raceCourseAttrOp),
getContractAddr(arenaNft),
getContractAddr(coin),
getContractAddr(constant),
ADDR_FEE_RECEIVER,
getContractAddr(raceAttr1),
getContractAddr(raceAttr1_1),
getContractAddr(raceAttr2),
getContractAddr(raceAttr2_1),
getContractAddr(horseNft),
getContractAddr(bonus.distribute)
);
await deployArenaExtra1(
contractOptions,
getContractAddr(arenaAttr),
getContractAddr(raceCourseAttrOp),
getContractAddr(arenaNft),
getContractAddr(coin),
getContractAddr(constant),
ADDR_FEE_RECEIVER,
getContractAddr(raceAttr1),
getContractAddr(raceAttr1_1),
getContractAddr(raceAttr2),
getContractAddr(raceAttr2_1),
getContractAddr(horseNft),
getContractAddr(metaToken),
getContractAddr(raceToken),
getContractAddr(bonus.distribute)
);
await deployArenaExtra2(
contractOptions,
getContractAddr(arenaAttr),
getContractAddr(raceCourseAttrOp),
getContractAddr(arenaNft),
getContractAddr(coin),
getContractAddr(constant),
ADDR_FEE_RECEIVER,
getContractAddr(raceAttr1),
getContractAddr(raceAttr1_1),
getContractAddr(raceAttr2),
getContractAddr(raceAttr2_1),
getContractAddr(horseNft)
);
await deployArenaExtra3(
contractOptions,
getContractAddr(arenaAttr),
getContractAddr(raceCourseAttrOp),
getContractAddr(arenaNft),
getContractAddr(coin),
getContractAddr(constant),
ADDR_FEE_RECEIVER,
getContractAddr(raceAttr1),
getContractAddr(raceAttr1_1),
getContractAddr(raceAttr2),
getContractAddr(raceAttr2_1),
getContractAddr(horseNft)
);
await _batchOperate("addMinter", RELY_ON_MINTER_MAP);
console.log("SetPermission addMinter finished.");
await _batchOperate("addAdmin", RELY_ON_ADMIN_MAP);
console.log("SetPermission addAdmin finished.");
await _batchOperate("addProgram", RELY_ON_PROGRAM_MAP);
console.log("SetPermission addProgram finished.");
await _batchOperate("registerTransferHandler", TRANSFER_HANDLER_MAP);
console.log("SetTransferHandler finished.");
await _batchOperate("addOfficialContract", OFFICIAL_CONTRACT_MAP);
console.log("AddOfficial finished.");
}
async function deployConstant() {
const contract = await deployUpgradeContract("Constant", "Constant", true);
for (let k in GAME_DISTANCE) {
await contract.setApplyGameAmount(k, GAME_DISTANCE[k].fee);
await contract.setAwardGameAmount(k, GAME_DISTANCE[k].award);
}
return contract;
}
async function deployCoin(metaToken, raceToken, usdtToken) {
const contract = await deployUpgradeContract("Coin", "Coin", true);
const tokenId = [1, 2, 3];
const tokenAddress = [metaToken, raceToken, usdtToken];
const tokenPrice = [1, 1, 10000];
const addTokens = await contract.add(tokenId, tokenAddress, tokenPrice);
await addTokens.wait();
console.log("deployCoin: addTokens(" + tokenAddress.join(",") + ")");
return contract;
}
async function deployCoin721(equipNft, horseNft, arenaNft) {
const contract = await deployUpgradeContract("Coin721", "Coin721", true);
const tokenAddress = [equipNft, horseNft, arenaNft];
const addTokens = await contract.add(tokenAddress);
await addTokens.wait();
console.log("deployCoin721: addTokens(" + tokenAddress.join(",") + ")");
return contract;
}
async function _setEquipFields(attrContract, equipNft) {
const fields = [
"horseEquipTypes",
"horseEquipStyle",
"horseEquipStatus",
"horseEquipPrice",
"horseEquipOfUid",
"horseEquipOfHorseId",
"horseEquipDiscount",
"horseEquipReward",
"horseEquipCoin",
"horseEquipLastOwner",
"horseEquipLastPrice",
"lastOperaTime",
];
const ftypes = [1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1];
const fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
const setfield = await attrContract.setFiled(
equipNft,
fields,
ftypes,
fauths
);
await setfield.wait();
}
async function _setHorseFields(attrContract, horseNft) {
let fields = [
"horseRaceName",
"nameUptCount",
"birthDay",
"mainGeneration",
"slaveGeneration",
"generationScore",
"gender",
"color",
"gene",
"gripGene",
];
let ftypes = [2, 1, 1, 1, 1, 1, 1, 1, 1, 1];
let fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
let setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = [
"accGene",
"endGene",
"speedGene",
"turnToGene",
"controlGene",
"trainingValue",
"trainingTime",
"useTraTime",
"energy",
"energyUpdateTime",
];
ftypes = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = [
"gradeScore",
"gradeIntegral",
"gradeScoreMark",
"raceScoreUpdateTime",
"father",
"mother",
"breedCount",
"breedTime",
"gradeIntegralYear",
"gradeIntegralYearTime",
];
ftypes = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = [
"gradeIntegralMonth",
"gradeIntegralMonthTime",
"gradeIntegralWeek",
"gradeIntegralWeekTime",
];
ftypes = [1, 1, 1, 1];
fauths = [2, 2, 2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = [
"headWearId",
"armorId",
"ponytailId",
"hoofId",
"grade",
"raceCount",
"winCount",
"raceId",
"raceType",
"racecourse",
];
ftypes = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = [
"distance",
"raceUpdateTime",
"horseRaceStatus",
"horseRaceDiscount",
"horseRaceReward",
"horseRaceCoin",
"horseRaceLastOwner",
"horseRaceLastPrice",
"horseRacePrice",
];
ftypes = [1, 1, 1, 1, 1, 1, 1, 1, 1];
fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
fields = ["sellUpdateTime", "studUpdateTime"];
ftypes = [1, 1];
fauths = [2, 2];
setfield = await attrContract.setFiled(horseNft, fields, ftypes, fauths);
await setfield.wait();
}
async function _setArenaFields(attrContract, arenaNft) {
const fields = [
"name",
"createTime",
"ownerType",
"isClose",
"raceCount",
"lastRaceTime",
"totalRaceCount",
"mortAmount",
"gameId",
"horseIds",
];
const ftypes = [2, 1, 1, 1, 1, 1, 1, 1, 1, 1];
const fauths = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
const setfield = await attrContract.setFiled(
arenaNft,
fields,
ftypes,
fauths
);
await setfield.wait();
}
async function deployNFTAttr(equipNft, horseNft, arenaNft) {
const contract = await deployUpgradeContract("ERC721Attr", "RaceNFTAttr", true);
await _setEquipFields(contract, equipNft);
await _setHorseFields(contract, horseNft);
await _setArenaFields(contract, arenaNft);
return contract;
}
async function deployNftAttrOpera(contractPath, contractName, nftAttr, nft) {
const contract = await deployUpgradeContract(contractPath, contractName, true);
const init = await contract.init(nftAttr, nft);
await init.wait();
return contract;
}
async function deployRaceCourseAttr() {
const contract = await deployUpgradeContract("ERC721Attr", "HorseCourseAttr", true);
return contract;
}
async function deployRaceCourseAttrOpera(raceCourseAttr) {
const contract = await deployUpgradeContract(
"RacecourseAttrOperaContract",
"HorseCourseAttrOpera",
true
);
const init = await contract.init(raceCourseAttr);
await init.wait();
return contract;
}
async function deployEquipExtra(
coin,
coin721,
equipAttrOpera,
equipNft,
feeAddr,
constant,
raceHorseAttr1_1
) {
const contract = await deployUpgradeContract(
"HorseEquipContract",
"EquipExtra",
true
);
const init = await contract.initHorseEquipAttrAddress(
coin,
getContractAddr(coin721),
equipAttrOpera,
equipNft,
feeAddr,
constant,
raceHorseAttr1_1
);
await init.wait();
return contract;
}
async function deployRaceExtra(
contractOptions,
raceAttr1,
raceAttr1_1,
horseNft,
raceAttr2,
raceAttr2_1,
coin,
coin721,
constant,
feeAddr,
equipAttr,
equipNft
) {
const contract = await deployUpgradeContract(
"HorseRaceContract",
"RaceExtra",
true,
undefined,
contractOptions
);
const init = await contract.initHorseRaceAttrAddress(
raceAttr1,
raceAttr1_1,
horseNft,
raceAttr2,
raceAttr2_1,
coin,
constant,
feeAddr
);
await init.wait();
return contract;
}
async function deployRaceExtra1(
contractOptions,
raceAttr1,
raceAttr1_1,
horseNft,
raceAttr2,
raceAttr2_1,
coin,
coin721,
constant,
feeAddr,
equipAttr,
equipNft
) {
const contract = await deployUpgradeContract(
"HorseRaceExtra1",
"RaceExtra1",
true,
undefined,
contractOptions
);
const init = await contract.initHorseRaceAttrAddress(
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
equipAttr,
horseNft,
equipNft,
constant,
coin,
feeAddr
);
await init.wait();
return contract;
}
async function deployRaceExtra2(
contractOptions,
raceAttr1,
raceAttr1_1,
horseNft,
raceAttr2,
raceAttr2_1,
coin,
coin721,
constant,
feeAddr,
equipAttr,
equipNft
) {
const contract = await deployUpgradeContract("HorseRaceExtra2", "RaceExtra2", true);
const init = await contract.initHorseRaceAttrAddress(
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
coin,
getContractAddr(coin721),
horseNft,
constant,
feeAddr
);
await init.wait();
return contract;
}
async function deployArenaExtra(
contractOptions,
arenaAttr,
courseAttr,
arenaNft,
coin,
constant,
feeAddr,
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
horseNft,
distribute
) {
const contract = await deployUpgradeContract(
"HorseArenaContract",
"ArenaExtra",
true,
undefined,
contractOptions
);
const init = await contract.init(arenaAttr, arenaNft, coin, constant);
await init.wait();
return contract;
}
async function deployArenaExtra1(
contractOptions,
arenaAttr,
courseAttr,
arenaNft,
coin,
constant,
feeAddr,
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
horseNft,
metaToken,
raceToken,
distribute
) {
const contract = await deployUpgradeContract("HorseArenaExtra", "ArenaExtra1", true);
const init = await contract.init(
arenaAttr,
coin,
courseAttr,
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
horseNft,
arenaNft,
constant,
metaToken,
raceToken
);
await init.wait();
await contract.setDistribute(distribute);
return contract;
}
async function deployArenaExtra2(
contractOptions,
arenaAttr,
courseAttr,
arenaNft,
coin,
constant,
feeAddr,
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
horseNft
) {
const contract = await deployUpgradeContract(
"HorseArenaExtra2",
"ArenaExtra2",
true
);
const init = await contract.init(
arenaAttr,
coin,
horseNft,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
constant
);
await init.wait();
return contract;
}
async function deployArenaExtra3(
contractOptions,
arenaAttr,
courseAttr,
arenaNft,
coin,
constant,
feeAddr,
raceAttr1,
raceAttr1_1,
raceAttr2,
raceAttr2_1,
horseNft
) {
const contract = await deployUpgradeContract(
"HorseArenaExtra3",
"ArenaExtra3",
true
);
const init = await contract.init(
arenaAttr,
courseAttr,
raceAttr1_1,
raceAttr2_1,
constant
);
await init.wait();
return contract;
}
function _allColor() {
const colors = [];
colors.push("FF00FFFF"); // 紫色
colors.push("FF5A00FF"); // 棕色
colors.push("00FFFFFF"); // 青色
colors.push("FFFFFFFF"); // 原色
return colors;
}
async function mintHorse(horseRaceAddr, toAddr, styleName, start, count) {
let horseIdx = start;
const prefix = "MR";
const horseRaceContract = await hre.ethers.getContractAt(
"HorseRaceContract",
horseRaceAddr
);
let pCount = BATCH_HORSE_COUNT;
let total = 0;
const geneList = HORSE_GENE[styleName];
const colors = _allColor();
for (total = 0; total < count; ) {
if (count - total > BATCH_HORSE_COUNT) {
pCount = BATCH_HORSE_COUNT;
} else {
pCount = count - total;
}
console.log("Mint horse count ", pCount);
const name = [];
const style = [];
const mainGeneration = [];
const slaveGeneration = [];
const generationScore = [];
const gender = [];
const color = [];
const gene = [];
const to = [];
for (let i = 1; i <= pCount; i++, horseIdx++) {
const cname = prefix + "-" + horseIdx;
name.push(cname);
style.push(styleName);
mainGeneration.push(0);
slaveGeneration.push(0);
generationScore.push(10000);
to.push(toAddr);
if (i % 2 == 0) {
gender.push(1); // male
} else {
gender.push(0); // female
}
const initGene = geneList[i % geneList.length];
const nColor = colors[i % colors.length];
color.push(nColor);
gene.push(initGene);
}
const mint = await horseRaceContract.batchMintHorse(
name,
style,
mainGeneration,
slaveGeneration,
generationScore,
gender,
color,
gene,
to
);
await mint.wait();
console.log(
"Batch mint horse to",
toAddr,
styleName,
total,
total + pCount
);
total += pCount;
}
console.log(
"Mint horse with style ",
styleName,
" finished, total ",
start,
total
);
}
async function batchMintHorseToPool(horseRaceAddr) {
let start = 1;
for (let i = 0; i < MYSTERY_BOX_HORSE_COUNT.length; i++) {
let count = 0;
for (let j = 0; j < MYSTERY_BOX_HORSE_COUNT.length; j++) {
count +=
(HORSE_GENE_PROBABILITIES[j][i] * MYSTERY_BOX_HORSE_COUNT[i]) / 10000;
}
await mintHorse(
horseRaceAddr,
ADDR_MINT_RECEIVER,
MYSTERY_BOX_HORSE_TYPES[i],
start,
count
);
start += count;
}
}
async function mintArena() {
const accounts = await hre.ethers.getSigners();
const metaToken = ContractMap.get("MetaToken");
const coinContract = ContractMap.get("Coin");
const constantContract = ContractMap.get("Constant");
const depositAmount = await constantContract.getMortAmount();
const decimals = await metaToken.decimals();
// const deposit = depositAmount * 10 ** decimals;
const deposit = BigInt(depositAmount) * BigInt(10 ** Number(decimals));
// 购买赛场需要抵押 meta token
const balance = await metaToken.balanceOf(accounts[0].address);
console.log("User have meta token %d and need deposit %d.", balance, deposit);
const approve = await metaToken.approve(getContractAddr(coinContract), balance);
await approve.wait();
const signer = process.env.NAME_SIGNER_KEY;
const arenaName = "MetaRace";
const hash = hre.ethers.solidityPackedKeccak256(["string"], [arenaName]);
const signingKey = new hre.ethers.SigningKey(signer);
const signature = await signingKey.sign(hash);
// const rawSign = await hre.ethers.joinSignature(signature);
const rawSign = signature.serialized
const horseArenaContract = ContractMap.get("ArenaExtra");
await horseArenaContract.mintOfficialArena(arenaName, rawSign);
console.log("Mint arena end.");
}
async function mintEquip(count) {
const equipExtra = ContractMap.get("EquipExtra");
let lstEquipType = [];
let lstEquipStyle = [];
if (count < 0) {
for (let i = 0; i < -count; i++) {
lstEquipType.push((i % EQUIP_TYPE_COUNT) + 1);
lstEquipStyle.push((i % EQUIP_STYLE_COUNT) + 1);
}
} else if (count > 0) {
for (let equipType = 1; equipType <= EQUIP_TYPE_COUNT; equipType++) {
for (let equipStyle = 1; equipStyle <= EQUIP_STYLE_COUNT; equipStyle++) {
for (let i = 0; i < count; i++) {
lstEquipType.push(equipType);
lstEquipStyle.push(equipStyle);
}
}
}
}
if (lstEquipType.length > 0) {
for (let i = 0; i < lstEquipType.length; i += BATCH_EQUIP_COUNT) {
let lstType = [];
let lstStyle = [];
let to = [];
let n =
i + BATCH_EQUIP_COUNT <= lstEquipType.length
? BATCH_EQUIP_COUNT
: lstEquipType.length - i;
for (let j = 0; j < n; j++) {
lstType[j] = lstEquipType[i + j];
lstStyle[j] = lstEquipStyle[i + j];
to[j] = ADDR_MINT_RECEIVER;
console.log(
"Mint equip with type = %d and style = %d.",
lstType[j],
lstStyle[j]
);
}
await equipExtra.batchMintEquip(to, lstType, lstStyle);
}
}
}
async function addInitColor() {
/*
color = "FF00FFFF"; // 紫色
color = "FF5A00FF"; // 棕色
color = "00FFFFFF"; // 青色
color = "FFFFFFFF"; // 原色
*/
const constant = ContractMap.get("Constant");
const colorList = _allColor();
for (const color of colorList) {
console.log("Added color", color);
await constant.addColor(color);
}
const count = await constant.getInitColorsCount();
// console.log("got init color count is ", count);
for (let i = 0; i < count; i++) {
const color = await constant.getInitColors(i);
console.log("Check color", color, "at", i);
}
}
async function _batchOperate(fn, lst) {
for (let i = 0; i < lst.length; i++) {
const item = lst[i];
let contract = ContractMap.get(item.contract);
if (item.contractPath && item.contractAddr) {
contract = await getContract(item.contractPath, item.contractAddr);
}
const isString = typeof item.params[0] == "string";
let addr = isString
? getContractAddr(ContractMap.get(item.params[0]))
: item.params[0].address;
if (addr) {
let args;
switch (fn) {
case "registerTransferHandler":
args = [addr, addr];
break;
default:
args = [addr];
}
await _callContract(
item.contract,
contract,
fn,
item.params,
args,
false
);
}
}
}
async function _callContract(name, contract, fn, params, args, isCall) {
const isString = typeof params[0] == "string";
let result;
switch (fn) {
case "registerTransferHandler":
result = await contract[fn].apply(contract, args);
break;
default:
result = await contract[fn].apply(contract, args);
}
if (!isCall) {
await result.wait();
console.log(
fn + "(" + name + "," + args[0] + (isString ? "," + params[0] : "") + ")"
);
} else {
console.log(
fn +
"(" +
name +
"," +
args[0] +
(isString ? "," + params[0] : "") +
") = " +
result
);
}
return result;
}
async function _checkOperate(fn, lst, fnSet) {
for (let i = 0; i < lst.length; i++) {
const item = lst[i];
const contract = await getContract(item.contractPath, item.contractAddr);
const isString = typeof item.params[0] == "string";
let addr = isString
? getContractAddr(ContractMap.get(item.params[0]))
: item.params[0].address;
if (addr) {
const result = await _callContract(
item.contract,
contract,
fn,
item.params,
[addr],
true
);
if (!result && fnSet) {
let args;
switch (fnSet) {
case "registerTransferHandler":
args = [addr, addr];
break;
default:
args = [addr];
}
await _callContract(
item.contract,
contract,
fnSet,
item.params,
args,
false
);
}
}
}
}
async function addOfficial() {
await _batchOperate("addOfficialContract", OFFICIAL_CONTRACT_MAP);
console.log("AddOfficial finished.");
}
async function setTransferHandler() {
await _batchOperate("registerTransferHandler", TRANSFER_HANDLER_MAP);
console.log("SetTransferHandler finished.");
}
async function checkPrivilege() {
const accounts = [{ address: ADDR_API_SERVER }];
const ProgramMap = [
{
contractPath: "HorseArenaExtra",
contractAddr: "0x05a757bf7C1811fC750879b68DC6a8c7bd2D8759",
contract: "ArenaExtra1",
params: accounts,
},
{
contractPath: "HorseArenaExtra3",
contractAddr: "0x9B8D70d2993b15F4DeA04e9C4A22183C05f0ec6f",
contract: "ArenaExtra3",
params: accounts,
},
{
contractPath: "HorseRaceExtra1",
contractAddr: "0xAE154d855c7e0aa9eF3f432A1051518f23167A63",
contract: "RaceExtra1",
params: accounts,
},
];
await _checkOperate("isProgram", ProgramMap, "addProgram");
const AdminMap = [
{
contractPath: "Constant",
contractAddr: "0x05De106a835E438AA02E103008Cc1dCD9425321d",
contract: "Constant",
params: accounts,
},
];
await _checkOperate("isAdmin", AdminMap, "addAdmin");
}
async function initialSetting() {
// await modifyConstant(contractMap);
await _batchOperate("addProgram", API_SERVER_PROGRAM_MAP);
await _batchOperate("addAdmin", API_SERVER_ADMIN_MAP);
await addInitColor();
}
function printContractMap() {
console.log("----- contract address list: ");
ContractMap.forEach(function (v, k) {
const contractAddr = getContractAddr(v);
console.log("ContractAddr:", contractAddr, "for", k);
});
console.log("----- contract address list end. ");
}
async function main() {
if (!ADDR_MINT_RECEIVER) {
console.log("Please set TOKEN721_RECEIVER in .env file first.");
return;
}
console.log("Initial deploy started");
// Hardhat always runs the compile task when running scripts with its command
// line interface.
//
// We get the contract list to deploy
await initialDeploy();
await initialSetting();
await mintArena();
await mintEquip(10);
console.log("Initial deploy finished");
printContractMap();
// await batchMintHorseToPool(ContractMap.get("RaceExtra").address);
// await addMysteryBoxToken(ContractMap.get("NFTMysteryBoxOffering").address);
// printContractMap();
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment