contracts-imtbl/contracts/mall/GameItemMall.sol

94 lines
2.7 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {HasSignature} from "../core/HasSignature.sol";
import {TimeChecker} from "../utils/TimeChecker.sol";
import {MallBase} from "./MallBase.sol";
/**
* @title GameItemMall
* @dev GameItemMall is a contract for managing centralized game items sale,
* allowing users to buy item in game.
*/
contract GameItemMall is MallBase, ReentrancyGuard, HasSignature, TimeChecker {
using SafeERC20 for IERC20;
mapping(uint256 itemId => address user) public orderIdUsed;
event ItemSoldOut(
address indexed buyer,
address indexed passport,
uint256 indexed orderId,
address currency,
uint256 amount
);
constructor(address _currency, address _feeToAddress, address _verifier, uint256 _duration)
TimeChecker(_duration)
MallBase(_currency, _feeToAddress, _verifier){
}
function buy(
address passport,
uint256 orderId,
address currency,
uint256 amount,
uint256 signTime,
uint256 saltNonce,
bytes calldata signature
) external nonReentrant signatureValid(signature) timeValid(signTime) {
require(passport != address(0), "passport address can not be zero");
// check if orderId is used
require(orderIdUsed[orderId] == address(0), "orderId is used");
// check if currency is supported
require(erc20Supported[currency], "currency is not supported");
// check if amount is valid
require(amount > 0, "amount is zero");
address buyer = _msgSender();
bytes32 criteriaMessageHash = getMessageHash(
buyer,
passport,
orderId,
currency,
amount,
_CACHED_THIS,
_CACHED_CHAIN_ID,
signTime,
saltNonce
);
checkSigner(verifier, criteriaMessageHash, signature);
IERC20 paymentContract = IERC20(currency);
_useSignature(signature);
orderIdUsed[orderId] = buyer;
paymentContract.safeTransferFrom(buyer, feeToAddress, amount);
emit ItemSoldOut(buyer, passport, orderId, currency, amount);
}
function getMessageHash(
address _buyer,
address _passport,
uint256 _orderId,
address _currency,
uint256 _amount,
address _contract,
uint256 _chainId,
uint256 _signTime,
uint256 _saltNonce
) public pure returns (bytes32) {
bytes memory encoded = abi.encodePacked(
_buyer,
_passport,
_orderId,
_currency,
_amount,
_contract,
_chainId,
_signTime,
_saltNonce
);
return keccak256(encoded);
}
}