使用prettier格式化代码

This commit is contained in:
cebgcontract 2022-08-18 10:54:42 +08:00
parent cbf5712881
commit 69681b8106
28 changed files with 1632 additions and 1579 deletions

15
.prettierrc.json Normal file
View File

@ -0,0 +1,15 @@
{
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false,
"explicitTypes": "always"
}
}
]
}

View File

@ -3,7 +3,7 @@ pragma solidity 0.8.10;
contract Migrations { contract Migrations {
address public owner = msg.sender; address public owner = msg.sender;
uint public last_completed_migration; uint256 public last_completed_migration;
modifier restricted() { modifier restricted() {
require( require(
@ -13,7 +13,7 @@ contract Migrations {
_; _;
} }
function setCompleted(uint completed) external restricted { function setCompleted(uint256 completed) external restricted {
last_completed_migration = completed; last_completed_migration = completed;
} }

View File

@ -7,39 +7,51 @@ contract BETimelockController is TimelockController {
uint256 public constant MAX_DELAY = 16 days; uint256 public constant MAX_DELAY = 16 days;
uint256 private _minDelay; uint256 private _minDelay;
constructor( constructor(address[] memory proposers, address[] memory executors)
address[] memory proposers, TimelockController(MIN_DELAY, proposers, executors)
address[] memory executors) {
TimelockController(MIN_DELAY, proposers, executors){ _minDelay = MIN_DELAY;
_minDelay = MIN_DELAY;
} }
/**
* @dev Returns the minimum delay for an operation to become valid.
*
* This value can be changed by executing an operation that calls `updateDelay`.
*/
function getMinDelay()
public
view
virtual
override
returns (uint256 duration)
{
return _minDelay;
}
/** /**
* @dev Returns the minimum delay for an operation to become valid. * @dev Changes the minimum timelock duration for future operations.
* *
* This value can be changed by executing an operation that calls `updateDelay`. * Emits a {MinDelayChange} event.
*/ *
function getMinDelay() public view virtual override returns (uint256 duration) { * Requirements:
return _minDelay; *
} * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
* an operation where the timelock is the target and the data is the ABI-encoded call to this function.
/** */
* @dev Changes the minimum timelock duration for future operations. function updateDelay(uint256 newDelay) external virtual override {
* require(
* Emits a {MinDelayChange} event. msg.sender == address(this),
* "BETimelockController: caller must be timelock"
* Requirements: );
* require(
* - the caller must be the timelock itself. This can only be achieved by scheduling and later executing newDelay >= MIN_DELAY,
* an operation where the timelock is the target and the data is the ABI-encoded call to this function. "BETimelockController: newDelay must greater than or equal to MIN_DELAY"
*/ );
function updateDelay(uint256 newDelay) external virtual override { require(
require(msg.sender == address(this), "BETimelockController: caller must be timelock"); newDelay <= MAX_DELAY,
require(newDelay >= MIN_DELAY, "BETimelockController: newDelay must greater than or equal to MIN_DELAY"); "BETimelockController: newDelay must less than or equal to MAX_DELAY"
require(newDelay <= MAX_DELAY, "BETimelockController: newDelay must less than or equal to MAX_DELAY"); );
emit MinDelayChange(_minDelay, newDelay); emit MinDelayChange(_minDelay, newDelay);
_minDelay = newDelay; _minDelay = newDelay;
} }
} }

View File

@ -4,136 +4,123 @@ import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/access/Ownable.sol";
import "../utils/Approval.sol"; import "../utils/Approval.sol";
contract HasSignature is Ownable, Approval{ contract HasSignature is Ownable, Approval {
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID; uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS; address private immutable _CACHED_THIS;
bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH; bytes32 private immutable _TYPE_HASH;
mapping(bytes => bool) private _usedSignatures; mapping(bytes => bool) private _usedSignatures;
constructor(string memory name, string memory version) { constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version)); bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256( bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
); );
_HASHED_NAME = hashedName; _HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion; _HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid; _CACHED_CHAIN_ID = block.chainid;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator( _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(
typeHash, typeHash,
hashedName, hashedName,
hashedVersion hashedVersion
); );
_CACHED_THIS = address(this); _CACHED_THIS = address(this);
_TYPE_HASH = typeHash; _TYPE_HASH = typeHash;
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return
keccak256(
abi.encode(
typeHash,
nameHash,
versionHash,
block.chainid,
address(this)
)
);
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
} }
}
function _buildDomainSeparator( /**
bytes32 typeHash, * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
bytes32 nameHash, * function returns the hash of the fully encoded EIP712 message for this domain.
bytes32 versionHash *
) private view returns (bytes32) { * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
return *
keccak256( * ```solidity
abi.encode( * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
typeHash, * keccak256("Mail(address to,string contents)"),
nameHash, * mailTo,
versionHash, * keccak256(bytes(mailContents))
block.chainid, * )));
address(this) * address signer = ECDSA.recover(digest, signature);
) * ```
); */
function _hashTypedDataV4(bytes32 structHash)
internal
view
virtual
returns (bytes32)
{
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
function checkSigner712(
address signer,
bytes32 structHash,
bytes memory signature
) public view {
bytes32 digest = _hashTypedDataV4(structHash);
address recovered = ECDSA.recover(digest, signature);
require(recovered == signer, "[BE] invalid signature");
require(signer != address(0), "ECDSA: invalid signature");
}
function checkSigner(
address signer,
bytes32 hash,
bytes memory signature
) public pure {
require(signature.length == 65, "[BE] invalid signature length");
bytes32 ethSignedMessageHash = ECDSA.toEthSignedMessageHash(hash);
address recovered = ECDSA.recover(ethSignedMessageHash, signature);
require(recovered == signer, "[BE] invalid signature");
}
modifier signatureValid(bytes calldata signature) {
require(
!_usedSignatures[signature],
"signature used. please send another transaction with new signature"
);
_;
}
/**
* @dev mark signature used
*/
function useSignature(bytes calldata signature) public approvaled {
if (!_usedSignatures[signature]) {
_usedSignatures[signature] = true;
} }
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (
address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID
) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return
_buildDomainSeparator(
_TYPE_HASH,
_HASHED_NAME,
_HASHED_VERSION
);
}
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash)
internal
view
virtual
returns (bytes32)
{
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
function checkSigner712(
address signer,
bytes32 structHash,
bytes memory signature
) public view{
bytes32 digest = _hashTypedDataV4(structHash);
address recovered = ECDSA.recover(digest, signature);
require(recovered == signer, "[BE] invalid signature");
require(signer != address(0), "ECDSA: invalid signature");
}
function checkSigner(
address signer,
bytes32 hash,
bytes memory signature
) public pure {
require(signature.length == 65, "[BE] invalid signature length");
bytes32 ethSignedMessageHash = ECDSA.toEthSignedMessageHash(
hash
);
address recovered = ECDSA.recover(ethSignedMessageHash, signature);
require(recovered == signer, "[BE] invalid signature");
}
modifier signatureValid(
bytes calldata signature
) {
require(
!_usedSignatures[signature],
"signature used. please send another transaction with new signature"
);
_;
}
/**
* @dev mark signature used
*/
function useSignature(
bytes calldata signature
) public approvaled {
if (!_usedSignatures[signature]) {
_usedSignatures[signature] = true;
}
}
} }

View File

@ -4,20 +4,23 @@ pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
interface IBEERC1155 is IERC1155 { interface IBEERC1155 is IERC1155 {
function mintBatch( function mintBatch(
address to, address to,
uint256[] memory ids, uint256[] memory ids,
uint256[] memory amounts, uint256[] memory amounts,
bytes memory data bytes memory data
) external; ) external;
function burnBatch( function burnBatch(
address owner, address owner,
uint256[] memory ids, uint256[] memory ids,
uint256[] memory values uint256[] memory values
) external; ) external;
function balanceOf(address account, uint256 id) external view returns (uint256); function balanceOf(address account, uint256 id)
external
view
returns (uint256);
function canMint(uint256 id) external view returns (bool); function canMint(uint256 id) external view returns (bool);
} }

View File

@ -3,10 +3,10 @@ pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IBEERC721 is IERC721 { interface IBEERC721 is IERC721 {
function mint(address to, uint256 tokenId) external; function mint(address to, uint256 tokenId) external;
function burn(address owner, uint256 tokenId) external;
function ownerOf(uint256 tokenId) external view returns (address owner); function burn(address owner, uint256 tokenId) external;
function ownerOf(uint256 tokenId) external view returns (address owner);
} }

View File

@ -21,7 +21,5 @@ interface IEvolveFactory {
bytes calldata signature bytes calldata signature
) external; ) external;
function useSignature( function useSignature(bytes calldata signature) external;
bytes calldata signature
) external;
} }

View File

