Commit 43cd466e authored by vicotor's avatar vicotor

add upgrade test code

parent bf959dc3
{addr: "0x452B05527F70bE30e16D01610C57E40c8ced54C6", name:"UserLogin"},
{addr: "0xD5e6035CE7371d0C0664A4d152788D8411F71fe7", name:"Constant"},
{addr: "0x913E224a67d160501744BeFc7fd279D228932b9B", name:"MetaToken"},
{addr: "0xb3842FEff99fC9dE995dE4FE81D9987654cdbf6D", name:"RaceToken"},
{addr: "0x4CB47128B01E15eb0aa0D2BC41a1c77CA3BF0654", name:"UsdtToken"},
{addr: "0xa849f84Bf38175D618d3495310672E5DFfFd6D24", name:"Coin"},
{addr: "0xBdFCeb5D19aa916a6CfdD6987D4c102700609Fc0", name:"EquipToken"},
{addr: "0xEEDb4FbC408E2C769BcEd2f89BcCb5E710E6842c", name:"HorseToken"},
{addr: "0x1e2B567dC82531c71057928D44944EF03Ba0BE46", name:"ArenaToken"},
{addr: "0x92dC3A31960E920f00B526bEc4594CCF13D244BF", name:"Coin721"},
{addr: "0xefB856A4A8fA069F60a41a2237a1eA4482FE7d4d", name:"NFTMysteryBoxOffering"},
{addr: "0xfd441677247Dd2961Bba8F46b4bb3D6598E172A3", name:"Random"},
{addr: "0xE32902791FCC89047465392600af7CF08073DdA5", name:"Whitelist"},
{addr: "0xD9e4fAa4C31694FcdFcfa2eDE8C3Ae7D25F28AB6", name:"MysteryBox"},
{addr: "0xb6b8A39137958B8DCd3A34E24A2E44787bc22bAF", name:"MysteryData"},
{addr: "0x196e5719F7983F8749A23B5142f7308f4196f6C3", name:"RaceBonusDistribute"},
{addr: "0x6e0bBb19021E290eCA0366D14c9FcC66DB1E15f2", name:"RaceBonusPool"},
{addr: "0x4f99c25aCA0d56Cf2E8E36D7e83C9a4329c5FB01", name:"RaceBonusData"},
{addr: "0xeE60AB31Da5f991D89D8918e2c1a784EEDe41f7f", name:"RaceNFTAttr"},
{addr: "0x897aF09d81d347BC4940E58157B672EdBC7Fa3Dd", name:"EquipAttr"},
{addr: "0xe40B9C2CAC590a45e666545862aA59a050f5C498", name:"ArenaAttr"},
{addr: "0x2bA3BD1bE12a696A5da58EF434d0Fa47B2bE4F5D", name:"RaceAttr1"},
{addr: "0x7Fe9395130Db10cB7B1c547632602F6d5608d72b", name:"RaceAttr1_1"},
{addr: "0x2d15B840CE5De85931d915003af44B29a78ae16D", name:"RaceAttr2"},
{addr: "0xC7B7b222cB8E12EF1B73123732b3aFA94FE5b835", name:"RaceAttr2_1"},
{addr: "0x147612b0E32B7Be28C32375A85B98A6b0FaF8d34", name:"HorseCourseAttr"},
{addr: "0xC8574F717bc5C5A9B029eAd3Da669E745E101542", name:"HorseCourseAttrOpera"},
{addr: "0x617a061015fdF830A1F5637469a51fb4879F0ddd", name:"Bytes"},
{addr: "0x3BCC634C43c15971623d5E33475b1732553440b9", name:"EquipExtra"},
{addr: "0x6bE51BD56aabAC86A8b0E62F7e23f2Aa49Bc92ac", name:"RaceExtra"},
{addr: "0x1C961B7373a5cF966F45Ab9Ad493C405943b3e3a", name:"RaceExtra1"},
{addr: "0xdb6e69467083fbe6AAE0dff0823353Ce82c8c35f", name:"RaceExtra2"},
{addr: "0x83c812Cd6e4ea911a9628bcDEBc48c079C92dC68", name:"ArenaExtra"},
{addr: "0xd1933659411d0Fe803f6eC24F6b47627210C5Db0", name:"ArenaExtra1"},
{addr: "0x5A952fbb82E3c1238d9692126A77002675A1D80f", name:"ArenaExtra2"},
{addr: "0x82a947F3D70C86E8Fc01d70414650fA29d9578d4", name:"ArenaExtra3"}
// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
contract Box {
uint256 private value;
// Emitted when the stored value changes
event ValueChanged(uint256 newValue);
// Stores a new value in the contract
function store(uint256 newValue) public {
value = newValue;
emit ValueChanged(newValue);
}
// Reads the last stored value
function retrieve() public view returns (uint256) {
return value;
}
}
// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
contract BoxV2 {
uint256 private value;
// Emitted when the stored value changes
event ValueChanged(uint256 newValue);
// Stores a new value in the contract
function store(uint256 newValue) public {
value = newValue;
emit ValueChanged(newValue);
}
// Reads the last stored value
function retrieve() public view returns (uint256) {
return value;
}
function increment() public {
value = value + 1;
emit ValueChanged(value);
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;
// Uncomment this line to use console.log
// import "hardhat/console.sol";
contract Lock {
uint public unlockTime;
address payable public owner;
event Withdrawal(uint amount, uint when);
constructor(uint _unlockTime) payable {
require(
block.timestamp < _unlockTime,
"Unlock time should be in the future"
);
unlockTime = _unlockTime;
owner = payable(msg.sender);
}
function withdraw() public {
// Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal
// console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp);
require(block.timestamp >= unlockTime, "You can't withdraw yet");
require(msg.sender == owner, "You aren't the owner");
emit Withdrawal(address(this).balance, block.timestamp);
owner.transfer(address(this).balance);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/Address.sol";
import "../game/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 Coin721V2 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)"));
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/Address.sol";
import "../game/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 CoinV2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "../game/Auth.sol";
contract ConstantV2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Bytes.sol";
import "../game/Auth.sol";
import "../Interface/BaseInterface.sol";
contract ERC721AttrV2 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];
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// 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 "../game/Auth.sol";
contract HorseArenaAttrOperaContractV2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// 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 "../game/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 HorseArenaExtra2V2 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);
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../Interface/ICoin.sol";
import "../game/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 HorseArenaExtra3V2 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");
}
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// 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 "../game/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 HorseArenaExtraV2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// 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 "../game/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 HorseArenaContractV2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// 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 "../game/Auth.sol";
contract HorseEquipAttrOperaContractV2 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();
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// 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 "../game/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 HorseEquipContractV2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Bytes.sol";
import "../library/Uint256.sol";
import "../library/String.sol";
import "../game/Auth.sol";
import "../Interface/IERC721Attr.sol";
import "../library/Address.sol";
contract HorseRaceAttrOpera1_1V2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Bytes.sol";
import "../game/Auth.sol";
import "../Interface/IERC721Token.sol";
import "../Interface/IERC721Attr.sol";
contract HorseRaceAttrOpera2V2 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);
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Bytes.sol";
import "../game/Auth.sol";
import "../Interface/IERC721Token.sol";
import "../Interface/IERC721Attr.sol";
contract HorseRaceAttrOpera2_1V2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../library/Bytes.sol";
import "../library/Uint256.sol";
import "../library/String.sol";
import "../game/Auth.sol";
import "../Interface/IERC721Token.sol";
import "../Interface/IERC721Attr.sol";
contract HorseRaceAttrOpera1V2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// 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 "../game/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 HorseRaceExtra1V2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// 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 "../game/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 HorseRaceExtra2V2 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);
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// 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 "../game/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 HorseRaceContractV2 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());
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// 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 "../game/Auth.sol";
contract RacecourseAttrOperaContractV2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "../game/Auth.sol";
contract UserLoginContractV2 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;
}
function getUpgradeInfo() public pure returns (string memory) {
return "V2.0.0";
}
}
......@@ -63,7 +63,9 @@ module.exports = {
},
cmp_test: {
accounts: [privateKey],
url: "https://rpc.block.caduceus.global",
// url: "https://rpc.block.caduceus.global",
// url: "https://rpc.echain.bitheart.org",
url: "https://flashy-necessary-feather.bsc-testnet.quiknode.pro/",
},
mantle: {
accounts: [privateKey],
......
// scripts/deploy.js
async function main() {
const Box = await ethers.getContractFactory("Box");
console.log("Deploying Box...");
const box = await upgrades.deployProxy(Box, [42], { initializer: 'store' });
await box.waitForDeployment();
const boxAddress = await box.getAddress();
console.log("Box deployed to:", boxAddress);
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
......@@ -469,13 +469,8 @@ async function deployMysteryBox(rewardToken, horseNFT, priceToken) {
}
function getContractAddr(contract) {
console.log("contract addr is ", contract.address);
// console.log("contract addr is ", contract.address);
return contract.address;
// var addr ;
// contract.getAddress().then((address) => {
// addr = address;
// });
// return addr
}
async function initialDeploy() {
......
/* 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 upgradeAbleContracts = [
{addr: "0x452B05527F70bE30e16D01610C57E40c8ced54C6", name:"UserLogin", path:"UserLoginContract"},
{addr: "0xD5e6035CE7371d0C0664A4d152788D8411F71fe7", name:"Constant", path:"Constant"},
{addr: "0xa849f84Bf38175D618d3495310672E5DFfFd6D24", name:"Coin", path:"Coin"},
{addr: "0x92dC3A31960E920f00B526bEc4594CCF13D244BF", name:"Coin721", path:"Coin721"},
// {addr: "0xefB856A4A8fA069F60a41a2237a1eA4482FE7d4d", name:"NFTMysteryBoxOffering", path:"NFTMysteryBoxOffering"},
// {addr: "0xfd441677247Dd2961Bba8F46b4bb3D6598E172A3", name:"Random", path:"Random"},
// {addr: "0xE32902791FCC89047465392600af7CF08073DdA5", name:"Whitelist", path:"Whitelist"},
// {addr: "0xD9e4fAa4C31694FcdFcfa2eDE8C3Ae7D25F28AB6", name:"MysteryBox", path:"MysteryBox"},
// {addr: "0xb6b8A39137958B8DCd3A34E24A2E44787bc22bAF", name:"MysteryData", path:"MysteryData"},
// {addr: "0x196e5719F7983F8749A23B5142f7308f4196f6C3", name:"RaceBonusDistribute", path:"RaceBonusDistribute"},
// {addr: "0x6e0bBb19021E290eCA0366D14c9FcC66DB1E15f2", name:"RaceBonusPool", path:"RaceBonusPool"},
// {addr: "0x4f99c25aCA0d56Cf2E8E36D7e83C9a4329c5FB01", name:"RaceBonusData", path:"RaceBonusData"},
{addr: "0xeE60AB31Da5f991D89D8918e2c1a784EEDe41f7f", name:"RaceNFTAttr", path:"ERC721Attr"},
{addr: "0x897aF09d81d347BC4940E58157B672EdBC7Fa3Dd", name:"EquipAttr", path:"HorseEquipAttrOperaContract"},
{addr: "0xe40B9C2CAC590a45e666545862aA59a050f5C498", name:"ArenaAttr", path:"HorseArenaAttrOperaContract"},
{addr: "0x2bA3BD1bE12a696A5da58EF434d0Fa47B2bE4F5D", name:"RaceAttr1", path:"HorseRaceAttrOpera1"},
{addr: "0x7Fe9395130Db10cB7B1c547632602F6d5608d72b", name:"RaceAttr1_1", path:"HorseRaceAttrOpera1_1"},
{addr: "0x2d15B840CE5De85931d915003af44B29a78ae16D", name:"RaceAttr2", path:"HorseRaceAttrOpera2"},
{addr: "0xC7B7b222cB8E12EF1B73123732b3aFA94FE5b835", name:"RaceAttr2_1", path:"HorseRaceAttrOpera2_1"},
{addr: "0x147612b0E32B7Be28C32375A85B98A6b0FaF8d34", name:"HorseCourseAttr", path:"ERC721Attr"},
{addr: "0xC8574F717bc5C5A9B029eAd3Da669E745E101542", name:"HorseCourseAttrOpera", path:"RacecourseAttrOperaContract"},
{addr: "0x3BCC634C43c15971623d5E33475b1732553440b9", name:"EquipExtra", path:"HorseEquipContract"},
{addr: "0x6bE51BD56aabAC86A8b0E62F7e23f2Aa49Bc92ac", name:"RaceExtra", path:"HorseRaceContract"},
{addr: "0x1C961B7373a5cF966F45Ab9Ad493C405943b3e3a", name:"RaceExtra1", path:"HorseRaceExtra1"},
{addr: "0xdb6e69467083fbe6AAE0dff0823353Ce82c8c35f", name:"RaceExtra2", path:"HorseRaceExtra2"},
{addr: "0x83c812Cd6e4ea911a9628bcDEBc48c079C92dC68", name:"ArenaExtra", path:"HorseArenaContract"},
{addr: "0xd1933659411d0Fe803f6eC24F6b47627210C5Db0", name:"ArenaExtra1", path:"HorseArenaExtra"},
{addr: "0x5A952fbb82E3c1238d9692126A77002675A1D80f", name:"ArenaExtra2", path:"HorseArenaExtra2"},
{addr: "0x82a947F3D70C86E8Fc01d70414650fA29d9578d4", name:"ArenaExtra3", path:"HorseArenaExtra3"}
]
let ContractMap = new Map();
async function getContract(contractPath, address) {
return await hre.ethers.getContractAt(contractPath, address);
}
async function upgradeContract(proxyAddress, contractName, contractPath) {
const newContract = await ethers.getContractFactory(contractPath);
console.log("upgrade " + contractPath + " to " + proxyAddress);
const nContract = await upgrades.upgradeProxy(proxyAddress, newContract);
await nContract.waitForDeployment();
const nAddress = await nContract.getAddress();
console.log(contractName + " deploy at:", nAddress);
}
async function upgradeAllContracts() {
for (let i = 0; i < upgradeAbleContracts.length; i++) {
const contract = upgradeAbleContracts[i];
const addr = contract.addr;
const name = contract.name;
const path = contract.path;
var newPath = path + "V2";
await upgradeContract(addr, name, newPath);
}
for (let i = 0; i < upgradeAbleContracts.length; i++) {
const contract = upgradeAbleContracts[i];
const addr = contract.addr;
const name = contract.name;
const path = contract.path;
var newPath = path + "V2";
const contractObj = await getContract(newPath, addr);
const version = await contractObj.getUpgradeInfo();
console.log("contract ", name, " version is ", version);
}
}
async function main() {
await upgradeAllContracts();
}
// 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;
});
// scripts/prepare_upgrade.js
async function main() {
const proxyAddress = '0x863dCa3ec27b12D2005f3cD857eD56153852B224';
const BoxV2 = await ethers.getContractFactory("BoxV2");
console.log("upgrade...");
const boxv2 = await upgrades.upgradeProxy(proxyAddress, BoxV2);
await boxv2.waitForDeployment();
const boxv2Address = await boxv2.getAddress();
console.log("BoxV2 at:", boxv2Address);
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
// test/Box.js
// Load dependencies
const { expect } = require('chai');
let Box;
let box;
// Start test block
describe('Box', function () {
beforeEach(async function () {
Box = await ethers.getContractFactory("Box");
box = await Box.deploy();
});
// Test case
it('retrieve returns a value previously stored', async function () {
// Store a value
await box.store(42);
// Test if the returned value is the same one
// Note that we need to use strings to compare the 256 bit integers
expect((await box.retrieve()).toString()).to.equal('42');
});
});
// test/Box.proxy.js
// Load dependencies
const { expect } = require('chai');
let Box;
let box;
// Start test block
describe('Box (proxy)', function () {
beforeEach(async function () {
Box = await ethers.getContractFactory("Box");
box = await upgrades.deployProxy(Box, [42], {initializer: 'store'});
});
// Test case
it('retrieve returns a value previously initialized', async function () {
// Test if the returned value is the same one
// Note that we need to use strings to compare the 256 bit integers
expect((await box.retrieve()).toString()).to.equal('42');
});
});
// test/BoxV2.js
// Load dependencies
const { expect } = require('chai');
let BoxV2;
let boxV2;
// Start test block
describe('BoxV2', function () {
beforeEach(async function () {
BoxV2 = await ethers.getContractFactory("BoxV2");
boxV2 = await BoxV2.deploy();
});
// Test case
it('retrieve returns a value previously stored', async function () {
// Store a value
await boxV2.store(42);
// Test if the returned value is the same one
// Note that we need to use strings to compare the 256 bit integers
expect((await boxV2.retrieve()).toString()).to.equal('42');
});
// Test case
it('retrieve returns a value previously incremented', async function () {
// Increment
await boxV2.increment();
// Test if the returned value is the same one
// Note that we need to use strings to compare the 256 bit integers
expect((await boxV2.retrieve()).toString()).to.equal('1');
});
});
// test/BoxV2.proxy.js
// Load dependencies
const { expect } = require('chai');
let Box;
let BoxV2;
let box;
let boxV2;
// Start test block
describe('BoxV2 (proxy)', function () {
beforeEach(async function () {
Box = await ethers.getContractFactory("Box");
BoxV2 = await ethers.getContractFactory("BoxV2");
box = await upgrades.deployProxy(Box, [42], {initializer: 'store'});
await box.waitForDeployment();
const nBoxAddr = await box.getAddress();
boxV2 = await upgrades.upgradeProxy(nBoxAddr, BoxV2);
});
// Test case
it('retrieve returns a value previously incremented', async function () {
// Increment
await boxV2.increment();
// Test if the returned value is the same one
// Note that we need to use strings to compare the 256 bit integers
expect((await boxV2.retrieve()).toString()).to.equal('43');
});
});
const {
time,
loadFixture,
} = require("@nomicfoundation/hardhat-toolbox/network-helpers");
const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs");
const { expect } = require("chai");
describe("Lock", function () {
// We define a fixture to reuse the same setup in every test.
// We use loadFixture to run this setup once, snapshot that state,
// and reset Hardhat Network to that snapshot in every test.
async function deployOneYearLockFixture() {
const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60;
const ONE_GWEI = 1_000_000_000;
const lockedAmount = ONE_GWEI;
const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS;
// Contracts are deployed using the first signer/account by default
const [owner, otherAccount] = await ethers.getSigners();
const Lock = await ethers.getContractFactory("Lock");
const lock = await Lock.deploy(unlockTime, { value: lockedAmount });
return { lock, unlockTime, lockedAmount, owner, otherAccount };
}
describe("Deployment", function () {
it("Should set the right unlockTime", async function () {
const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture);
expect(await lock.unlockTime()).to.equal(unlockTime);
});
it("Should set the right owner", async function () {
const { lock, owner } = await loadFixture(deployOneYearLockFixture);
expect(await lock.owner()).to.equal(owner.address);
});
it("Should receive and store the funds to lock", async function () {
const { lock, lockedAmount } = await loadFixture(
deployOneYearLockFixture
);
expect(await ethers.provider.getBalance(lock.target)).to.equal(
lockedAmount
);
});
it("Should fail if the unlockTime is not in the future", async function () {
// We don't use the fixture here because we want a different deployment
const latestTime = await time.latest();
const Lock = await ethers.getContractFactory("Lock");
await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith(
"Unlock time should be in the future"
);
});
});
describe("Withdrawals", function () {
describe("Validations", function () {
it("Should revert with the right error if called too soon", async function () {
const { lock } = await loadFixture(deployOneYearLockFixture);
await expect(lock.withdraw()).to.be.revertedWith(
"You can't withdraw yet"
);
});
it("Should revert with the right error if called from another account", async function () {
const { lock, unlockTime, otherAccount } = await loadFixture(
deployOneYearLockFixture
);
// We can increase the time in Hardhat Network
await time.increaseTo(unlockTime);
// We use lock.connect() to send a transaction from another account
await expect(lock.connect(otherAccount).withdraw()).to.be.revertedWith(
"You aren't the owner"
);
});
it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async function () {
const { lock, unlockTime } = await loadFixture(
deployOneYearLockFixture
);
// Transactions are sent using the first signer by default
await time.increaseTo(unlockTime);
await expect(lock.withdraw()).not.to.be.reverted;
});
});
describe("Events", function () {
it("Should emit an event on withdrawals", async function () {
const { lock, unlockTime, lockedAmount } = await loadFixture(
deployOneYearLockFixture
);
await time.increaseTo(unlockTime);
await expect(lock.withdraw())
.to.emit(lock, "Withdrawal")
.withArgs(lockedAmount, anyValue); // We accept any value as `when` arg
});
});
describe("Transfers", function () {
it("Should transfer the funds to the owner", async function () {
const { lock, unlockTime, lockedAmount, owner } = await loadFixture(
deployOneYearLockFixture
);
await time.increaseTo(unlockTime);
await expect(lock.withdraw()).to.changeEtherBalances(
[owner, lock],
[lockedAmount, -lockedAmount]
);
});
});
});
});
#!/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/testUpgrade.js --network $network
rm -rf .env
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