diff --git a/hardhat/contracts/IMintPoint.sol b/hardhat/contracts/IMintPoint.sol index 7862b75..0efff1b 100644 --- a/hardhat/contracts/IMintPoint.sol +++ b/hardhat/contracts/IMintPoint.sol @@ -4,7 +4,8 @@ pragma solidity ^0.8.19; interface IMintPoint { event Register(address indexed account, uint256 indexed id); - event Mint(address indexed account, uint256 indexed id); + event MintByMinter(address indexed account, uint256 indexed id); + event MintForReferral(address indexed from, address indexed to, uint256 indexed id); event Transfer(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values, uint256 timestamp); @@ -12,7 +13,9 @@ interface IMintPoint { function register() external; - function mint(address to, uint256 id, uint256 amount) external; + function mintByMinter(address to, uint256 id, uint256 amount) external; + + function mintForReferral(address to, uint256 amount) external; function burn(uint256 tokenId, uint256 amount) external; } \ No newline at end of file diff --git a/hardhat/contracts/MintPoint.sol b/hardhat/contracts/MintPoint.sol index d8c7f91..e17186e 100644 --- a/hardhat/contracts/MintPoint.sol +++ b/hardhat/contracts/MintPoint.sol @@ -4,11 +4,14 @@ pragma solidity ^0.8.19; import "@openzeppelin/contracts/utils/Base64.sol"; import {ERC1155Upgradeable, ERC1155SupplyUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155SupplyUpgradeable.sol"; import {AccessControlEnumerableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/metatx/MinimalForwarderUpgradeable.sol"; +import "./ERC2771ContextUpgradeable.sol"; import {IMintPoint} from "./IMintPoint.sol"; contract MintPoint is ERC1155SupplyUpgradeable, AccessControlEnumerableUpgradeable, + ERC2771ContextUpgradeable, IMintPoint { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); @@ -16,10 +19,11 @@ contract MintPoint is string public name; string public symbol; - function initialize() public initializer { + function initialize(MinimalForwarderUpgradeable _trustedForwarder) public initializer { __ERC1155_init(""); __ERC1155Supply_init(); __AccessControlEnumerable_init(); + __ERC2771Context_init(address(_trustedForwarder)); _grantRole(DEFAULT_ADMIN_ROLE, _msgSender()); _grantRole(MINTER_ROLE, _msgSender()); @@ -27,6 +31,7 @@ contract MintPoint is name = "MintPoint"; symbol = "MNT"; _register(); + _register(); } function supportsInterface( @@ -51,7 +56,7 @@ contract MintPoint is return super.isApprovedForAll(account, operator); } - function mint( + function mintByMinter( address to, uint256 tokenId, uint256 amount @@ -59,7 +64,17 @@ contract MintPoint is require(tokenId < tokenIds, "MintPoint: tokenId is not registered."); _mint(to, tokenId, amount, ""); - emit Mint(to, tokenId); + emit MintByMinter(to, tokenId); + } + + function mintForReferral(address to, uint256 amount) external { + require(amount < balanceOf(_msgSender(), 0), "MintPoint: not enough."); + + _burn(_msgSender(), 0, amount); + + _mint(to, 1, amount, ""); + + emit MintForReferral(_msgSender(), to, 1); } function register() external onlyRole(DEFAULT_ADMIN_ROLE) { @@ -82,4 +97,36 @@ contract MintPoint is ); _burn(_msgSender(), tokenId, amount); } + + function _msgSender() + internal + view + virtual + override(ContextUpgradeable, ERC2771ContextUpgradeable) + returns (address sender) + { + if (isTrustedForwarder(msg.sender)) { + // The assembly code is more direct than the Solidity version using `abi.decode`. + /// @solidity memory-safe-assembly + assembly { + sender := shr(96, calldataload(sub(calldatasize(), 20))) + } + } else { + return super._msgSender(); + } + } + + function _msgData() + internal + view + virtual + override(ContextUpgradeable, ERC2771ContextUpgradeable) + returns (bytes calldata) + { + if (isTrustedForwarder(msg.sender)) { + return msg.data[:msg.data.length - 20]; + } else { + return super._msgData(); + } + } } diff --git a/hardhat/scripts/helper/deploy.ts b/hardhat/scripts/helper/deploy.ts index 9a87017..f871446 100644 --- a/hardhat/scripts/helper/deploy.ts +++ b/hardhat/scripts/helper/deploy.ts @@ -117,11 +117,11 @@ export const deployForwarder = async () => { return deployedForwarder; }; -export const deployMintPoint = async () => { +export const deployMintPoint = async (params: { forwarderAddress: string }) => { const mintPoint = await ethers.getContractFactory("MintPoint"); const deployedMintPoint: MintPoint = (await upgrades.deployProxy( mintPoint, - [], + [params.forwarderAddress], { initializer: "initialize", }