// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 몇으로 할까 import "../contracts/utils/cryptography/ECDSA.sol"; import "../contracts/utils/cryptography/draft-EIP712.sol"; import "../contracts/utils/math/SafeMath.sol"; interface IMetaRareERC721Collection { function mint(address, uint256) external; function hasRole(bytes32, address) external view returns (bool); function ownerOf(uint256 tokenId) external view returns (address); function transferFrom(address from, address to, uint256 tokenId) external; function transferOnlyOperator(address, address, uint256) external; } interface IMetaRareERC1155Collection { function owner() external view returns (address); function exists(uint256) external view returns (bool); function createByOperator(address, uint256, uint256, string memory, bytes memory) external returns (uint256); function safeTransferFrom(address, address, uint256, uint256, bytes memory) external; function balanceOf(address, uint256) external view returns (uint256); function transferOnlyOperator(address, address, uint256, uint256) external; } interface IERC20 { function transfer(address to, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool); function balanceOf(address owner) external view returns (uint256); } contract MetaRareOperator is EIP712 { using SafeMath for uint256; mapping (uint256 => address) public creators; mapping (address => mapping(uint256 => address)) public creatorsWithinCollection; mapping (address => mapping(uint256 => uint256)) public creationTaxRate; struct NFTVoucher { address signer; address tokenAddress; uint256 tokenType; uint256 tokenId; address assetAddress; uint256 price; uint256 balance; uint256 totalBalance; uint256 creationTax; uint256 treasuryTax; address treasuryAddress; string uri; } constructor() EIP712("METARARE","1"){ } bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); address payable private _treasury; function recoverAddress(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s) public pure returns(address) { return ecrecover(msgHash, v, r, s); } function excuteMintingOrderWithERC721Collection(NFTVoucher calldata voucher, bytes32 hash, uint8 v, bytes32 r, bytes32 s) public payable { address signer = recoverAddress(hash, v,r,s); require(signer == voucher.signer, "Invalid signature"); creators[voucher.tokenId] = signer; creatorsWithinCollection[voucher.tokenAddress][voucher.tokenId] = creators[voucher.tokenId]; creationTaxRate[voucher.tokenAddress][voucher.tokenId] = voucher.creationTax; _treasury = payable(voucher.treasuryAddress); address ERC721TokenAddress = voucher.tokenAddress; IMetaRareERC721Collection _ERC721Collection = IMetaRareERC721Collection(ERC721TokenAddress); require(_ERC721Collection.hasRole(MINTER_ROLE, signer), "Signature invalid or unauthorized"); if (voucher.assetAddress == address(0)) { require(msg.value >= voucher.price, "No money"); address payable targetAddress; targetAddress = payable(signer); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_seller = voucher.price.sub(value_treasury); _treasury.transfer(value_treasury); targetAddress.transfer(value_seller); } else { IERC20 tokenContract = IERC20(voucher.assetAddress); require(tokenContract.balanceOf(msg.sender) >= voucher.price, "No money"); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_seller = voucher.price.sub(value_treasury); tokenContract.transferFrom(msg.sender, _treasury, value_treasury); tokenContract.transferFrom(msg.sender, signer, value_seller); } _ERC721Collection.mint(msg.sender, voucher.tokenId); } function excuteMintingOrderWithERC721MetaRareCollection(NFTVoucher calldata voucher, bytes32 hash, uint8 v, bytes32 r, bytes32 s) public payable { address signer = recoverAddress(hash, v,r,s); require(signer == voucher.signer, "Invalid signature"); creators[voucher.tokenId] = signer; creatorsWithinCollection[voucher.tokenAddress][voucher.tokenId] = creators[voucher.tokenId]; creationTaxRate[voucher.tokenAddress][voucher.tokenId] = voucher.creationTax; _treasury = payable(voucher.treasuryAddress); address ERC721TokenAddress = voucher.tokenAddress; IMetaRareERC721Collection _ERC721Collection = IMetaRareERC721Collection(ERC721TokenAddress); if (voucher.assetAddress == address(0)) { require(msg.value >= voucher.price, "No money"); address payable targetAddress; targetAddress = payable(signer); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_seller = voucher.price.sub(value_treasury); _treasury.transfer(value_treasury); targetAddress.transfer(value_seller); } else { IERC20 tokenContract = IERC20(voucher.assetAddress); require(tokenContract.balanceOf(msg.sender) >= voucher.price, "No money"); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_seller = voucher.price.sub(value_treasury); tokenContract.transferFrom(msg.sender, _treasury, value_treasury); tokenContract.transferFrom(msg.sender, signer, value_seller); } _ERC721Collection.mint(msg.sender, voucher.tokenId); } function excuteTransferOrderWithERC721Collection(NFTVoucher calldata voucher, bytes32 hash, uint8 v, bytes32 r, bytes32 s) public payable { address signer = recoverAddress(hash, v,r,s); require(signer == voucher.signer, "Invalid signature"); _treasury = payable(voucher.treasuryAddress); address ERC721TokenAddress = voucher.tokenAddress; IMetaRareERC721Collection _ERC721Collection = IMetaRareERC721Collection(ERC721TokenAddress); require(_ERC721Collection.ownerOf(voucher.tokenId) == signer, "Signature invalid or unauthorized"); if (voucher.assetAddress == address(0)) { require(msg.value >= voucher.price, "No money"); address payable targetAddress; targetAddress = payable(signer); address payable creatorAddress; creatorAddress = payable(creatorsWithinCollection[voucher.tokenAddress][voucher.tokenId]); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_creator = voucher.price.mul(voucher.creationTax).div(10000); uint256 value_seller = voucher.price; value_seller = value_seller.sub(value_treasury).sub(value_creator); _treasury.transfer(value_treasury); creatorAddress.transfer(value_creator); targetAddress.transfer(value_seller); } else { IERC20 tokenContract = IERC20(voucher.assetAddress); require(tokenContract.balanceOf(msg.sender) >= voucher.price, "No money"); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_creator = voucher.price.mul(voucher.creationTax).div(10000); uint256 value_seller = voucher.price.sub(value_treasury).sub(value_creator); tokenContract.transferFrom(msg.sender, _treasury, value_treasury); address _creator = creatorsWithinCollection[voucher.tokenAddress][voucher.tokenId]; tokenContract.transferFrom(msg.sender, _creator, value_creator); tokenContract.transferFrom(msg.sender, signer, value_seller); } _ERC721Collection.transferOnlyOperator(signer, msg.sender, voucher.tokenId); } function excuteMintingOrderWithERC1155Collection(NFTVoucher calldata voucher, bytes32 hash, uint8 v, bytes32 r, bytes32 s) public payable { address signer = recoverAddress(hash, v,r,s); require(signer == voucher.signer, "Invalid signature"); creators[voucher.tokenId] = signer; creatorsWithinCollection[voucher.tokenAddress][voucher.tokenId] = creators[voucher.tokenId]; creationTaxRate[voucher.tokenAddress][voucher.tokenId] = voucher.creationTax; _treasury = payable(voucher.treasuryAddress); address ERC1155TokenAddress = voucher.tokenAddress; IMetaRareERC1155Collection _ERC1155Collection = IMetaRareERC1155Collection(ERC1155TokenAddress); require(_ERC1155Collection.owner() == signer, "Signature invalid or unauthorized"); if (voucher.assetAddress == address(0)) { require(msg.value >= voucher.price, "No money"); address payable targetAddress; targetAddress = payable(signer); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_seller = voucher.price.sub(value_treasury); _treasury.transfer(value_treasury); targetAddress.transfer(value_seller); } else { IERC20 tokenContract = IERC20(voucher.assetAddress); require(tokenContract.balanceOf(msg.sender) >= voucher.price, "No money"); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_seller = voucher.price.sub(value_treasury); tokenContract.transferFrom(msg.sender, _treasury, value_treasury); tokenContract.transferFrom(msg.sender, signer, value_seller); } if(!_ERC1155Collection.exists(voucher.tokenId)) { _ERC1155Collection.createByOperator(signer, voucher.tokenId, voucher.totalBalance, voucher.uri, ""); _ERC1155Collection.safeTransferFrom(signer, msg.sender, voucher.tokenId, voucher.balance, ""); } else { _ERC1155Collection.safeTransferFrom(signer, msg.sender, voucher.tokenId, voucher.balance, ""); } } function excuteMintingOrderWithERC1155MetaRareCollection(NFTVoucher calldata voucher, bytes32 hash, uint8 v, bytes32 r, bytes32 s) public payable { address signer = recoverAddress(hash, v,r,s); require(signer == voucher.signer, "Invalid signature"); creators[voucher.tokenId] = signer; creatorsWithinCollection[voucher.tokenAddress][voucher.tokenId] = creators[voucher.tokenId]; creationTaxRate[voucher.tokenAddress][voucher.tokenId] = voucher.creationTax; _treasury = payable(voucher.treasuryAddress); address ERC1155TokenAddress = voucher.tokenAddress; IMetaRareERC1155Collection _ERC1155Collection = IMetaRareERC1155Collection(ERC1155TokenAddress); if (voucher.assetAddress == address(0)) { require(msg.value >= voucher.price, "No money"); address payable targetAddress; targetAddress = payable(signer); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_seller = voucher.price.sub(value_treasury); _treasury.transfer(value_treasury); targetAddress.transfer(value_seller); } else { IERC20 tokenContract = IERC20(voucher.assetAddress); require(tokenContract.balanceOf(msg.sender) >= voucher.price, "No money"); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_seller = voucher.price.sub(value_treasury); tokenContract.transferFrom(msg.sender, _treasury, value_treasury); tokenContract.transferFrom(msg.sender, signer, value_seller); } if(!_ERC1155Collection.exists(voucher.tokenId)) { _ERC1155Collection.createByOperator(signer, voucher.tokenId, voucher.totalBalance, voucher.uri, ""); _ERC1155Collection.transferOnlyOperator(signer, msg.sender, voucher.tokenId, voucher.balance); } else { _ERC1155Collection.transferOnlyOperator(signer, msg.sender, voucher.tokenId, voucher.balance); } } function excuteTransferOrderWithERC1155Collection(NFTVoucher calldata voucher, bytes32 hash, uint8 v, bytes32 r, bytes32 s) public payable { address signer = recoverAddress(hash, v,r,s); require(signer == voucher.signer, "Invalid signature"); _treasury = payable(voucher.treasuryAddress); address ERC1155TokenAddress = voucher.tokenAddress; IMetaRareERC1155Collection _ERC1155Collection = IMetaRareERC1155Collection(ERC1155TokenAddress); require(_ERC1155Collection.balanceOf(signer, voucher.tokenId) >= voucher.balance, "Signature invalid or unauthorized"); if (voucher.assetAddress == address(0)) { require(msg.value >= voucher.price, "No money"); address payable targetAddress; targetAddress = payable(signer); address payable creatorAddress; creatorAddress = payable(creatorsWithinCollection[voucher.tokenAddress][voucher.tokenId]); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_creator = voucher.price; value_creator = value_creator.mul(voucher.creationTax).div(10000); uint256 value_seller = voucher.price; value_seller = value_seller.sub(value_treasury).sub(value_creator); _treasury.transfer(value_treasury); creatorAddress.transfer(value_creator); targetAddress.transfer(value_seller); } else { IERC20 tokenContract = IERC20(voucher.assetAddress); require(tokenContract.balanceOf(msg.sender) >= voucher.price, "No money"); uint256 value_treasury = voucher.price.mul(voucher.treasuryTax).div(10000); uint256 value_creator = voucher.price.mul(voucher.creationTax).div(10000); uint256 value_seller = voucher.price.sub(value_treasury).sub(value_creator); address _creator = creatorsWithinCollection[voucher.tokenAddress][voucher.tokenId]; tokenContract.transferFrom(msg.sender, _treasury, value_treasury); tokenContract.transferFrom(msg.sender, _creator, value_creator); tokenContract.transferFrom(msg.sender, signer, value_seller); } _ERC1155Collection.transferOnlyOperator(signer, msg.sender, voucher.tokenId, voucher.balance); } }