105 lines
3.0 KiB
Solidity
105 lines
3.0 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity 0.8.0;
|
|
|
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
import "./HasSignature.sol";
|
|
|
|
contract BEBoxMall is Ownable, HasSignature {
|
|
using SafeERC20 for IERC20;
|
|
|
|
event BEBoxPaid(
|
|
uint256 indexed boxId,
|
|
address indexed buyer,
|
|
uint256 boxType,
|
|
uint256 price,
|
|
address paymentToken
|
|
);
|
|
|
|
address public paymentReceivedAddress;
|
|
mapping(bytes => bool) public usedSignatures;
|
|
|
|
function setPaymentReceivedAddress(address _paymentReceivedAddress)
|
|
public
|
|
onlyOwner
|
|
{
|
|
require(_paymentReceivedAddress != address(0), 'payment received address can not be zero');
|
|
paymentReceivedAddress = _paymentReceivedAddress;
|
|
}
|
|
|
|
/**
|
|
* @dev BE box payment buy function
|
|
*/
|
|
function buyBoxWithSignature(
|
|
uint256 boxId,
|
|
uint256 _type,
|
|
address userAddress,
|
|
uint256 price,
|
|
address paymentErc20,
|
|
uint256 saltNonce,
|
|
bytes calldata signature
|
|
) external onlyOwner {
|
|
require(
|
|
!isContract(userAddress),
|
|
"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,
|
|
price,
|
|
saltNonce
|
|
);
|
|
|
|
checkSigner(userAddress, criteriaMessageHash, signature);
|
|
|
|
IERC20 paymentToken = IERC20(paymentErc20);
|
|
uint256 allowToPayAmount = paymentToken.allowance(
|
|
userAddress,
|
|
address(this)
|
|
);
|
|
require(
|
|
allowToPayAmount >= price,
|
|
"BEBoxPayment: Invalid token allowance"
|
|
);
|
|
// Transfer payment
|
|
paymentToken.safeTransferFrom(
|
|
userAddress,
|
|
paymentReceivedAddress,
|
|
price
|
|
);
|
|
usedSignatures[signature] = true;
|
|
// Emit payment event
|
|
emit BEBoxPaid(boxId, userAddress, _type, price, paymentErc20);
|
|
}
|
|
|
|
function getMessageHash(
|
|
uint256 _boxType,
|
|
address _paymentErc20,
|
|
uint256 _price,
|
|
uint256 _saltNonce
|
|
) public pure returns (bytes32) {
|
|
return
|
|
keccak256(
|
|
abi.encodePacked(_boxType, _paymentErc20, _price, _saltNonce)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @dev Identify an address is user address or contract address
|
|
*/
|
|
function isContract(address _address) private view returns (bool) {
|
|
uint32 size;
|
|
assembly {
|
|
size := extcodesize(_address)
|
|
}
|
|
return (size > 0);
|
|
}
|
|
}
|