@ -18,14 +18,9 @@ contract EvolveFactory is Ownable, TimeChecker, Initializable, HasSignature {
address public executor; address public executor;
event TokenEvolved( event TokenEvolved(address indexed owner, uint256[] tokenIds);
address indexed owner,
uint256[] tokenIds
);
constructor() constructor() HasSignature("EvolveFactory", "1") {}
HasSignature("EvolveFactory", "1"){
}
function init(address chipAddress) external initializer onlyOwner { function init(address chipAddress) external initializer onlyOwner {
chip = IBEERC1155(chipAddress); chip = IBEERC1155(chipAddress);
@ -35,7 +30,7 @@ contract EvolveFactory is Ownable, TimeChecker, Initializable, HasSignature {
* @dev update executor * @dev update executor
*/ */
function updateExecutor(address account) external onlyOwner { function updateExecutor(address account) external onlyOwner {
require(account != address(0), 'address can not be zero'); require(account != address(0), "address can not be zero");
executor = account; executor = account;
} }
@ -46,7 +41,7 @@ contract EvolveFactory is Ownable, TimeChecker, Initializable, HasSignature {
uint256 saltNonce, uint256 saltNonce,
bytes calldata signature, bytes calldata signature,
IBEERC721 nft IBEERC721 nft
) external signatureValid(signature) timeValid(startTime){ ) external signatureValid(signature) timeValid(startTime) {
require( require(
tokenIds[0] > 0 && tokenIds[1] > 0, tokenIds[0] > 0 && tokenIds[1] > 0,
"EvolveFactory: token to evolve and burn can not be 0" "EvolveFactory: token to evolve and burn can not be 0"
@ -69,7 +64,7 @@ contract EvolveFactory is Ownable, TimeChecker, Initializable, HasSignature {
} }
uint256[] memory signArray = new uint256[](3); uint256[] memory signArray = new uint256[](3);
for (uint256 i = 0; i < tokenIds.length; ++ i) { for (uint256 i = 0; i < tokenIds.length; ++i) {
uint256 _id = tokenIds[i]; uint256 _id = tokenIds[i];
signArray[i] = _id; signArray[i] = _id;
} }
@ -83,15 +78,14 @@ contract EvolveFactory is Ownable, TimeChecker, Initializable, HasSignature {
nft.burn(to, tokenIds[1]); nft.burn(to, tokenIds[1]);
if (tokenIds[2] > 0) { if (tokenIds[2] > 0) {
uint256 amount = 1; uint256 amount = 1;
chip.burnBatch(to, chip.burnBatch(
tokenIds[2].asSingletonArray(), to,
amount.asSingletonArray()); tokenIds[2].asSingletonArray(),
amount.asSingletonArray()
);
} }
useSignature(signature); useSignature(signature);
emit TokenEvolved( emit TokenEvolved(to, signArray);
to,
signArray
);
} }
function evolveChip( function evolveChip(
@ -100,12 +94,12 @@ contract EvolveFactory is Ownable, TimeChecker, Initializable, HasSignature {
uint256 startTime, uint256 startTime,
uint256 saltNonce, uint256 saltNonce,
bytes calldata signature bytes calldata signature
) external signatureValid(signature) timeValid(startTime){ ) external signatureValid(signature) timeValid(startTime) {
require(to != address(0), "EvolveFacrory: address is zero address"); require(to != address(0), "EvolveFacrory: address is zero address");
uint256 len = tokenIds.length; uint256 len = tokenIds.length;
uint256[] memory amounts = new uint256[](len -1); uint256[] memory amounts = new uint256[](len - 1);
uint256[] memory idsForBurn = new uint256[](len - 1); uint256[] memory idsForBurn = new uint256[](len - 1);
for (uint256 i = 0; i < len; ++ i) { for (uint256 i = 0; i < len; ++i) {
require( require(
chip.balanceOf(to, tokenIds[i]) > 0, chip.balanceOf(to, tokenIds[i]) > 0,
"EvolveFacrory: Chip specified not exists" "EvolveFacrory: Chip specified not exists"
@ -115,14 +109,16 @@ contract EvolveFactory is Ownable, TimeChecker, Initializable, HasSignature {
amounts[i - 1] = 1; amounts[i - 1] = 1;
} }
} }
bytes32 criteriaMessageHash = getMessageHash(to, startTime, saltNonce, tokenIds); bytes32 criteriaMessageHash = getMessageHash(
to,
startTime,
saltNonce,
tokenIds
);
checkSigner(executor, criteriaMessageHash, signature); checkSigner(executor, criteriaMessageHash, signature);
chip.burnBatch(to, idsForBurn, amounts); chip.burnBatch(to, idsForBurn, amounts);
useSignature(signature); useSignature(signature);
emit TokenEvolved( emit TokenEvolved(to, tokenIds);
to,
tokenIds
);
} }
function getMessageHash( function getMessageHash(
@ -138,5 +134,4 @@ contract EvolveFactory is Ownable, TimeChecker, Initializable, HasSignature {
} }
return keccak256(encoded); return keccak256(encoded);
} }
} }

View File

@ -12,285 +12,299 @@ import "../utils/TimeChecker.sol";
import "../core/HasSignature.sol"; import "../core/HasSignature.sol";
import "./FactoryBase.sol"; import "./FactoryBase.sol";
contract MinterFactory is Ownable, FactoryBase, TimeChecker, Initializable, HasSignature { contract MinterFactory is
using UInt for uint256; Ownable,
using SafeERC20 for IERC20; FactoryBase,
address public executor; TimeChecker,
// NFT contract Initializable,
IBEERC721 public hero; HasSignature
IBEERC721 public equip; {
IBEERC1155 public chip; using UInt for uint256;
IBEERC1155 public shard; using SafeERC20 for IERC20;
address public executor;
// NFT contract
IBEERC721 public hero;
IBEERC721 public equip;
IBEERC1155 public chip;
IBEERC1155 public shard;
address public feeToAddress; address public feeToAddress;
event TokenMinted( event TokenMinted(
address contractAddress, address contractAddress,
address to, address to,
uint256 indexed tokenId uint256 indexed tokenId
);
event TokenMintedBatch(
address contractAddress,
address indexed to,
uint256[] ids,
uint256[] amounts
);
constructor() HasSignature("MinterFactory", "1") {}
function init(address[4] calldata _erc721s) external initializer onlyOwner {
hero = IBEERC721(_erc721s[0]);
equip = IBEERC721(_erc721s[1]);
chip = IBEERC1155(_erc721s[2]);
shard = IBEERC1155(_erc721s[3]);
}
/**
* @dev update executor
*/
function updateExecutor(address account) external onlyOwner {
require(account != address(0), "address can not be zero");
executor = account;
}
function setFeeToAddress(address _feeToAddress) external onlyOwner {
require(
_feeToAddress != address(0),
"fee received address can not be zero"
);
feeToAddress = _feeToAddress;
}
/**
* @dev mint function to distribute Hero NFT to user
*/
function mintHeroTo(address to, uint256 tokenId) external onlyOwner {
mint721NFT(to, tokenId, hero);
}
/**
* @dev mint function to distribute Equipment NFT to user
*/
function mintEquipTo(address to, uint256 tokenId) external onlyOwner {
mint721NFT(to, tokenId, equip);
}
/**
* @dev mint function to distribute Chip NFT to user
*/
function mintChipTo(address to, uint256 tokenId) external onlyOwner {
mint1155NFT(to, tokenId, 1, chip);
}
/**
* @dev mint function to distribute Shard NFT to user
*/
function mintShardTo(address to, uint256 tokenId) external onlyOwner {
mint1155NFT(to, tokenId, 1, shard);
}
/**
* @dev batch mint 1155 Chip to user
*/
function mintChipBatch(address to, uint256[] memory ids) external onlyOwner {
require(
to != address(0),
"MinterFactory::mintChipBatch: to address can not be zero"
);
require(
ids.length > 0,
"MinterFactory::mintChipBatch: ids cannot be empty"
);
uint256[] memory amounts = new uint256[](ids.length);
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
amounts[i] = 1;
}
mint1155NFTBatch(to, ids, amounts, chip);
}
/**
* @dev batch mint 1155 Shard to user
*/
function mintShardBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts
) external onlyOwner {
require(to != address(0), "MinterFactory: to address can not be zero");
require(ids.length > 0, "MinterFactory: ids cannot be empty");
require(
ids.length == amounts.length,
"MinterFactory: ids and amounts length mismatch"
);
mint1155NFTBatch(to, ids, amounts, shard);
}
function mint721ByUser(
address to,
uint256 id,
uint256 startTime,
uint256 saltNonce,
bytes calldata signature,
IBEERC721 nft
) external signatureValid(signature) timeValid(startTime) {
uint256[] memory signArray = new uint256[](1);
signArray[0] = id;
bytes32 criteriaMessageHash = getMessageHash(
to,
address(nft),
startTime,
saltNonce,
signArray
);
checkSigner(executor, criteriaMessageHash, signature);
mint721NFT(to, id, nft);
useSignature(signature);
}
function mint1155BatchByUser(
address to,
uint256[] memory ids,
uint256[] memory amounts,
uint256 startTime,
uint256 saltNonce,
bytes calldata signature,
IBEERC1155 nft
) external signatureValid(signature) timeValid(startTime) {
uint256 len = ids.length;
require(len > 0, "MinterFactory: ids cannot be empty");
require(
len == amounts.length,
"MinterFactory: ids and amounts length mismatch"
);
uint256[] memory signArray = new uint256[](len * 2);
for (uint256 i = 0; i < len; ++i) {
require(
nft.canMint(ids[i]),
"MinterFactory: can not mint for current nft rule setting"
);
signArray[i * 2] = ids[i];
signArray[i * 2 + 1] = amounts[i];
}
bytes32 criteriaMessageHash = getMessageHash(
to,
address(nft),
startTime,
saltNonce,
signArray
);
checkSigner(executor, criteriaMessageHash, signature);
mint1155NFTBatch(to, ids, amounts, nft);
useSignature(signature);
}
function shardMixByUser(
ShardParam memory param,
uint256[] memory ids,
uint256[] memory amounts,
bytes calldata signature,
IBEERC721 nft
) external signatureValid(signature) timeValid(param.startTime) {
require(ids.length > 0, "MinterFactory: ids cannot be empty");
require(
ids.length == amounts.length,
"MinterFactory: ids and amounts length mismatch"
); );
uint256[] memory signArray = new uint256[](ids.length * 2);
event TokenMintedBatch( for (uint256 i = 0; i < ids.length; ++i) {
address contractAddress, require(
address indexed to, shard.balanceOf(param.to, ids[i]) > 0,
uint256[] ids, "MinterFactory: not enough shard"
uint256[] amounts );
signArray[i * 2] = ids[i];
signArray[i * 2 + 1] = amounts[i];
}
bytes32 criteriaMessageHash = getShardMixHash(
param,
address(nft),
signArray
); );
checkSigner(executor, criteriaMessageHash, signature);
// Check payment approval and buyer balance
IERC20 paymentContract = IERC20(param.payToken);
require(
paymentContract.balanceOf(param.to) >= param.payAmount,
"MinterFactory: doesn't have enough token to mix shard"
);
require(
paymentContract.allowance(param.to, address(this)) >= param.payAmount,
"MinterFactory: doesn't approve MinterFactory to spend payment amount"
);
// transfer money to address
paymentContract.safeTransferFrom(param.to, feeToAddress, param.payAmount);
shard.burnBatch(param.to, ids, amounts);
mint721NFT(param.to, param.nftId, nft);
useSignature(signature);
}
function mint721NFT(
address to,
uint256 tokenId,
IBEERC721 nft
) internal {
require(to != address(0), "MinterFactory: to address can not be zero");
nft.mint(to, tokenId);
emit TokenMinted(address(nft), to, tokenId);
}
constructor() HasSignature("MinterFactory", "1") {} function mint1155NFT(
address to,
uint256 id,
uint256 amount,
IBEERC1155 nft
) internal {
require(to != address(0), "MinterFactory: to address can not be zero");
nft.mintBatch(to, id.asSingletonArray(), amount.asSingletonArray(), "");
emit TokenMinted(address(chip), to, id);
}
function init(address[4] calldata _erc721s) external initializer onlyOwner { function mint1155NFTBatch(
hero = IBEERC721(_erc721s[0]); address to,
equip = IBEERC721(_erc721s[1]); uint256[] memory ids,
chip = IBEERC1155(_erc721s[2]); uint256[] memory amounts,
shard = IBEERC1155(_erc721s[3]); IBEERC1155 nft
) internal {
nft.mintBatch(to, ids, amounts, "");
emit TokenMintedBatch(address(nft), to, ids, amounts);
}
function getMessageHash(
address _to,
address _nftAddress,
uint256 _startTime,
uint256 _saltNonce,
uint256[] memory _ids
) public pure returns (bytes32) {
bytes memory encoded = abi.encodePacked(
_to,
_nftAddress,
_startTime,
_saltNonce
);
uint256 len = _ids.length;
for (uint256 i = 0; i < len; ++i) {
encoded = bytes.concat(encoded, abi.encodePacked(_ids[i]));
} }
return keccak256(encoded);
}
function getShardMixHash(
/** ShardParam memory param,
* @dev update executor address nftAddress,
*/ uint256[] memory _ids
function updateExecutor(address account) external onlyOwner { ) internal pure returns (bytes32) {
require(account != address(0), "address can not be zero"); bytes memory encoded = abi.encodePacked(
executor = account; param.to,
} nftAddress,
param.nftId,
function setFeeToAddress(address _feeToAddress) external onlyOwner { param.payToken,
require(_feeToAddress != address(0), 'fee received address can not be zero'); param.payAmount,
feeToAddress = _feeToAddress; param.startTime,
} param.saltNonce
);
/** uint256 len = _ids.length;
* @dev mint function to distribute Hero NFT to user for (uint256 i = 0; i < len; ++i) {
*/ encoded = bytes.concat(encoded, abi.encodePacked(_ids[i]));
function mintHeroTo(address to, uint256 tokenId) external onlyOwner {
mint721NFT(to, tokenId, hero);
}
/**
* @dev mint function to distribute Equipment NFT to user
*/
function mintEquipTo(address to, uint256 tokenId) external onlyOwner {
mint721NFT(to, tokenId, equip);
}
/**
* @dev mint function to distribute Chip NFT to user
*/
function mintChipTo(address to, uint256 tokenId) external onlyOwner {
mint1155NFT(to, tokenId, 1, chip);
}
/**
* @dev mint function to distribute Shard NFT to user
*/
function mintShardTo(address to, uint256 tokenId) external onlyOwner {
mint1155NFT(to, tokenId, 1, shard);
}
/**
* @dev batch mint 1155 Chip to user
*/
function mintChipBatch(address to, uint256[] memory ids)
external
onlyOwner
{
require(
to != address(0),
"MinterFactory::mintChipBatch: to address can not be zero"
);
require(
ids.length > 0,
"MinterFactory::mintChipBatch: ids cannot be empty"
);
uint256[] memory amounts = new uint256[](ids.length);
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
amounts[i] = 1;
}
mint1155NFTBatch(to, ids, amounts, chip);
}
/**
* @dev batch mint 1155 Shard to user
*/
function mintShardBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts
) external onlyOwner {
require(to != address(0), "MinterFactory: to address can not be zero");
require(ids.length > 0, "MinterFactory: ids cannot be empty");
require(
ids.length == amounts.length,
"MinterFactory: ids and amounts length mismatch"
);
mint1155NFTBatch(to, ids, amounts, shard);
}
function mint721ByUser(
address to,
uint256 id,
uint256 startTime,
uint256 saltNonce,
bytes calldata signature,
IBEERC721 nft
) external signatureValid(signature) timeValid(startTime){
uint256[] memory signArray = new uint256[](1);
signArray[0] = id;
bytes32 criteriaMessageHash =
getMessageHash(to, address(nft), startTime, saltNonce, signArray);
checkSigner(executor, criteriaMessageHash, signature);
mint721NFT(to, id, nft);
useSignature(signature);
}
function mint1155BatchByUser(
address to,
uint256[] memory ids,
uint256[] memory amounts,
uint256 startTime,
uint256 saltNonce,
bytes calldata signature,
IBEERC1155 nft
) external signatureValid(signature) timeValid(startTime){
uint256 len = ids.length;
require(len > 0, "MinterFactory: ids cannot be empty");
require(
len == amounts.length,
"MinterFactory: ids and amounts length mismatch"
);
uint256[] memory signArray = new uint256[](len * 2);
for (uint256 i = 0; i < len; ++i) {
require(
nft.canMint(ids[i]),
"MinterFactory: can not mint for current nft rule setting"
);
signArray[i * 2] = ids[i];
signArray[i * 2 + 1] = amounts[i];
}
bytes32 criteriaMessageHash =
getMessageHash(to, address(nft), startTime, saltNonce, signArray);
checkSigner(executor, criteriaMessageHash, signature);
mint1155NFTBatch(to, ids, amounts, nft);
useSignature(signature);
}
function shardMixByUser(
ShardParam memory param,
uint256[] memory ids,
uint256[] memory amounts,
bytes calldata signature,
IBEERC721 nft
) external signatureValid(signature) timeValid(param.startTime) {
require(ids.length > 0, "MinterFactory: ids cannot be empty");
require(
ids.length == amounts.length,
"MinterFactory: ids and amounts length mismatch"
);
uint256[] memory signArray = new uint256[](ids.length * 2);
for (uint256 i = 0; i < ids.length; ++i) {
require(
shard.balanceOf(param.to, ids[i]) > 0,
"MinterFactory: not enough shard"
);
signArray[i * 2] = ids[i];
signArray[i * 2 + 1] = amounts[i];
}
bytes32 criteriaMessageHash =
getShardMixHash(param, address(nft), signArray);
checkSigner(executor, criteriaMessageHash, signature);
// Check payment approval and buyer balance
IERC20 paymentContract = IERC20(param.payToken);
require(
paymentContract.balanceOf(param.to) >= param.payAmount,
"MinterFactory: doesn't have enough token to mix shard"
);
require(
paymentContract.allowance(param.to, address(this)) >= param.payAmount,
"MinterFactory: doesn't approve MinterFactory to spend payment amount"
);
// transfer money to address
paymentContract.safeTransferFrom(
param.to,
feeToAddress,
param.payAmount
);
shard.burnBatch(param.to, ids, amounts);
mint721NFT(param.to, param.nftId, nft);
useSignature(signature);
}
function mint721NFT(
address to,
uint256 tokenId,
IBEERC721 nft
) internal {
require(to != address(0), "MinterFactory: to address can not be zero");
nft.mint(to, tokenId);
emit TokenMinted(address(nft), to, tokenId);
}
function mint1155NFT(
address to,
uint256 id,
uint256 amount,
IBEERC1155 nft
) internal {
require(to != address(0), "MinterFactory: to address can not be zero");
nft.mintBatch(to, id.asSingletonArray(), amount.asSingletonArray(), "");
emit TokenMinted(address(chip), to, id);
}
function mint1155NFTBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
IBEERC1155 nft
) internal {
nft.mintBatch(to, ids, amounts, "");
emit TokenMintedBatch(address(nft), to, ids, amounts);
}
function getMessageHash(
address _to,
address _nftAddress,
uint256 _startTime,
uint256 _saltNonce,
uint256[] memory _ids
) public pure returns (bytes32) {
bytes memory encoded =
abi.encodePacked(_to, _nftAddress, _startTime, _saltNonce);
uint256 len = _ids.length;
for (uint256 i = 0; i < len; ++i) {
encoded = bytes.concat(encoded, abi.encodePacked(_ids[i]));
}
return keccak256(encoded);
}
function getShardMixHash(
ShardParam memory param,
address nftAddress,
uint256[] memory _ids
) internal pure returns (bytes32) {
bytes memory encoded =
abi.encodePacked(
param.to,
nftAddress,
param.nftId,
param.payToken,
param.payAmount,
param.startTime,
param.saltNonce
);
uint256 len = _ids.length;
for (uint256 i = 0; i < len; ++i) {
encoded = bytes.concat(encoded, abi.encodePacked(_ids[i]));
}
return keccak256(encoded);
} }
return keccak256(encoded);
}
} }

