重构代码, 将一些重复的代码提出来

This commit is contained in:
cebgcontract 2022-08-16 16:00:49 +08:00
parent 92876d4160
commit 1858260d00
10 changed files with 211 additions and 199 deletions

View File

@ -1,8 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "../utils/Approval.sol";
contract HasSignature {
contract HasSignature is Ownable, Approval{
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
@ -10,6 +12,7 @@ contract HasSignature {
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
mapping(bytes => bool) private _usedSignatures;
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
@ -112,4 +115,25 @@ contract HasSignature {
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

@ -23,7 +23,7 @@ interface INFTFactory {
IBEERC1155 nft
) external;
function ignoreSignature(
function useSignature(
bytes calldata signature
) external;
}

View File

@ -6,28 +6,24 @@ import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "../interfaces/IBEERC721.sol";
import "../interfaces/IBEERC1155.sol";
import "../utils/UInt.sol";
import "../utils/TimeChecker.sol";
import "../core/HasSignature.sol";
// this contract will transfer ownership to BETimelockController after deployed
// all onlyowner method would add timelock
contract EvolveFactory is Ownable, Initializable, HasSignature {
contract EvolveFactory is Ownable, TimeChecker, Initializable, HasSignature {
using UInt for uint256;
IBEERC721 public hero;
IBEERC721 public equip;
IBEERC1155 public chip;
mapping(bytes => bool) public usedSignatures;
uint256 private _duration;
address public executor;
event TokenEvolved(
uint256 indexed evolveEventId,
address indexed owner,
uint256 tokenEvolved,
uint256 tokenBurned,
uint256 chip
uint256[3] tokenIds
);
constructor()
@ -48,70 +44,14 @@ contract EvolveFactory is Ownable, Initializable, HasSignature {
executor = account;
}
/**
* @dev evolve function to Blissful Elites Hero NFT
* tokenIds: [hero_to_evolve, hero_for_burn, chip]
*/
function evolveHero(
uint256 evolveEventId,
uint256[3] calldata tokenIds,
uint256 saltNonce,
bytes calldata signature
) external {
require(
tokenIds[0] > 0 && tokenIds[1] > 0,
"EvolveFactory: hero to evolve and burn can not be 0"
);
require(
tokenIds[0] != tokenIds[1],
"EvolveFactory: hero to evolve and burn can not be same"
);
require(
hero.ownerOf(tokenIds[0]) == msg.sender,
"EvolveFactory: not owner of this hero now"
);
require(
!usedSignatures[signature],
"EvolveFactory: signature used. please send another transaction with new signature"
);
bytes32 criteriaMessageHash = getMessageHash(
evolveEventId,
tokenIds[0],
tokenIds[1],
tokenIds[2],
saltNonce
);
checkSigner(executor, criteriaMessageHash, signature);
hero.burn(msg.sender, tokenIds[1]);
if (tokenIds[2] > 0) {
uint256 amount = 1;
chip.burnBatch(msg.sender,
tokenIds[2].asSingletonArray(),
amount.asSingletonArray());
}
usedSignatures[signature] = true;
emit TokenEvolved(
evolveEventId,
msg.sender,
tokenIds[0],
tokenIds[1],
tokenIds[2]
);
}
/**
* @dev evolve function to Blissful Elites Equip NFT
* tokenIds: [equip_to_evolve, equip_for_burn, chip]
*/
function evolveEquip(
uint256 evolveEventId,
uint256[3] calldata tokenIds,
uint256 saltNonce,
bytes calldata signature
) external{
function evolve721NFT(
address to,
uint256[3] calldata tokenIds,
uint256 startTime,
uint256 saltNonce,
bytes calldata signature,
IBEERC721 nft
) internal signatureValid(signature) timeValid(startTime){
require(
tokenIds[0] > 0 && tokenIds[1] > 0,
"EvolveFactory: equip to evolve and burn can not be 0"
@ -123,56 +63,60 @@ contract EvolveFactory is Ownable, Initializable, HasSignature {
);
require(
equip.ownerOf(tokenIds[0]) == msg.sender,
"EvolveFactory: current address is not owner of this equip now"
nft.ownerOf(tokenIds[0]) == to,
"EvolveFactory: current address is not owner of this nft now"
);
require(
!usedSignatures[signature],
"EvolveFactory: signature used. please send another transaction with new signature"
);
nft.ownerOf(tokenIds[1]) == to,
"EvolveFactory: current address is not owner of this nft now"
);
if (tokenIds[2] > 0) {
require(
nft.ownerOf(tokenIds[2]) == to,
"EvolveFactory: current address is not owner of this nft now"
);
}
uint256[] memory signArray = new uint256[](3);
for (uint256 i = 0; i < tokenIds.length; ++ i) {
signArray[i] = tokenIds[i];
}
bytes32 criteriaMessageHash = getMessageHash(
evolveEventId,
tokenIds[0],
tokenIds[1],
tokenIds[2],
saltNonce
to,
startTime,
saltNonce,
signArray
);
checkSigner(executor, criteriaMessageHash, signature);
equip.burn(msg.sender, tokenIds[1]);
nft.burn(to, tokenIds[1]);
if (tokenIds[2] > 0) {
uint256 amount = 1;
chip.burnBatch(msg.sender,
chip.burnBatch(to,
tokenIds[2].asSingletonArray(),
amount.asSingletonArray());
}
usedSignatures[signature] = true;
useSignature(signature);
emit TokenEvolved(
evolveEventId,
msg.sender,
tokenIds[0],
tokenIds[1],
tokenIds[2]
to,
tokenIds
);
}
function getMessageHash(
uint256 _eventId,
uint256 _mainToken,
uint256 _burnToken,
uint256 _chipToken,
uint256 _saltNonce
address _to,
uint256 _startTime,
uint256 _saltNonce,
uint256[] memory _ids
) public pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
_eventId,
_mainToken,
_burnToken,
_chipToken,
_saltNonce
)
);
bytes memory encoded = abi.encodePacked(_to, _startTime, _saltNonce);
uint256 len = _ids.length;
for (uint256 i = 0; i < len; ++i) {
encoded = bytes.concat(encoded, abi.encodePacked(_ids[i]));
}
return keccak256(encoded);
}
}

View File

@ -6,9 +6,10 @@ import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "../interfaces/IBEERC721.sol";
import "../interfaces/IBEERC1155.sol";
import "../utils/UInt.sol";
import "../utils/TimeChecker.sol";
import "../core/HasSignature.sol";
contract MinterFactory is Ownable, Initializable, HasSignature {
contract MinterFactory is Ownable, TimeChecker, Initializable, HasSignature {
using UInt for uint256;
address public executor;
// NFT contract
@ -16,8 +17,6 @@ contract MinterFactory is Ownable, Initializable, HasSignature {
IBEERC721 public equip;
IBEERC1155 public chip;
IBEERC1155 public shard;
uint256 private _duration;
mapping(address => bool) public approvalLists;
event TokenMinted(
address contractAddress,
@ -33,7 +32,6 @@ contract MinterFactory is Ownable, Initializable, HasSignature {
uint256[] amounts
);
mapping(bytes => bool) public usedSignatures;
constructor() HasSignature("MinterFactory", "1") {}
@ -42,23 +40,8 @@ contract MinterFactory is Ownable, Initializable, HasSignature {
equip = IBEERC721(_erc721s[1]);
chip = IBEERC1155(_erc721s[2]);
shard = IBEERC1155(_erc721s[3]);
_duration = 1 days;
}
/**
* @dev Allow operation to reverse signature.
*/
function addApprovalList(address user) external onlyOwner {
require(!approvalLists[user], "MinterFactory: Invalid user address");
approvalLists[user] = true;
}
/**
* @dev Remove operation from approval list.
*/
function removeApprovalList(address user) external onlyOwner {
approvalLists[user] = false;
}
/**
* @dev update executor
@ -68,21 +51,6 @@ contract MinterFactory is Ownable, Initializable, HasSignature {
executor = account;
}
/**
* @dev Returns the max duration for function called by user
*/
function getDuration() external view
returns (uint256 duration) {
return _duration;
}
/**
* @dev Change duration value
*/
function updateDuation(uint256 valNew) external onlyOwner {
_duration = valNew;
}
/**
* @dev mint function to distribute Hero NFT to user
*/
@ -158,21 +126,13 @@ contract MinterFactory is Ownable, Initializable, HasSignature {
uint256 saltNonce,
bytes calldata signature,
IBEERC721 nft
) external {
require(
startTime + _duration >= block.timestamp,
"MinterFactory: signature expired, please send another transaction with new signature"
);
require(
!usedSignatures[signature],
"MinterFactory: signature used. please send another transaction with new signature"
);
) external signatureValid(signature) timeValid(startTime){
uint256[] memory signArray = new uint256[](1);
signArray[0] = id;
bytes32 criteriaMessageHash = getMessageHash(to, startTime, saltNonce, signArray);
checkSigner(executor, criteriaMessageHash, signature);
mint721NFT(to, id, nft);
usedSignatures[signature] = true;
useSignature(signature);
}
function mint1155BatchByUser(
@ -183,21 +143,13 @@ contract MinterFactory is Ownable, Initializable, HasSignature {
uint256 saltNonce,
bytes calldata signature,
IBEERC1155 nft
) external {
) 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"
);
require(
startTime + _duration >= block.timestamp,
"MinterFactory: signature expired, please send another transaction with new signature"
);
require(
!usedSignatures[signature],
"MinterFactory: signature used. please send another transaction with new signature"
);
uint256[] memory signArray = new uint256[](len * 2);
for (uint256 i = 0; i < len; ++i) {
require(
@ -210,7 +162,7 @@ contract MinterFactory is Ownable, Initializable, HasSignature {
bytes32 criteriaMessageHash = getMessageHash(to, startTime, saltNonce, signArray);
checkSigner(executor, criteriaMessageHash, signature);
mint1155NFTBatch(to, ids, amounts, nft);
usedSignatures[signature] = true;
useSignature(signature);
}
function mint721NFT(
@ -244,17 +196,6 @@ contract MinterFactory is Ownable, Initializable, HasSignature {
emit TokenMintedBatch(address(nft), to, ids, amounts);
}
function ignoreSignature(
bytes calldata signature
) external {
require(
approvalLists[_msgSender()],
"Must be valid approval list"
);
if (!usedSignatures[signature]) {
usedSignatures[signature] = true;
}
}
function getMessageHash(
address _to,

View File

@ -0,0 +1,48 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import "../interfaces/INFTFactory.sol";
import "../interfaces/IBEERC721.sol";
import "../interfaces/IBEERC1155.sol";
contract UserEvolveFactory is Ownable, Initializable {
IBEERC721 public hero;
IBEERC721 public equip;
IBEERC1155 public chip;
IBEERC1155 public shard;
event TokenEvolveFail (
address indexed to,
uint256 mainToken,
bytes signature,
string reason,
bytes byteReason
);
function init() external initializer onlyOwner {
}
/**
* @dev evolve function to Blissful Elites Hero NFT
* tokenIds: [hero_to_evolve, hero_for_burn, chip]
*/
function evolveHero(
uint256[3] calldata tokenIds,
uint256 saltNonce,
bytes calldata signature
) external {
}
/**
* @dev evolve function to Blissful Elites Equip NFT
* tokenIds: [equip_to_evolve, equip_for_burn, chip]
*/
function evolveEquip(
uint256[3] calldata tokenIds,
uint256 saltNonce,
bytes calldata signature
) external{
}
}

View File

@ -42,7 +42,7 @@ contract UserMinterFactory is Ownable, Initializable {
return true;
} catch Error(string memory reason) {
bytes memory by;
factory.ignoreSignature(signature);
factory.useSignature(signature);
emit TokenMintFail(
to,
signature,
@ -51,6 +51,7 @@ contract UserMinterFactory is Ownable, Initializable {
);
return false;
} catch (bytes memory lowLevelData) {
factory.useSignature(signature);
string memory reason;
emit TokenMintFail(
to,
@ -77,7 +78,7 @@ contract UserMinterFactory is Ownable, Initializable {
return true;
} catch Error(string memory reason) {
bytes memory by;
factory.ignoreSignature(signature);
factory.useSignature(signature);
emit TokenMintFail(
to,
signature,
@ -86,6 +87,7 @@ contract UserMinterFactory is Ownable, Initializable {
);
return false;
} catch (bytes memory lowLevelData) {
factory.useSignature(signature);
string memory reason;
emit TokenMintFail(
to,
@ -117,7 +119,7 @@ contract UserMinterFactory is Ownable, Initializable {
return true;
} catch Error(string memory reason) {
bytes memory by;
factory.ignoreSignature(signature);
factory.useSignature(signature);
emit TokenMintFail(
to,
signature,
@ -126,6 +128,7 @@ contract UserMinterFactory is Ownable, Initializable {
);
return false;
} catch (bytes memory lowLevelData) {
factory.useSignature(signature);
string memory reason;
emit TokenMintFail(
to,
@ -152,7 +155,7 @@ contract UserMinterFactory is Ownable, Initializable {
return true;
} catch Error(string memory reason) {
bytes memory by;
factory.ignoreSignature(signature);
factory.useSignature(signature);
emit TokenMintFail(
to,
signature,
@ -161,6 +164,7 @@ contract UserMinterFactory is Ownable, Initializable {
);
return false;
} catch (bytes memory lowLevelData) {
factory.useSignature(signature);
string memory reason;
emit TokenMintFail(
to,

View File

@ -36,7 +36,6 @@ contract BEBoxMall is Ownable, HasSignature, TimelockController{
);
address public paymentReceivedAddress;
mapping(bytes => bool) public usedSignatures;
function setPaymentReceivedAddress(address _paymentReceivedAddress)
public
@ -62,17 +61,13 @@ contract BEBoxMall is Ownable, HasSignature, TimelockController{
address paymentErc20,
uint256 saltNonce,
bytes calldata signature
) external onlyOwner {
) 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");
require(
!usedSignatures[signature],
"BEBoxPayment: signature used. please send another transaction with new signature"
);
bytes32 criteriaMessageHash = getMessageHash(
_type,
paymentErc20,
@ -97,7 +92,7 @@ contract BEBoxMall is Ownable, HasSignature, TimelockController{
paymentReceivedAddress,
price
);
usedSignatures[signature] = true;
useSignature(signature);
// Emit payment event
emit BEBoxPaid(boxId, userAddress, _type, price, paymentErc20);
}

View File

@ -81,11 +81,7 @@ contract MarketPlace is Ownable, HasSignature {
address[2] calldata addresses,
uint256[3] calldata values,
bytes calldata signature
) external {
require(
!usedSignatures[signature],
"Marketplace: this signature has added to ignore list already"
);
) external signatureValid(signature){
bytes32 criteriaMessageHash = getMessageHash(
addresses[0],
values[0],
@ -95,8 +91,7 @@ contract MarketPlace is Ownable, HasSignature {
);
checkSigner(_msgSender(), criteriaMessageHash, signature);
usedSignatures[signature] = true;
useSignature(signature);
}
/**
@ -106,7 +101,7 @@ contract MarketPlace is Ownable, HasSignature {
address[3] calldata addresses,
uint256[3] calldata values,
bytes calldata signature
) external returns (bool) {
) external signatureValid(signature) returns (bool) {
// address[3] [seller_address,nft_address,payment_token_address]
// uint256[3] [token_id,price,salt_nonce]
// bytes seller_signature
@ -115,11 +110,6 @@ contract MarketPlace is Ownable, HasSignature {
"Marketplace: invalid payment method"
);
require(
!usedSignatures[signature],
"Marketplace: signature used. please send another transaction with new signature"
);
bytes32 criteriaMessageHash = getMessageHash(
addresses[1],
values[0],
@ -167,7 +157,7 @@ contract MarketPlace is Ownable, HasSignature {
// transfer item to buyer
nft.safeTransferFrom(addresses[0], _msgSender(), values[0]);
usedSignatures[signature] = true;
useSignature(signature);
// emit sale event
emitEvent(addresses, values);
return true;

View File

@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Approval is Ownable {
mapping(address => bool) private approvalLists;
/**
* @dev Allow operation to reverse signature.
*/
function addApprovalList(address user) external onlyOwner {
require(!approvalLists[user], "MinterFactory: Invalid user address");
approvalLists[user] = true;
}
/**
* @dev Remove operation from approval list.
*/
function removeApprovalList(address user) external onlyOwner {
approvalLists[user] = false;
}
modifier approvaled() {
require(
_msgSender() == address(this) || approvalLists[_msgSender()],
"Must be valid approval list"
);
_;
}
}

View File

@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/access/Ownable.sol";
contract TimeChecker is Ownable {
mapping(address => bool) private approvalLists;
uint256 private _duration;
constructor() {
_duration = 1 days;
}
modifier timeValid(uint256 time) {
require(
time + _duration >= block.timestamp,
"expired, please send another transaction with new signature"
);
_;
}
/**
* @dev Returns the max duration for function called by user
*/
function getDuration() external view
returns (uint256 duration) {
return _duration;
}
/**
* @dev Change duration value
*/
function updateDuation(uint256 valNew) external onlyOwner {
_duration = valNew;
}
}