View File

@ -8,165 +8,153 @@ import "../interfaces/IBEERC721.sol";
import "../core/HasSignature.sol"; import "../core/HasSignature.sol";
contract MysteryBoxProxy is Ownable, Initializable, HasSignature { contract MysteryBoxProxy is Ownable, Initializable, HasSignature {
IBEERC721 public box; IBEERC721 public box;
IBEERC721 public hero; IBEERC721 public hero;
IBEERC721 public equip; IBEERC721 public equip;
IBEERC721 public chip; IBEERC721 public chip;
uint8 public constant TYPE_NONE = 0; uint8 public constant TYPE_NONE = 0;
uint8 public constant TYPE_HERO = 1; uint8 public constant TYPE_HERO = 1;
uint8 public constant TYPE_EQUIP = 2; uint8 public constant TYPE_EQUIP = 2;
uint8 public constant TYPE_CHIP = 3; uint8 public constant TYPE_CHIP = 3;
address public executor; address public executor;
mapping(bytes => bool) public usedSignatures; mapping(bytes => bool) public usedSignatures;
event TokenMinted( event TokenMinted(
address contractAddress, address contractAddress,
address to, address to,
uint256 indexed tokenId uint256 indexed tokenId
);
event BoxOpened(
address indexed to,
uint256 indexed boxId,
uint256 val,
uint256[3] ids,
uint8[3] types
);
constructor() HasSignature("MysteryBoxProxy", "1") {}
function init(address[4] calldata _erc721s) external initializer onlyOwner {
hero = IBEERC721(_erc721s[0]);
equip = IBEERC721(_erc721s[1]);
chip = IBEERC721(_erc721s[2]);
box = IBEERC721(_erc721s[3]);
}
/**
* @dev update executor
*/
function updateExecutor(address account) external onlyOwner {
require(account != address(0), "address can not be zero");
executor = account;
}
function mintBoxTo(address to, uint256 tokenId) external onlyOwner {
require(to != address(0), "to address can not be zero");
box.mint(to, tokenId);
emit TokenMinted(address(box), to, tokenId);
}
function openBox(
uint256 boxId,
uint256[3] calldata ids,
uint256 saltNonce,
bytes calldata signature
) external {
require(ids.length == 3, "MysteryBoxProxy: amount of token id mismatch");
require(
!usedSignatures[signature],
"MysteryBoxProxy: signature used. please send another transaction with new signature"
); );
address owner = msg.sender;
event BoxOpened( require(
address indexed to, box.ownerOf(boxId) == owner,
uint256 indexed boxId, "MysteryBoxProxy: only owner can open this box"
uint256 val,
uint256[3] ids,
uint8[3] types
); );
bytes32 criteriaMessageHash = getMessageHash(
boxId,
ids[0],
ids[1],
ids[2],
saltNonce
);
checkSigner(executor, criteriaMessageHash, signature);
// open box
box.burn(owner, boxId);
usedSignatures[signature] = true;
constructor() HasSignature("MysteryBoxProxy", "1") {} uint256[3] memory results = [ids[0], 0, 0];
uint8[3] memory types = [TYPE_HERO, TYPE_NONE, TYPE_NONE];
mint721WithType(owner, ids[0], types[0]);
results[0] = ids[0];
function init(address[4] calldata _erc721s) uint256 val = rand(owner, saltNonce, 100);
external if (val >= 70 && val < 90) {
initializer types[1] = TYPE_CHIP;
onlyOwner mint721WithType(owner, ids[1], types[1]);
{ results[1] = ids[1];
hero = IBEERC721(_erc721s[0]); } else if (val >= 90 && val < 98) {
equip = IBEERC721(_erc721s[1]); types[1] = TYPE_EQUIP;
chip = IBEERC721(_erc721s[2]); mint721WithType(owner, ids[1], types[1]);
box = IBEERC721(_erc721s[3]); results[1] = ids[1];
} else if (val >= 98) {
types[1] = TYPE_EQUIP;
mint721WithType(owner, ids[1], types[1]);
results[1] = ids[1];
types[2] = TYPE_CHIP;
mint721WithType(owner, ids[2], types[2]);
results[2] = ids[2];
} }
emit BoxOpened(owner, boxId, val, results, types);
}
/** function mint721WithType(
* @dev update executor address to,
*/ uint256 tokenId,
function updateExecutor(address account) external onlyOwner { uint256 typeNum
require(account != address(0), "address can not be zero"); ) private {
executor = account; if (typeNum == 1) {
hero.mint(to, tokenId);
} else if (typeNum == 2) {
equip.mint(to, tokenId);
} else if (typeNum == 3) {
chip.mint(to, tokenId);
} }
}
function mintBoxTo(address to, uint256 tokenId) external onlyOwner{ function rand(
require(to != address(0), 'to address can not be zero'); address owner,
box.mint(to, tokenId); uint256 nonce,
emit TokenMinted(address(box), to, tokenId); uint256 _length
} ) internal view returns (uint256) {
uint256 random = uint256(
keccak256(
abi.encodePacked(owner, nonce, block.difficulty, block.timestamp)
)
);
return random % _length;
}
function openBox( function getMessageHash(
uint256 boxId, uint256 _boxId,
uint256[3] calldata ids, uint256 _firstToken,
uint256 saltNonce, uint256 _secondToken,
bytes calldata signature uint256 _thirdToken,
) external { uint256 _saltNonce
require( ) public pure returns (bytes32) {
ids.length == 3, return
"MysteryBoxProxy: amount of token id mismatch" keccak256(
); abi.encodePacked(
require( _boxId,
!usedSignatures[signature], _firstToken,
"MysteryBoxProxy: signature used. please send another transaction with new signature" _secondToken,
); _thirdToken,
address owner = msg.sender; _saltNonce
require( )
box.ownerOf(boxId) == owner, );
"MysteryBoxProxy: only owner can open this box" }
);
bytes32 criteriaMessageHash = getMessageHash(
boxId,
ids[0],
ids[1],
ids[2],
saltNonce
);
checkSigner(executor, criteriaMessageHash, signature);
// open box
box.burn(owner, boxId);
usedSignatures[signature] = true;
uint256[3] memory results = [ids[0], 0, 0];
uint8[3] memory types = [TYPE_HERO, TYPE_NONE, TYPE_NONE];
mint721WithType(owner, ids[0], types[0]);
results[0] = ids[0];
uint256 val = rand(owner, saltNonce, 100);
if (val >= 70 && val < 90) {
types[1] = TYPE_CHIP;
mint721WithType(owner, ids[1], types[1]);
results[1] = ids[1];
} else if (val >= 90 && val < 98) {
types[1] = TYPE_EQUIP;
mint721WithType(owner, ids[1], types[1]);
results[1] = ids[1];
} else if (val >= 98) {
types[1] = TYPE_EQUIP;
mint721WithType(owner, ids[1], types[1]);
results[1] = ids[1];
types[2] = TYPE_CHIP;
mint721WithType(owner, ids[2], types[2]);
results[2] = ids[2];
}
emit BoxOpened(owner, boxId, val, results, types);
}
function mint721WithType(
address to,
uint256 tokenId,
uint256 typeNum
) private {
if (typeNum == 1) {
hero.mint(to, tokenId);
} else if (typeNum == 2) {
equip.mint(to, tokenId);
} else if (typeNum == 3) {
chip.mint(to, tokenId);
}
}
function rand(
address owner,
uint256 nonce,
uint256 _length
) internal view returns (uint256) {
uint256 random = uint256(
keccak256(
abi.encodePacked(
owner,
nonce,
block.difficulty,
block.timestamp
)
)
);
return random % _length;
}
function getMessageHash(
uint256 _boxId,
uint256 _firstToken,
uint256 _secondToken,
uint256 _thirdToken,
uint256 _saltNonce
) public pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
_boxId,
_firstToken,
_secondToken,
_thirdToken,
_saltNonce
)
);
}
} }

View File

@ -10,7 +10,7 @@ contract UserEvolveFactory is Ownable, Initializable {
IBEERC721 public hero; IBEERC721 public hero;
IBEERC721 public equip; IBEERC721 public equip;
event TokenEvolveFail ( event TokenEvolveFail(
address indexed to, address indexed to,
bytes signature, bytes signature,
string reason, string reason,
@ -23,73 +23,58 @@ contract UserEvolveFactory is Ownable, Initializable {
factory = IEvolveFactory(_nfts[2]); factory = IEvolveFactory(_nfts[2]);
} }
/** /**
* @dev evolve function Hero NFT * @dev evolve function Hero NFT
* tokenIds: [hero_to_evolve, hero_for_burn, chip] * tokenIds: [hero_to_evolve, hero_for_burn, chip]
*/ */
function evolveHero( function evolveHero(
uint256[3] calldata tokenIds, uint256[3] calldata tokenIds,
uint256 startTime, uint256 startTime,
uint256 saltNonce, uint256 saltNonce,
bytes calldata signature bytes calldata signature
) external returns (bool success){ ) external returns (bool success) {
address to = _msgSender(); address to = _msgSender();
try factory.evolve721NFT(to, tokenIds, startTime, saltNonce, signature, hero) { try
factory.evolve721NFT(to, tokenIds, startTime, saltNonce, signature, hero)
{
return true; return true;
} catch Error(string memory reason) { } catch Error(string memory reason) {
bytes memory by; bytes memory by;
factory.useSignature(signature); factory.useSignature(signature);
emit TokenEvolveFail( emit TokenEvolveFail(to, signature, reason, by);
to,
signature,
reason,
by
);
return false; return false;
} catch (bytes memory lowLevelData) { } catch (bytes memory lowLevelData) {
factory.useSignature(signature); factory.useSignature(signature);
string memory reason; string memory reason;
emit TokenEvolveFail( emit TokenEvolveFail(to, signature, reason, lowLevelData);
to,
signature,
reason,
lowLevelData
);
return false; return false;
} }
} }
/** /**
* @dev evolve function for equip NFT * @dev evolve function for equip NFT
* tokenIds: [equip_to_evolve, equip_for_burn, chip] * tokenIds: [equip_to_evolve, equip_for_burn, chip]
*/ */
function evolveEquip( function evolveEquip(
uint256[3] calldata tokenIds, uint256[3] calldata tokenIds,
uint256 startTime, uint256 startTime,
uint256 saltNonce, uint256 saltNonce,
bytes calldata signature bytes calldata signature
) external returns (bool success){ ) external returns (bool success) {
address to = _msgSender(); address to = _msgSender();
try factory.evolve721NFT(to, tokenIds, startTime, saltNonce, signature, equip) { try
factory.evolve721NFT(to, tokenIds, startTime, saltNonce, signature, equip)
{
return true; return true;
} catch Error(string memory reason) { } catch Error(string memory reason) {
bytes memory by; bytes memory by;
factory.useSignature(signature); factory.useSignature(signature);
emit TokenEvolveFail( emit TokenEvolveFail(to, signature, reason, by);
to,
signature,
reason,
by
);
return false; return false;
} catch (bytes memory lowLevelData) { } catch (bytes memory lowLevelData) {
factory.useSignature(signature); factory.useSignature(signature);
string memory reason; string memory reason;
emit TokenEvolveFail( emit TokenEvolveFail(to, signature, reason, lowLevelData);
to,
signature,
reason,
lowLevelData
);
return false; return false;
} }
} }
@ -98,39 +83,23 @@ contract UserEvolveFactory is Ownable, Initializable {
* @dev evolve function for chip * @dev evolve function for chip
*/ */
function evolveChip( function evolveChip(
uint256[] memory ids, uint256[] memory ids,
uint256 startTime, uint256 startTime,
uint256 saltNonce, uint256 saltNonce,
bytes calldata signature bytes calldata signature
) external returns (bool success){ ) external returns (bool success) {
address to = _msgSender(); address to = _msgSender();
try factory.evolveChip( try factory.evolveChip(to, ids, startTime, saltNonce, signature) {
to,
ids,
startTime,
saltNonce,
signature
) {
return true; return true;
} catch Error(string memory reason) { } catch Error(string memory reason) {
bytes memory by; bytes memory by;
factory.useSignature(signature); factory.useSignature(signature);
emit TokenEvolveFail( emit TokenEvolveFail(to, signature, reason, by);
to,
signature,
reason,
by
);
return false; return false;
} catch (bytes memory lowLevelData) { } catch (bytes memory lowLevelData) {
factory.useSignature(signature); factory.useSignature(signature);
string memory reason; string memory reason;
emit TokenEvolveFail( emit TokenEvolveFail(to, signature, reason, lowLevelData);
to,
signature,
reason,
lowLevelData
);
return false; return false;
} }
} }

View File

@ -28,6 +28,7 @@ contract UserMinterFactory is Ownable, FactoryBase, Initializable {
shard = IBEERC1155(addressArr[3]); shard = IBEERC1155(addressArr[3]);
factory = MinterFactory(addressArr[4]); factory = MinterFactory(addressArr[4]);
} }
/** /**
* @dev mint hero by user * @dev mint hero by user
*/ */
@ -36,32 +37,23 @@ contract UserMinterFactory is Ownable, FactoryBase, Initializable {
uint256 startTime, uint256 startTime,
uint256 saltNonce, uint256 saltNonce,
bytes calldata signature bytes calldata signature
) external returns (bool success){ ) external returns (bool success) {
address to = _msgSender(); address to = _msgSender();
try factory.mint721ByUser(to, tokenId, startTime, saltNonce, signature, hero) { try
factory.mint721ByUser(to, tokenId, startTime, saltNonce, signature, hero)
{
return true; return true;
} catch Error(string memory reason) { } catch Error(string memory reason) {
bytes memory by; bytes memory by;
factory.useSignature(signature); factory.useSignature(signature);
emit TokenMintFail( emit TokenMintFail(to, signature, reason, by);
to,
signature,
reason,
by
);
return false; return false;
} catch (bytes memory lowLevelData) { } catch (bytes memory lowLevelData) {
factory.useSignature(signature); factory.useSignature(signature);
string memory reason; string memory reason;
emit TokenMintFail( emit TokenMintFail(to, signature, reason, lowLevelData);
to,
signature,
reason,
lowLevelData
);
return false; return false;
} }
} }
/** /**
@ -72,112 +64,104 @@ contract UserMinterFactory is Ownable, FactoryBase, Initializable {
uint256 startTime, uint256 startTime,
uint256 saltNonce, uint256 saltNonce,
bytes calldata signature bytes calldata signature
) external returns (bool success){ ) external returns (bool success) {
address to = _msgSender(); address to = _msgSender();
try factory.mint721ByUser(to, tokenId, startTime, saltNonce, signature, equip) { try
factory.mint721ByUser(to, tokenId, startTime, saltNonce, signature, equip)
{
return true; return true;
} catch Error(string memory reason) { } catch Error(string memory reason) {
bytes memory by; bytes memory by;
factory.useSignature(signature); factory.useSignature(signature);
emit TokenMintFail( emit TokenMintFail(to, signature, reason, by);
to,
signature,
reason,
by
);
return false; return false;
} catch (bytes memory lowLevelData) { } catch (bytes memory lowLevelData) {
factory.useSignature(signature); factory.useSignature(signature);
string memory reason; string memory reason;
emit TokenMintFail( emit TokenMintFail(to, signature, reason, lowLevelData);
to,
signature,
reason,
lowLevelData
);
return false; return false;
} }
} }
/** /**
* @dev user batch mint 1155 chip * @dev user batch mint 1155 chip
*/ */
function mintChipBatchUser( function mintChipBatchUser(
uint256[] memory ids, uint256[] memory ids,
uint256 startTime, uint256 startTime,
uint256 saltNonce, uint256 saltNonce,
bytes calldata signature bytes calldata signature
) external returns (bool success){ ) external returns (bool success) {
uint256 len = ids.length; uint256 len = ids.length;
uint256[] memory amounts = new uint256[](len); uint256[] memory amounts = new uint256[](len);
for (uint256 i = 0; i < len; ++i) { for (uint256 i = 0; i < len; ++i) {
amounts[i] = 1; amounts[i] = 1;
} }
address to = _msgSender(); address to = _msgSender();
try factory.mint1155BatchByUser(to, ids, amounts, startTime, saltNonce, signature, chip) { try
factory.mint1155BatchByUser(
to,
ids,
amounts,
startTime,
saltNonce,
signature,
chip
)
{
return true; return true;
} catch Error(string memory reason) { } catch Error(string memory reason) {
bytes memory by; bytes memory by;
factory.useSignature(signature); factory.useSignature(signature);
emit TokenMintFail( emit TokenMintFail(to, signature, reason, by);
to,
signature,
reason,
by
);
return false; return false;
} catch (bytes memory lowLevelData) { } catch (bytes memory lowLevelData) {
factory.useSignature(signature); factory.useSignature(signature);
string memory reason; string memory reason;
emit TokenMintFail( emit TokenMintFail(to, signature, reason, lowLevelData);
to,
signature,
reason,
lowLevelData
);
return false; return false;
} }
} }
/** /**
* @dev user batch mint 1155 shard * @dev user batch mint 1155 shard
*/ */
function mintShardBatchUser( function mintShardBatchUser(
uint256[] memory ids, uint256[] memory ids,
uint256[] memory amounts, uint256[] memory amounts,
uint256 startTime, uint256 startTime,
uint256 saltNonce, uint256 saltNonce,
bytes calldata signature bytes calldata signature
) external returns (bool success){ ) external returns (bool success) {
address to = _msgSender(); address to = _msgSender();
try factory.mint1155BatchByUser(to, ids, amounts, startTime, saltNonce, signature, shard) { try
factory.mint1155BatchByUser(
to,
ids,
amounts,
startTime,
saltNonce,
signature,
shard
)
{
return true; return true;
} catch Error(string memory reason) { } catch Error(string memory reason) {
bytes memory by; bytes memory by;
factory.useSignature(signature); factory.useSignature(signature);
emit TokenMintFail( emit TokenMintFail(to, signature, reason, by);
to,
signature,
reason,
by
);
return false; return false;
} catch (bytes memory lowLevelData) { } catch (bytes memory lowLevelData) {
factory.useSignature(signature); factory.useSignature(signature);
string memory reason; string memory reason;
emit TokenMintFail( emit TokenMintFail(to, signature, reason, lowLevelData);
to,
signature,
reason,
lowLevelData
);
return false; return false;
} }
} }
/** /**
* @dev mint hero or equip with shard * @dev mint hero or equip with shard
*/ */
function shardMixByUser( function shardMixByUser(
uint256 nftId, uint256 nftId,
uint8 nftType, uint8 nftType,
@ -197,36 +181,24 @@ contract UserMinterFactory is Ownable, FactoryBase, Initializable {
nft = equip; nft = equip;
} }
ShardParam memory param = ShardParam( ShardParam memory param = ShardParam(
to, nftId, payToken, payAmount, startTime, saltNonce); to,
try factory.shardMixByUser( nftId,
param, payToken,
ids, payAmount,
amounts, startTime,
signature, saltNonce
nft );
) { try factory.shardMixByUser(param, ids, amounts, signature, nft) {
return true; return true;
} catch Error(string memory reason) { } catch Error(string memory reason) {
bytes memory by; bytes memory by;
factory.useSignature(signature); factory.useSignature(signature);
emit TokenMintFail( emit TokenMintFail(to, signature, reason, by);
to,
signature,
reason,
by
);
return false; return false;
} catch (bytes memory lowLevelData) { } catch (bytes memory lowLevelData) {
factory.useSignature(signature); factory.useSignature(signature);
string memory reason; string memory reason;
emit TokenMintFail( emit TokenMintFail(to, signature, reason, lowLevelData);
to,
signature,
reason,
lowLevelData
);
} }
} }
} }

View File

@ -8,137 +8,150 @@ import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/governance/TimelockController.sol"; import "@openzeppelin/contracts/governance/TimelockController.sol";
import "../core/HasSignature.sol"; import "../core/HasSignature.sol";
contract BEBoxMall is Ownable, HasSignature, TimelockController{ contract BEBoxMall is Ownable, HasSignature, TimelockController {
using SafeERC20 for IERC20; using SafeERC20 for IERC20;
using Address for address; using Address for address;
uint256 public constant MIN_DELAY = 2 days; uint256 public constant MIN_DELAY = 2 days;
uint256 public constant MAX_DELAY = 16 days; uint256 public constant MAX_DELAY = 16 days;
uint256 private _minDelay; uint256 private _minDelay;
bool public address_initialized; bool public address_initialized;
constructor( constructor(address[] memory proposers, address[] memory executors)
address[] memory proposers, TimelockController(MIN_DELAY, proposers, executors)
address[] memory executors) HasSignature("BEBoxMall", "1")
TimelockController(MIN_DELAY, proposers, executors) {
HasSignature("BEBoxMall", "1"){ _minDelay = MIN_DELAY;
_minDelay = MIN_DELAY; address_initialized = false;
address_initialized = false; }
event BEBoxPaid(
uint256 indexed boxId,
address indexed buyer,
uint256 boxType,
uint256 price,
address paymentToken
);
address public paymentReceivedAddress;
function setPaymentReceivedAddress(address _paymentReceivedAddress) public {
require(
_paymentReceivedAddress != address(0),
"BEBoxMall::setPaymentReceivedAddress: payment received address can not be zero"
);
if (address_initialized) {
require(
msg.sender == address(this),
"BEBoxMall::setPaymentReceivedAddress: Call must come from BEBoxMall."
);
} else {
require(
msg.sender == owner(),
"BEBoxMall::setPaymentReceivedAddress: First call must come from owner."
);
address_initialized = true;
} }
paymentReceivedAddress = _paymentReceivedAddress;
}
event BEBoxPaid( /**
uint256 indexed boxId, * @dev BE box payment function
address indexed buyer, */
uint256 boxType, function payForBoxWithSignature(
uint256 price, uint256 boxId,
address paymentToken uint256 _type,
address userAddress,
uint256 price,
address paymentErc20,
uint256 saltNonce,
bytes calldata signature
) external onlyOwner signatureValid(signature) {
require(
!userAddress.isContract(),
"BEBoxPayment: Only user address is allowed to buy box"
);
require(_type > 0, "BEBoxPayment: Invalid box type");
require(price > 0, "BEBoxPayment: Invalid payment amount");
bytes32 criteriaMessageHash = getMessageHash(
_type,
paymentErc20,
price,
saltNonce
); );
address public paymentReceivedAddress; checkSigner712(userAddress, criteriaMessageHash, signature);
function setPaymentReceivedAddress(address _paymentReceivedAddress) IERC20 paymentToken = IERC20(paymentErc20);
public uint256 allowToPayAmount = paymentToken.allowance(
{ userAddress,
require(_paymentReceivedAddress != address(0), 'BEBoxMall::setPaymentReceivedAddress: payment received address can not be zero'); address(this)
if (address_initialized) { );
require(msg.sender == address(this), "BEBoxMall::setPaymentReceivedAddress: Call must come from BEBoxMall."); require(allowToPayAmount >= price, "BEBoxPayment: Invalid token allowance");
} else { // Transfer payment
require(msg.sender == owner(), "BEBoxMall::setPaymentReceivedAddress: First call must come from owner."); paymentToken.safeTransferFrom(userAddress, paymentReceivedAddress, price);
address_initialized = true; useSignature(signature);
} // Emit payment event
paymentReceivedAddress = _paymentReceivedAddress; emit BEBoxPaid(boxId, userAddress, _type, price, paymentErc20);
} }
/** function getMessageHash(
* @dev BE box payment function uint256 _boxType,
*/ address _paymentErc20,
function payForBoxWithSignature( uint256 _price,
uint256 boxId, uint256 _saltNonce
uint256 _type, ) public pure returns (bytes32) {
address userAddress, return
uint256 price, keccak256(
address paymentErc20, abi.encode(
uint256 saltNonce, keccak256(
bytes calldata signature "set(uint256 item,address token,uint256 price,uint256 salt)"
) external onlyOwner signatureValid(signature){ ),
require( _boxType,
!userAddress.isContract(), _paymentErc20,
"BEBoxPayment: Only user address is allowed to buy box" _price,
); _saltNonce
require(_type > 0, "BEBoxPayment: Invalid box type"); )
require(price > 0, "BEBoxPayment: Invalid payment amount"); );
bytes32 criteriaMessageHash = getMessageHash( }
_type,
paymentErc20,
price,
saltNonce
);
checkSigner712(userAddress, criteriaMessageHash, signature); /**
* @dev Returns the minimum delay for an operation to become valid.
*
* This value can be changed by executing an operation that calls `updateDelay`.
*/
function getMinDelay()
public
view
virtual
override
returns (uint256 duration)
{
return _minDelay;
}
IERC20 paymentToken = IERC20(paymentErc20); /**
uint256 allowToPayAmount = paymentToken.allowance( * @dev Changes the minimum timelock duration for future operations.
userAddress, *
address(this) * Emits a {MinDelayChange} event.
); *
require( * Requirements:
allowToPayAmount >= price, *
"BEBoxPayment: Invalid token allowance" * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
); * an operation where the timelock is the target and the data is the ABI-encoded call to this function.
// Transfer payment */
paymentToken.safeTransferFrom( function updateDelay(uint256 newDelay) external virtual override {
userAddress, require(msg.sender == address(this), "BEBoxMall: caller must be timelock");
paymentReceivedAddress, require(
price newDelay >= MIN_DELAY,
); "BEBoxMall: newDelay must greater than or equal to MIN_DELAY"
useSignature(signature); );
// Emit payment event require(
emit BEBoxPaid(boxId, userAddress, _type, price, paymentErc20); newDelay <= MAX_DELAY,
} "BEBoxMall: newDelay must less than or equal to MAX_DELAY"
);
function getMessageHash( emit MinDelayChange(_minDelay, newDelay);
uint256 _boxType, _minDelay = newDelay;
address _paymentErc20, }
uint256 _price,
uint256 _saltNonce
) public pure returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("set(uint256 item,address token,uint256 price,uint256 salt)"),
_boxType,
_paymentErc20,
_price,
_saltNonce
)
);
}
/**
* @dev Returns the minimum delay for an operation to become valid.
*
* This value can be changed by executing an operation that calls `updateDelay`.
*/
function getMinDelay() public view virtual override returns (uint256 duration) {
return _minDelay;
}
/**
* @dev Changes the minimum timelock duration for future operations.
*
* Emits a {MinDelayChange} event.
*
* Requirements:
*
* - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
* an operation where the timelock is the target and the data is the ABI-encoded call to this function.
*/
function updateDelay(uint256 newDelay) external virtual override {
require(msg.sender == address(this), "BEBoxMall: caller must be timelock");
require(newDelay >= MIN_DELAY, "BEBoxMall: newDelay must greater than or equal to MIN_DELAY");
require(newDelay <= MAX_DELAY, "BEBoxMall: newDelay must less than or equal to MAX_DELAY");
emit MinDelayChange(_minDelay, newDelay);
_minDelay = newDelay;
}
} }

View File

@ -13,191 +13,191 @@ import "../core/HasSignature.sol";
// this contract will transfer ownership to BETimelockController after deployed // this contract will transfer ownership to BETimelockController after deployed
// all onlyowner method would add timelock // all onlyowner method would add timelock
contract MarketPlace is Ownable, HasSignature { contract MarketPlace is Ownable, HasSignature {
using SafeERC20 for IERC20; using SafeERC20 for IERC20;
using SafeMath for uint256; using SafeMath for uint256;
// Supported payment token WETH & list of authorized ERC20 // Supported payment token WETH & list of authorized ERC20
mapping(address => bool) public paymentTokens; mapping(address => bool) public paymentTokens;
mapping(bytes => bool) public usedSignatures; mapping(bytes => bool) public usedSignatures;
// Address to receive transaction fee // Address to receive transaction fee
address public feeToAddress; address public feeToAddress;
uint256 public transactionFee; uint256 public transactionFee;
uint256 public constant MIN_TRANSACTION_FEE = 50; uint256 public constant MIN_TRANSACTION_FEE = 50;
uint256 public constant MAX_TRANSACTION_FEE = 1000; uint256 public constant MAX_TRANSACTION_FEE = 1000;
// Events // Events
event MatchTransaction( event MatchTransaction(
uint256 indexed tokenId, uint256 indexed tokenId,
address contractAddress, address contractAddress,
uint256 price, uint256 price,
address paymentToken, address paymentToken,
address seller, address seller,
address buyer, address buyer,
uint256 fee uint256 fee
);
constructor() HasSignature("MarketPlace", "1") {}
function setFeeToAddress(address _feeToAddress) external onlyOwner {
require(
_feeToAddress != address(0),
"fee received address can not be zero"
);
feeToAddress = _feeToAddress;
}
function setTransactionFee(uint256 _transactionFee) external onlyOwner {
require(
_transactionFee >= MIN_TRANSACTION_FEE &&
_transactionFee <= MAX_TRANSACTION_FEE,
"Marketplace: _transactionFee must >= 50 and <= 1000"
);
transactionFee = _transactionFee;
}
function setPaymentTokens(address[] calldata _paymentTokens)
external
onlyOwner
{
for (uint256 i = 0; i < _paymentTokens.length; i++) {
if (paymentTokens[_paymentTokens[i]]) {
continue;
}
paymentTokens[_paymentTokens[i]] = true;
}
}
function removePaymentTokens(address[] calldata _removedPaymentTokens)
external
onlyOwner
{
for (uint256 i = 0; i < _removedPaymentTokens.length; i++) {
paymentTokens[_removedPaymentTokens[i]] = false;
}
}
function ignoreSignature(
address[2] calldata addresses,
uint256[3] calldata values,
bytes calldata signature
) external signatureValid(signature) {
bytes32 criteriaMessageHash = getMessageHash(
addresses[0],
values[0],
addresses[1],
values[1],
values[2]
); );
constructor() checkSigner(_msgSender(), criteriaMessageHash, signature);
HasSignature("MarketPlace", "1"){ useSignature(signature);
}
/**
* @dev Function matched transaction with user signatures
*/
function matchTransaction(
address[3] calldata addresses,
uint256[3] calldata values,
bytes calldata signature
) external signatureValid(signature) returns (bool) {
// address[3] [seller_address,nft_address,payment_token_address]
// uint256[3] [token_id,price,salt_nonce]
// bytes seller_signature
require(paymentTokens[addresses[2]], "Marketplace: invalid payment method");
bytes32 criteriaMessageHash = getMessageHash(
addresses[1],
values[0],
addresses[2],
values[1],
values[2]
);
checkSigner712(addresses[0], criteriaMessageHash, signature);
// check current ownership
IERC721 nft = IERC721(addresses[1]);
require(
nft.ownerOf(values[0]) == addresses[0],
"Marketplace: seller is not owner of this item now"
);
// Check payment approval and buyer balance
IERC20 paymentContract = IERC20(addresses[2]);
require(
paymentContract.balanceOf(_msgSender()) >= values[1],
"Marketplace: buyer doesn't have enough token to buy this item"
);
require(
paymentContract.allowance(_msgSender(), address(this)) >= values[1],
"Marketplace: buyer doesn't approve marketplace to spend payment amount"
);
// We divide by 10000 to support decimal value such as 4.25% => 425 / 10000
uint256 fee = transactionFee.mul(values[1]).div(10000);
uint256 payToSellerAmount = values[1].sub(fee);
// transfer money to seller
paymentContract.safeTransferFrom(
_msgSender(),
addresses[0],
payToSellerAmount
);
// transfer fee to address
if (fee > 0) {
paymentContract.safeTransferFrom(_msgSender(), feeToAddress, fee);
} }
function setFeeToAddress(address _feeToAddress) external onlyOwner { // transfer item to buyer
require(_feeToAddress != address(0), 'fee received address can not be zero'); nft.safeTransferFrom(addresses[0], _msgSender(), values[0]);
feeToAddress = _feeToAddress;
}
function setTransactionFee(uint256 _transactionFee) external onlyOwner { useSignature(signature);
require( // emit sale event
_transactionFee >= MIN_TRANSACTION_FEE && _transactionFee <= MAX_TRANSACTION_FEE, emitEvent(addresses, values);
"Marketplace: _transactionFee must >= 50 and <= 1000" return true;
); }
transactionFee = _transactionFee;
}
function setPaymentTokens(address[] calldata _paymentTokens) /**
external * @dev Function to emit transaction matched event
onlyOwner */
{ function emitEvent(address[3] calldata addresses, uint256[3] calldata values)
for (uint256 i = 0; i < _paymentTokens.length; i++) { internal
if (paymentTokens[_paymentTokens[i]]) { {
continue; emit MatchTransaction(
} values[0],
addresses[1],
values[1],
addresses[2],
addresses[0],
_msgSender(),
transactionFee
);
}
paymentTokens[_paymentTokens[i]] = true; function getMessageHash(
} address _nftAddress,
} uint256 _tokenId,
address _paymentErc20,
function removePaymentTokens(address[] calldata _removedPaymentTokens) uint256 _price,
external uint256 _saltNonce
onlyOwner ) public pure returns (bytes32) {
{ return
for (uint256 i = 0; i < _removedPaymentTokens.length; i++) { keccak256(
paymentTokens[_removedPaymentTokens[i]] = false; abi.encode(
} keccak256(
} "set(address nft,uint256 tokenId,address payToken,uint256 price,uint256 salt)"
),
function ignoreSignature( _nftAddress,
address[2] calldata addresses, _tokenId,
uint256[3] calldata values, _paymentErc20,
bytes calldata signature _price,
) external signatureValid(signature){ _saltNonce
bytes32 criteriaMessageHash = getMessageHash( )
addresses[0], );
values[0], }
addresses[1],
values[1],
values[2]
);
checkSigner(_msgSender(), criteriaMessageHash, signature);
useSignature(signature);
}
/**
* @dev Function matched transaction with user signatures
*/
function matchTransaction(
address[3] calldata addresses,
uint256[3] calldata values,
bytes calldata signature
) external signatureValid(signature) returns (bool) {
// address[3] [seller_address,nft_address,payment_token_address]
// uint256[3] [token_id,price,salt_nonce]
// bytes seller_signature
require(
paymentTokens[addresses[2]],
"Marketplace: invalid payment method"
);
bytes32 criteriaMessageHash = getMessageHash(
addresses[1],
values[0],
addresses[2],
values[1],
values[2]
);
checkSigner712(addresses[0], criteriaMessageHash, signature);
// check current ownership
IERC721 nft = IERC721(addresses[1]);
require(
nft.ownerOf(values[0]) == addresses[0],
"Marketplace: seller is not owner of this item now"
);
// Check payment approval and buyer balance
IERC20 paymentContract = IERC20(addresses[2]);
require(
paymentContract.balanceOf(_msgSender()) >= values[1],
"Marketplace: buyer doesn't have enough token to buy this item"
);
require(
paymentContract.allowance(_msgSender(), address(this)) >= values[1],
"Marketplace: buyer doesn't approve marketplace to spend payment amount"
);
// We divide by 10000 to support decimal value such as 4.25% => 425 / 10000
uint256 fee = transactionFee.mul(values[1]).div(10000);
uint256 payToSellerAmount = values[1].sub(fee);
// transfer money to seller
paymentContract.safeTransferFrom(
_msgSender(),
addresses[0],
payToSellerAmount
);
// transfer fee to address
if (fee > 0) {
paymentContract.safeTransferFrom(_msgSender(), feeToAddress, fee);
}
// transfer item to buyer
nft.safeTransferFrom(addresses[0], _msgSender(), values[0]);
useSignature(signature);
// emit sale event
emitEvent(addresses, values);
return true;
}
/**
* @dev Function to emit transaction matched event
*/
function emitEvent(
address[3] calldata addresses,
uint256[3] calldata values
) internal {
emit MatchTransaction(
values[0],
addresses[1],
values[1],
addresses[2],
addresses[0],
_msgSender(),
transactionFee
);
}
function getMessageHash(
address _nftAddress,
uint256 _tokenId,
address _paymentErc20,
uint256 _price,
uint256 _saltNonce
) public pure returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("set(address nft,uint256 tokenId,address payToken,uint256 price,uint256 salt)"),
_nftAddress,
_tokenId,
_paymentErc20,
_price,
_saltNonce
)
);
}
} }

View File

@ -7,301 +7,285 @@ import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/access/AccessControl.sol";
abstract contract BEBase1155 is ERC1155, Ownable, AccessControl { abstract contract BEBase1155 is ERC1155, Ownable, AccessControl {
using Strings for uint256; using Strings for uint256;
bytes32 public constant URI_SETTER_ROLE = keccak256("URI_SETTER_ROLE"); bytes32 public constant URI_SETTER_ROLE = keccak256("URI_SETTER_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURN_ROLE = keccak256("BURN_ROLE"); bytes32 public constant BURN_ROLE = keccak256("BURN_ROLE");
bytes32 public constant LOCK_ROLE = keccak256("LOCK_ROLE"); bytes32 public constant LOCK_ROLE = keccak256("LOCK_ROLE");
mapping(uint256 => bool) public lockedTokens; mapping(uint256 => bool) public lockedTokens;
mapping(address => uint256[]) private _ownedTokens; mapping(address => uint256[]) private _ownedTokens;
// for 0 means not exists, value stored = index + 1; // for 0 means not exists, value stored = index + 1;
mapping(address => mapping(uint256 => uint256)) private _ownedTokensIndex; mapping(address => mapping(uint256 => uint256)) private _ownedTokensIndex;
mapping(uint256 => uint256) private _totalSupply; mapping(uint256 => uint256) private _totalSupply;
uint256 public maxSupply = 0; uint256 public maxSupply = 0;
struct TokenStruct { struct TokenStruct {
uint256 tokenId; uint256 tokenId;
uint256 amount; uint256 amount;
}
constructor() ERC1155("https://market.cebg.games/api/nft/info/{id}") {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(URI_SETTER_ROLE, msg.sender);
}
function setURI(string memory newuri) external onlyRole(URI_SETTER_ROLE) {
_setURI(newuri);
}
function mintBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) external onlyRole(MINTER_ROLE) {
_mintBatch(to, ids, amounts, data);
}
function burnBatch(
address account,
uint256[] memory ids,
uint256[] memory values
) external onlyRole(BURN_ROLE) {
_burnBatch(account, ids, values);
}
// The following functions are overrides required by Solidity.
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC1155, AccessControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
/**
* @dev Add factory to mint/burn item
*/
function setMintFactory(address factory) external onlyOwner {
_grantRole(MINTER_ROLE, factory);
}
/**
* @dev Remove factory
*/
function removeMintFactory(address factory) external onlyOwner {
_revokeRole(MINTER_ROLE, factory);
}
function grantLockRole(address account) external onlyOwner {
_grantRole(LOCK_ROLE, account);
}
function revokeLockRole(address account) external onlyOwner {
_revokeRole(LOCK_ROLE, account);
}
/**
* @dev Add factory to burn item
*/
function grantBurnRole(address proxy) external onlyOwner {
_grantRole(BURN_ROLE, proxy);
}
/**
* @dev Remove proxy
*/
function revokeBurnRole(address proxy) external onlyOwner {
_revokeRole(BURN_ROLE, proxy);
}
/**
* @dev Total amount of tokens in with a given id.
*/
function totalSupply(uint256 id) external view virtual returns (uint256) {
return _totalSupply[id];
}
/**
* @dev Indicates whether any token exist with a given id, or not.
*/
function exists(uint256 id) public view virtual returns (bool) {
return _totalSupply[id] > 0;
}
function canMint(
uint256 /*id*/
) external view virtual returns (bool) {
return true;
}
/**
* @dev Lock token to use in game or for rental
*/
function lock(uint256 id) external onlyRole(LOCK_ROLE) {
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(!lockedTokens[id], "Token has already locked");
lockedTokens[id] = true;
}
function lockBatch(uint256[] memory ids) external onlyRole(LOCK_ROLE) {
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
uint256 id = ids[i];
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(!lockedTokens[id], "Token has already locked");
lockedTokens[id] = true;
} }
}
constructor() ERC1155("https://market.cebg.games/api/nft/info/{id}") { /**
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender); * @dev Unlock token to use blockchain or sale on marketplace
_grantRole(URI_SETTER_ROLE, msg.sender); */
function unlock(uint256 id) external onlyRole(LOCK_ROLE) {
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(lockedTokens[id], "Token has already unlocked");
lockedTokens[id] = false;
}
function unlockBatch(uint256[] memory ids) external onlyRole(LOCK_ROLE) {
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
uint256 id = ids[i];
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(lockedTokens[id], "Token has already unlocked");
lockedTokens[id] = false;
} }
}
function setURI(string memory newuri) external onlyRole(URI_SETTER_ROLE) { /**
_setURI(newuri); * @dev Get lock status
*/
function isLocked(uint256 id) external view returns (bool) {
return lockedTokens[id];
}
function isLockedBatch(uint256[] memory ids)
external
view
returns (bool[] memory)
{
uint256 len = ids.length;
bool[] memory results = new bool[](len);
for (uint256 i = 0; i < len; ++i) {
results[i] = lockedTokens[ids[i]];
} }
return results;
}
function mintBatch( /**
address to, * @dev See {ERC1155-_beforeTokenTransfer}.
uint256[] memory ids, */
uint256[] memory amounts, function _beforeTokenTransfer(
bytes memory data address operator,
) external onlyRole(MINTER_ROLE) { address from,
_mintBatch(to, ids, amounts, data); address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual override {
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
require(!lockedTokens[ids[i]], "Can not transfer locked token");
} }
if (from == address(0)) {
// mint nft
function burnBatch( for (uint256 i = 0; i < len; ++i) {
address account, _totalSupply[ids[i]] += amounts[i];
uint256[] memory ids, if (maxSupply > 0) {
uint256[] memory values require(
) external onlyRole(BURN_ROLE) { _totalSupply[ids[i]] <= maxSupply,
_burnBatch(account, ids, values); "Can not mint for exceeds max supply"
} );
// The following functions are overrides required by Solidity.
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC1155, AccessControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
/**
* @dev Add factory to mint/burn item
*/
function setMintFactory(address factory)
external
onlyOwner
{
_grantRole(MINTER_ROLE, factory);
}
/**
* @dev Remove factory
*/
function removeMintFactory(address factory)
external
onlyOwner
{
_revokeRole(MINTER_ROLE, factory);
}
function grantLockRole(address account)
external
onlyOwner
{
_grantRole(LOCK_ROLE, account);
}
function revokeLockRole(address account)
external
onlyOwner
{
_revokeRole(LOCK_ROLE, account);
}
/**
* @dev Add factory to burn item
*/
function grantBurnRole(address proxy) external onlyOwner {
_grantRole(BURN_ROLE, proxy);
}
/**
* @dev Remove proxy
*/
function revokeBurnRole(address proxy) external onlyOwner {
_revokeRole(BURN_ROLE, proxy);
}
/**
* @dev Total amount of tokens in with a given id.
*/
function totalSupply(uint256 id) external view virtual returns (uint256) {
return _totalSupply[id];
}
/**
* @dev Indicates whether any token exist with a given id, or not.
*/
function exists(uint256 id) public view virtual returns (bool) {
return _totalSupply[id] > 0;
}
function canMint(uint256 /*id*/) external view virtual returns (bool) {
return true;
}
/**
* @dev Lock token to use in game or for rental
*/
function lock(uint256 id) external onlyRole(LOCK_ROLE) {
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(!lockedTokens[id], "Token has already locked");
lockedTokens[id] = true;
}
function lockBatch(uint256[] memory ids) external onlyRole(LOCK_ROLE) {
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
uint256 id = ids[i];
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(!lockedTokens[id], "Token has already locked");
lockedTokens[id] = true;
} }
}
} else if (from != to) {
// transfer from -> to
for (uint256 i = 0; i < len; ++i) {
_removeTokenFromOwnerEnumeration(from, ids[i], amounts[i]);
}
} }
/** if (to == address(0)) {
* @dev Unlock token to use blockchain or sale on marketplace // burn nft
*/ for (uint256 i = 0; i < len; ++i) {
function unlock(uint256 id) external onlyRole(LOCK_ROLE) { _totalSupply[ids[i]] -= amounts[i];
require(_totalSupply[id] > 0, "Must be valid tokenId"); }
require(lockedTokens[id], "Token has already unlocked"); } else if (to != from) {
lockedTokens[id] = false; // mint or transfer from -> to
for (uint256 i = 0; i < len; ++i) {
_addTokenToOwnerEnumeration(to, ids[i]);
}
} }
}
function unlockBatch(uint256[] memory ids) external onlyRole(LOCK_ROLE) { function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 len = ids.length; if (_ownedTokensIndex[to][tokenId] == 0 && balanceOf(to, tokenId) == 0) {
for (uint256 i = 0; i < len; ++i) { _ownedTokensIndex[to][tokenId] = _ownedTokens[to].length + 1;
uint256 id = ids[i]; _ownedTokens[to].push(tokenId);
require(_totalSupply[id] > 0, "Must be valid tokenId");
require(lockedTokens[id], "Token has already unlocked");
lockedTokens[id] = false;
}
} }
}
/** function _removeTokenFromOwnerEnumeration(
* @dev Get lock status address from,
*/ uint256 tokenId,
function isLocked(uint256 id) external view returns (bool) { uint256 amount
return lockedTokens[id]; ) private {
uint256 balance = balanceOf(from, tokenId);
if (balance == amount) {
uint256 lastTokenIndex = _ownedTokens[from].length - 1;
uint256 tokenIndex = _ownedTokensIndex[from][tokenId] - 1;
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
// Move the last token to the slot of the to-delete token
_ownedTokens[from][tokenIndex] = lastTokenId;
// Update the moved token's index
_ownedTokensIndex[from][lastTokenId] = tokenIndex + 1;
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[from][tokenId];
_ownedTokens[from].pop();
} }
}
function isLockedBatch(uint256[] memory ids) function userTokens(
external address user,
view uint256 start,
returns (bool[] memory) uint256 page
{ ) external view returns (TokenStruct[] memory) {
uint256 len = ids.length; uint256 size = _ownedTokens[user].length;
bool[] memory results = new bool[](len); uint256 max = size;
for (uint256 i = 0; i < len; ++i) { uint256 pageSize = 0;
results[i] = lockedTokens[ids[i]]; if (start < size) {
} if (start + page < size) {
return results; pageSize = page;
max = start + page;
} else {
pageSize = size - start;
}
} }
TokenStruct[] memory results = new TokenStruct[](pageSize);
/** if (pageSize > 0) {
* @dev See {ERC1155-_beforeTokenTransfer}. for (uint256 i = start; i < max; ++i) {
*/ TokenStruct memory dataObj;
function _beforeTokenTransfer( uint256 tokenId = _ownedTokens[user][i];
address operator, dataObj.tokenId = tokenId;
address from, dataObj.amount = balanceOf(user, tokenId);
address to, results[i - start] = dataObj;
uint256[] memory ids, }
uint256[] memory amounts,
bytes memory data
) internal virtual override {
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
uint256 len = ids.length;
for (uint256 i = 0; i < len; ++i) {
require(!lockedTokens[ids[i]], "Can not transfer locked token");
}
if (from == address(0)) {
// mint nft
for (uint256 i = 0; i < len; ++i) {
_totalSupply[ids[i]] += amounts[i];
if (maxSupply > 0) {
require(
_totalSupply[ids[i]] <= maxSupply,
"Can not mint for exceeds max supply"
);
}
}
} else if (from != to) {
// transfer from -> to
for (uint256 i = 0; i < len; ++i) {
_removeTokenFromOwnerEnumeration(from, ids[i], amounts[i]);
}
}
if (to == address(0)) {
// burn nft
for (uint256 i = 0; i < len; ++i) {
_totalSupply[ids[i]] -= amounts[i];
}
} else if (to != from) {
// mint or transfer from -> to
for (uint256 i = 0; i < len; ++i) {
_addTokenToOwnerEnumeration(to, ids[i]);
}
}
}
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
if (
_ownedTokensIndex[to][tokenId] == 0 && balanceOf(to, tokenId) == 0
) {
_ownedTokensIndex[to][tokenId] = _ownedTokens[to].length + 1;
_ownedTokens[to].push(tokenId);
}
} }
return results;
}
function _removeTokenFromOwnerEnumeration( function tokenTypes(address user) external view returns (uint256) {
address from, return _ownedTokens[user].length;
uint256 tokenId, }
uint256 amount
) private {
uint256 balance = balanceOf(from, tokenId);
if (balance == amount) {
uint256 lastTokenIndex = _ownedTokens[from].length - 1;
uint256 tokenIndex = _ownedTokensIndex[from][tokenId] - 1;
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
// Move the last token to the slot of the to-delete token
_ownedTokens[from][tokenIndex] = lastTokenId;
// Update the moved token's index
_ownedTokensIndex[from][lastTokenId] = tokenIndex + 1;
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[from][tokenId];
_ownedTokens[from].pop();
}
}
function userTokens(
address user,
uint256 start,
uint256 page
) external view returns (TokenStruct[] memory) {
uint256 size = _ownedTokens[user].length;
uint256 max = size;
uint256 pageSize = 0;
if (start < size) {
if (start + page < size) {
pageSize = page;
max = start + page;
} else {
pageSize = size - start;
}
}
TokenStruct[] memory results = new TokenStruct[](pageSize);
if (pageSize > 0) {
for (uint256 i = start; i < max; ++i) {
TokenStruct memory dataObj;
uint256 tokenId = _ownedTokens[user][i];
dataObj.tokenId = tokenId;
dataObj.amount = balanceOf(user, tokenId);
results[i - start] = dataObj;
}
}
return results;
}
function tokenTypes(address user) external view returns (uint256) {
return _ownedTokens[user].length;
}
} }

View File

@ -4,13 +4,13 @@ pragma solidity 0.8.10;
import "./BEBase1155.sol"; import "./BEBase1155.sol";
contract BEChip1155 is BEBase1155 { contract BEChip1155 is BEBase1155 {
mapping(uint256 => uint256) public tokenLevels; mapping(uint256 => uint256) public tokenLevels;
constructor() { constructor() {
maxSupply = 1; maxSupply = 1;
} }
function canMint(uint256 id) external view override returns (bool) { function canMint(uint256 id) external view override returns (bool) {
return !exists(id); return !exists(id);
} }
} }

View File

@ -2,6 +2,7 @@
pragma solidity 0.8.10; pragma solidity 0.8.10;
import "./BEBase1155.sol"; import "./BEBase1155.sol";
/** /**
* for Hero and Weapon shard * for Hero and Weapon shard
*/ */

View File

@ -2,11 +2,10 @@
pragma solidity 0.8.10; pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
contract BECoin is ERC20Burnable { contract BECoin is ERC20Burnable {
uint256 public constant INITIALIZED_CAP = 100000000 * 1e18; uint256 public constant INITIALIZED_CAP = 100000000 * 1e18;
constructor() ERC20("CRYPTO ELITE'S COIN", "CEC") { constructor() ERC20("CRYPTO ELITE'S COIN", "CEC") {
_mint(_msgSender(), INITIALIZED_CAP); _mint(_msgSender(), INITIALIZED_CAP);
} }
} }

View File

@ -4,33 +4,31 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/access/Ownable.sol";
/** /**
* this contract will transfer ownership to BETimelockController after deployed * this contract will transfer ownership to BETimelockController after deployed
* all onlyowner method would add timelock * all onlyowner method would add timelock
*/ */
contract BEGold is ERC20, ERC20Burnable, Pausable, Ownable { contract BEGold is ERC20, ERC20Burnable, Pausable, Ownable {
constructor() ERC20("CRYPTO ELITE'S GOLD", "CEG") {}
function pause() external onlyOwner {
_pause();
}
constructor() ERC20("CRYPTO ELITE'S GOLD", "CEG") { function unpause() external onlyOwner {
} _unpause();
}
function pause() external onlyOwner { function mint(address to, uint256 amount) external onlyOwner {
_pause(); _mint(to, amount);
} }
function unpause() external onlyOwner { function _beforeTokenTransfer(
_unpause(); address from,
} address to,
uint256 amount
function mint(address to, uint256 amount) external onlyOwner { ) internal override whenNotPaused {
_mint(to, amount); super._beforeTokenTransfer(from, to, amount);
} }
function _beforeTokenTransfer(address from, address to, uint256 amount)
internal
whenNotPaused
override
{
super._beforeTokenTransfer(from, to, amount);
}
} }

View File

@ -7,164 +7,157 @@ import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/access/AccessControl.sol";
abstract contract BEBase is ERC721, AccessControl, ERC721Enumerable, Ownable { abstract contract BEBase is ERC721, AccessControl, ERC721Enumerable, Ownable {
using Strings for uint256; using Strings for uint256;
mapping(uint256 => bool) public lockedTokens; mapping(uint256 => bool) public lockedTokens;
string private _baseTokenURI = "https://market.cebg.games/api/nft/info/"; string private _baseTokenURI = "https://market.cebg.games/api/nft/info/";
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURN_ROLE = keccak256("BURN_ROLE"); bytes32 public constant BURN_ROLE = keccak256("BURN_ROLE");
bytes32 public constant LOCK_ROLE = keccak256("LOCK_ROLE"); bytes32 public constant LOCK_ROLE = keccak256("LOCK_ROLE");
function _baseURI() internal view virtual override returns (string memory) { function _baseURI() internal view virtual override returns (string memory) {
return _baseTokenURI; return _baseTokenURI;
} }
/** /**
* @dev Creates a new token for `to`. Its token ID will be automatically * @dev Creates a new token for `to`. Its token ID will be automatically
* assigned (and available on the emitted {IERC721-Transfer} event), and the token * assigned (and available on the emitted {IERC721-Transfer} event), and the token
* URI autogenerated based on the base URI passed at construction. * URI autogenerated based on the base URI passed at construction.
* *
* See {ERC721-_mint}. * See {ERC721-_mint}.
* *
* Requirements: * Requirements:
* *
* - the caller must have the `MINTER_ROLE`. * - the caller must have the `MINTER_ROLE`.
*/ */
function mint(address to, uint256 tokenId) function mint(address to, uint256 tokenId)
external external
onlyRole(MINTER_ROLE) virtual
virtual { onlyRole(MINTER_ROLE)
require(!_exists(tokenId), "Must have unique tokenId"); {
// We cannot just use balanceOf to create the new tokenId because tokens require(!_exists(tokenId), "Must have unique tokenId");
// can be burned (destroyed), so we need a separate counter. // We cannot just use balanceOf to create the new tokenId because tokens
_mint(to, tokenId); // can be burned (destroyed), so we need a separate counter.
} _mint(to, tokenId);
}
/** /**
* @dev Add factory to mint item * @dev Add factory to mint item
*/ */
function setMintFactory(address factory) external onlyOwner { function setMintFactory(address factory) external onlyOwner {
_grantRole(MINTER_ROLE, factory); _grantRole(MINTER_ROLE, factory);
} }
/** /**
* @dev Remove factory * @dev Remove factory
*/ */
function removeMintFactory(address factory) external onlyOwner { function removeMintFactory(address factory) external onlyOwner {
_revokeRole(MINTER_ROLE, factory); _revokeRole(MINTER_ROLE, factory);
} }
/** /**
* @dev Add factory to burn item * @dev Add factory to burn item
*/ */
function grantBurnRole(address proxy) external onlyOwner { function grantBurnRole(address proxy) external onlyOwner {
_grantRole(BURN_ROLE, proxy); _grantRole(BURN_ROLE, proxy);
} }
/** /**
* @dev Remove proxy * @dev Remove proxy
*/ */
function revokeBurnProxy(address proxy) external onlyOwner { function revokeBurnProxy(address proxy) external onlyOwner {
_revokeRole(BURN_ROLE, proxy); _revokeRole(BURN_ROLE, proxy);
} }
/**
* @dev Add address to lock item
*/
function grantLockRole(address account)
external
onlyOwner
{
_grantRole(LOCK_ROLE, account);
}
/**
* @dev Remove address for lock item
*/
function revokeLockRole(address account)
external
onlyOwner
{
_revokeRole(LOCK_ROLE, account);
}
/**
* @dev Add address to lock item
*/
function grantLockRole(address account) external onlyOwner {
_grantRole(LOCK_ROLE, account);
}
/** /**
* @dev Lock token to use in game or for rental * @dev Remove address for lock item
*/ */
function lock(uint256 tokenId) external onlyRole(LOCK_ROLE) { function revokeLockRole(address account) external onlyOwner {
require(_exists(tokenId), "Must be valid tokenId"); _revokeRole(LOCK_ROLE, account);
require(!lockedTokens[tokenId], "Token has already locked"); }
lockedTokens[tokenId] = true;
}
/** /**
* @dev Unlock token to use blockchain or sale on marketplace * @dev Lock token to use in game or for rental
*/ */
function unlock(uint256 tokenId) external onlyRole(LOCK_ROLE){ function lock(uint256 tokenId) external onlyRole(LOCK_ROLE) {
require(_exists(tokenId), "Must be valid tokenId"); require(_exists(tokenId), "Must be valid tokenId");
require(lockedTokens[tokenId], "Token has already unlocked"); require(!lockedTokens[tokenId], "Token has already locked");
lockedTokens[tokenId] = false; lockedTokens[tokenId] = true;
} }
/** /**
* @dev Get lock status * @dev Unlock token to use blockchain or sale on marketplace
*/ */
function isLocked(uint256 tokenId) external view returns (bool) { function unlock(uint256 tokenId) external onlyRole(LOCK_ROLE) {
return lockedTokens[tokenId]; require(_exists(tokenId), "Must be valid tokenId");
} require(lockedTokens[tokenId], "Token has already unlocked");
lockedTokens[tokenId] = false;
}
/** /**
* @dev Set token URI * @dev Get lock status
*/ */
function updateBaseURI(string calldata baseTokenURI) external onlyOwner { function isLocked(uint256 tokenId) external view returns (bool) {
_baseTokenURI = baseTokenURI; return lockedTokens[tokenId];
} }
/** /**
* @dev See {IERC165-_beforeTokenTransfer}. * @dev Set token URI
*/ */
function _beforeTokenTransfer( function updateBaseURI(string calldata baseTokenURI) external onlyOwner {
address from, _baseTokenURI = baseTokenURI;
address to, }
uint256 tokenId
) internal virtual override(ERC721, ERC721Enumerable) {
require(!lockedTokens[tokenId], "Can not transfer locked token");
super._beforeTokenTransfer(from, to, tokenId);
}
/** /**
* @dev See {IERC165-supportsInterface}. * @dev See {IERC165-_beforeTokenTransfer}.
*/ */
function supportsInterface(bytes4 interfaceId) function _beforeTokenTransfer(
public address from,
view address to,
virtual uint256 tokenId
override(AccessControl, ERC721, ERC721Enumerable) ) internal virtual override(ERC721, ERC721Enumerable) {
returns (bool) require(!lockedTokens[tokenId], "Can not transfer locked token");
{ super._beforeTokenTransfer(from, to, tokenId);
return super.supportsInterface(interfaceId); }
}
/**
* @dev Burns `tokenId`.
*
* Requirements:
*
* - The caller must own `tokenId` or be an approved operator.
*/
function burn(address owner, uint256 tokenId)
external
onlyRole(BURN_ROLE)
virtual
{
require(_exists(tokenId), "TokenId not exists");
require(!lockedTokens[tokenId], "Can not burn locked token");
require(
ownerOf(tokenId) == owner,
"current address is not owner of this item now"
);
_burn(tokenId);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(AccessControl, ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
/**
* @dev Burns `tokenId`.
*
* Requirements:
*
* - The caller must own `tokenId` or be an approved operator.
*/
function burn(address owner, uint256 tokenId)
external
virtual
onlyRole(BURN_ROLE)
{
require(_exists(tokenId), "TokenId not exists");
require(!lockedTokens[tokenId], "Can not burn locked token");
require(
ownerOf(tokenId) == owner,
"current address is not owner of this item now"
);
_burn(tokenId);
}
} }

View File

@ -4,6 +4,6 @@ import "./BEBase.sol";
// this contract will transfer ownership to BETimelockController after deployed // this contract will transfer ownership to BETimelockController after deployed
// all onlyowner method would add timelock // all onlyowner method would add timelock
contract BEChip is BEBase{ contract BEChip is BEBase {
constructor() ERC721("CRYPTO ELITE'S CHIP", "CHIP") {} constructor() ERC721("CRYPTO ELITE'S CHIP", "CHIP") {}
} }

View File

@ -4,6 +4,6 @@ import "./BEBase.sol";
// this contract will transfer ownership to BETimelockController after deployed // this contract will transfer ownership to BETimelockController after deployed
// all onlyowner method would add timelock // all onlyowner method would add timelock
contract BEEquipment is BEBase{ contract BEEquipment is BEBase {
constructor() ERC721("CRYPTO ELITE'S WEAPON", "WEAPON") {} constructor() ERC721("CRYPTO ELITE'S WEAPON", "WEAPON") {}
} }

View File

@ -4,6 +4,6 @@ import "./BEBase.sol";
// this contract will transfer ownership to BETimelockController after deployed // this contract will transfer ownership to BETimelockController after deployed
// all onlyowner method would add timelock // all onlyowner method would add timelock
contract BEHero is BEBase{ contract BEHero is BEBase {
constructor() ERC721("CRYPTO ELITE'S HERO", "HERO") {} constructor() ERC721("CRYPTO ELITE'S HERO", "HERO") {}
} }

View File

@ -4,23 +4,26 @@ import "./BEBase.sol";
// this contract will transfer ownership to BETimelockController after deployed // this contract will transfer ownership to BETimelockController after deployed
// all onlyowner method would add timelock // all onlyowner method would add timelock
contract BEMysteryBox is BEBase{ contract BEMysteryBox is BEBase {
constructor() ERC721("CRYPTO ELITE'S MYSTERY BOXES", "BOX") {} constructor() ERC721("CRYPTO ELITE'S MYSTERY BOXES", "BOX") {}
function userTokens(address user, uint256 start, uint256 page) function userTokens(
external view returns (uint256 [] memory){ address user,
uint256 size = balanceOf(user); uint256 start,
uint256[] memory results = new uint256[](page); uint256 page
if (start < size) { ) external view returns (uint256[] memory) {
uint256 max = size; uint256 size = balanceOf(user);
if (start + page < size) { uint256[] memory results = new uint256[](page);
max = start + page; if (start < size) {
} uint256 max = size;
for (uint256 i = start; i < max; ++i) { if (start + page < size) {
uint256 tokenId = tokenOfOwnerByIndex(user, i); max = start + page;
results[i-start] = tokenId; }
} for (uint256 i = start; i < max; ++i) {
} uint256 tokenId = tokenOfOwnerByIndex(user, i);
return results; results[i - start] = tokenId;
}
} }
return results;
}
} }

View File

@ -9,6 +9,7 @@ contract TimeChecker is Ownable {
constructor() { constructor() {
_duration = 1 days; _duration = 1 days;
} }
modifier timeValid(uint256 time) { modifier timeValid(uint256 time) {
require( require(
time + _duration >= block.timestamp, time + _duration >= block.timestamp,
@ -20,10 +21,9 @@ contract TimeChecker is Ownable {
/** /**
* @dev Returns the max duration for function called by user * @dev Returns the max duration for function called by user
*/ */
function getDuration() external view function getDuration() external view returns (uint256 duration) {
returns (uint256 duration) { return _duration;
return _duration; }
}
/** /**
* @dev Change duration value * @dev Change duration value
@ -31,6 +31,4 @@ contract TimeChecker is Ownable {
function updateDuation(uint256 valNew) external onlyOwner { function updateDuation(uint256 valNew) external onlyOwner {
_duration = valNew; _duration = valNew;
} }
} }

View File

@ -1,9 +1,12 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.10; pragma solidity 0.8.10;
library UInt{ library UInt {
function asSingletonArray(uint256 element)
function asSingletonArray(uint256 element) internal pure returns (uint256[] memory) { internal
pure
returns (uint256[] memory)
{
uint256[] memory array = new uint256[](1); uint256[] memory array = new uint256[](1);
array[0] = element; array[0] = element;
return array; return array;

104
package-lock.json generated
View File

@ -1426,6 +1426,15 @@
"integrity": "sha1-n7OjzzEyMoFR81PeRjLgHlIQK+o=", "integrity": "sha1-n7OjzzEyMoFR81PeRjLgHlIQK+o=",
"dev": true "dev": true
}, },
"@solidity-parser/parser": {
"version": "0.14.3",
"resolved": "https://registry.npmmirror.com/@solidity-parser/parser/-/parser-0.14.3.tgz",
"integrity": "sha512-29g2SZ29HtsqA58pLCtopI1P/cPy5/UAzlcAXO6T/CNJimG6yA8kx4NaseMyJULiC+TEs02Y9/yeHzClqoA0hw==",
"dev": true,
"requires": {
"antlr4ts": "^0.5.0-alpha.4"
}
},
"@szmarczak/http-timer": { "@szmarczak/http-timer": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmmirror.com/@szmarczak/http-timer/download/@szmarczak/http-timer-1.1.2.tgz", "resolved": "https://registry.npmmirror.com/@szmarczak/http-timer/download/@szmarczak/http-timer-1.1.2.tgz",
@ -3061,6 +3070,12 @@
"color-convert": "^1.9.0" "color-convert": "^1.9.0"
} }
}, },
"antlr4ts": {
"version": "0.5.0-alpha.4",
"resolved": "https://registry.npmmirror.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz",
"integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==",
"dev": true
},
"any-signal": { "any-signal": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmmirror.com/any-signal/download/any-signal-2.1.2.tgz", "resolved": "https://registry.npmmirror.com/any-signal/download/any-signal-2.1.2.tgz",
@ -15296,6 +15311,89 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"prettier": {
"version": "2.7.1",
"resolved": "https://registry.npmmirror.com/prettier/-/prettier-2.7.1.tgz",
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true
},
"prettier-plugin-solidity": {
"version": "1.0.0-beta.24",
"resolved": "https://registry.npmmirror.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.24.tgz",
"integrity": "sha512-6JlV5BBTWzmDSq4kZ9PTXc3eLOX7DF5HpbqmmaF+kloyUwOZbJ12hIYsUaZh2fVgZdV2t0vWcvY6qhILhlzgqg==",
"dev": true,
"requires": {
"@solidity-parser/parser": "^0.14.3",
"emoji-regex": "^10.1.0",
"escape-string-regexp": "^4.0.0",
"semver": "^7.3.7",
"solidity-comments-extractor": "^0.0.7",
"string-width": "^4.2.3"
},
"dependencies": {
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"emoji-regex": {
"version": "10.1.0",
"resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.1.0.tgz",
"integrity": "sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg==",
"dev": true
},
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"semver": {
"version": "7.3.7",
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"dependencies": {
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
}
}
},
"strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
}
}
},
"printj": { "printj": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmmirror.com/printj/download/printj-1.1.2.tgz", "resolved": "https://registry.npmmirror.com/printj/download/printj-1.1.2.tgz",
@ -16708,6 +16806,12 @@
} }
} }
}, },
"solidity-comments-extractor": {
"version": "0.0.7",
"resolved": "https://registry.npmmirror.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz",
"integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==",
"dev": true
},
"source-list-map": { "source-list-map": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmmirror.com/source-list-map/download/source-list-map-2.0.1.tgz", "resolved": "https://registry.npmmirror.com/source-list-map/download/source-list-map-2.0.1.tgz",

View File

@ -6,6 +6,8 @@
"scripts": { "scripts": {
"test": "npx truffle test", "test": "npx truffle test",
"build": "truffle compile", "build": "truffle compile",
"prettier": "prettier --write 'contracts/**/*.sol'",
"lint": "prettier --list-different 'contracts/**/*.sol'",
"deploy:dev": "truffle migrate --network development", "deploy:dev": "truffle migrate --network development",
"deploy:20": "truffle migrate --network lan20 --compile-none", "deploy:20": "truffle migrate --network lan20 --compile-none",
"deploy:22": "truffle migrate --network lan22 --compile-none", "deploy:22": "truffle migrate --network lan22 --compile-none",
@ -20,6 +22,8 @@
"@openzeppelin/test-helpers": "^0.5.15", "@openzeppelin/test-helpers": "^0.5.15",
"@truffle/hdwallet-provider": "^2.0.0", "@truffle/hdwallet-provider": "^2.0.0",
"chai": "^4.3.4", "chai": "^4.3.4",
"prettier": "^2.7.1",
"prettier-plugin-solidity": "^1.0.0-beta.24",
"truffle": "^5.4.23", "truffle": "^5.4.23",
"truffle-plugin-stdjsonin": "git+https://github.com/mhrsalehi/truffle-plugin-stdjsonin.git", "truffle-plugin-stdjsonin": "git+https://github.com/mhrsalehi/truffle-plugin-stdjsonin.git",
"truffle-plugin-verify": "^0.5.25" "truffle-plugin-verify": "^0.5.25"