diff --git a/hardhat/contracts/IERC1155MetadataURIView.sol b/hardhat/contracts/IERC1155MetadataURIView.sol new file mode 100644 index 00000000..c89fec6c --- /dev/null +++ b/hardhat/contracts/IERC1155MetadataURIView.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol) + +pragma solidity ^0.8.9; + +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +/** + * @dev Required interface of an ERC-1155 compliant contract, as defined in the + * https://eips.ethereum.org/EIPS/eip-1155[ERC]. + */ +interface IERC1155MetadataURIView is IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); + /** + * @dev Returns the value of tokens of token type `id` owned by `account`. + */ + function balanceOf(address account, uint256 id) external view returns (uint256); + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. + * + * Requirements: + * + * - `accounts` and `ids` must have the same length. + */ + function balanceOfBatch( + address[] calldata accounts, + uint256[] calldata ids + ) external view returns (uint256[] memory); + + /** + * @dev Returns the URI for token type `id`. + * + * If the `\{id\}` substring is present in the URI, it must be replaced by + * clients with the actual token type ID. + */ + function uri(uint256 id) external view returns (string memory); + + /** + * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. + * Used in batch transfers. + * @param idsLength Length of the array of token identifiers + * @param valuesLength Length of the array of token amounts + */ + error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); +} \ No newline at end of file diff --git a/hardhat/contracts/IMintNFT.sol b/hardhat/contracts/IMintNFT.sol index f5eab4be..44e264be 100644 --- a/hardhat/contracts/IMintNFT.sol +++ b/hardhat/contracts/IMintNFT.sol @@ -99,4 +99,15 @@ interface IMintNFT { ) external; function transferOwnership(address newOwner) external; + + function isHoldingEventNFTByAddress( + address _addr, + uint256 _eventId + ) external view returns (bool); + + function getNFTAttributeRecordsByEventId( + uint256 _eventId, + uint256 _limit, + uint256 _offset + ) external view returns (NFTAttribute[] memory); } diff --git a/hardhat/contracts/MintRallyViewer.sol b/hardhat/contracts/MintRallyViewer.sol new file mode 100644 index 00000000..32f94e55 --- /dev/null +++ b/hardhat/contracts/MintRallyViewer.sol @@ -0,0 +1,75 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import {IERC1155MetadataURI} from "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol"; +import {ContextUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import {ERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import {IERC1155MetadataURIView} from "./IERC1155MetadataURIView.sol"; +import {IMintNFT} from "./IMintNFT.sol"; +import {IEventManager} from "./IEvent.sol"; + +contract MintRallyViewer is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155MetadataURIView, OwnableUpgradeable { + address private mintManagerAddr; + address private eventManagerAddr; + + // struct NFTAttribute { + // string metaDataURL; + // uint256 requiredParticipateCount; + // } + + function initialize( + address _owner, + address _mintManagerAddr, + address _eventManagerAddr + ) public initializer { + __Context_init(); + __ERC165_init(); + __Ownable_init(); + _transferOwnership(_owner); + mintManagerAddr = _mintManagerAddr; + eventManagerAddr = _eventManagerAddr; + } + + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC1155MetadataURIView) returns (bool) { + return + interfaceId == type(IERC1155).interfaceId || + interfaceId == type(IERC1155MetadataURI).interfaceId || + super.supportsInterface(interfaceId); + } + + function balanceOf(address account, uint256 id) external view override returns (uint256) { + return _balanceOf(account, id); + } + + function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view override returns (uint256[] memory) { + if (accounts.length != ids.length) { + revert ERC1155InvalidArrayLength(ids.length, accounts.length); + } + uint256[] memory batchBalances = new uint256[](accounts.length); + + for (uint256 i = 0; i < accounts.length; ++i) { + batchBalances[i] = _balanceOf(accounts[i], ids[i]); + } + + return batchBalances; + } + + function _balanceOf(address account, uint256 id) internal view returns (uint256) { + bool isHolidingEventNFT = IMintNFT(mintManagerAddr).isHoldingEventNFTByAddress(account, id); + if (isHolidingEventNFT) { + return 1; + } else { + return 0; + } + } + + function uri(uint256 id) external view override returns (string memory) { + IMintNFT.NFTAttribute[] memory attributes = IMintNFT(mintManagerAddr).getNFTAttributeRecordsByEventId(id, 1, 0); + + return attributes[0].metaDataURL; + } +} \ No newline at end of file diff --git a/hardhat/scripts/deploy_stg.ts b/hardhat/scripts/deploy_stg.ts index bd467c58..a929b97c 100644 --- a/hardhat/scripts/deploy_stg.ts +++ b/hardhat/scripts/deploy_stg.ts @@ -39,6 +39,7 @@ async function main() { const deployedMintNFT: any = await upgrades.deployProxy( MintNFTFactory, [ + "0xc5952da2d393d3421D56bd5FBCac1F8a3df40567", forwarder.address, secretPhraseVerifier.address, operationController.address, @@ -54,6 +55,7 @@ async function main() { const deployedEventManager: any = await upgrades.deployProxy( EventManagerFactory, [ + "0xc5952da2d393d3421D56bd5FBCac1F8a3df40567", process.env.MUMBAI_RELAYER_ADDRESS, 250000, 1000000, diff --git a/hardhat/scripts/deploy_viewer.ts b/hardhat/scripts/deploy_viewer.ts new file mode 100644 index 00000000..f753fcc0 --- /dev/null +++ b/hardhat/scripts/deploy_viewer.ts @@ -0,0 +1,36 @@ +import { ethers, upgrades } from "hardhat"; +import { + MintRallyViewer, +} from "../typechain"; + +async function main() { + const ownerAddr = "0xc5952da2d393d3421D56bd5FBCac1F8a3df40567"; + const mintNftAddr = "0x225B131690c2648EE58E7684e613C07D01A1B946"; + const eventManagerAddr = "0x71BAfD0812b483054b7e0c66dB428eB4AA54E13C"; + + let mintRallyViewer: MintRallyViewer; + + const MintRallyViewerFactory = await ethers.getContractFactory("MintRallyViewer"); + const deployedMintRallyViewer: any = await upgrades.deployProxy( + MintRallyViewerFactory, + [ + ownerAddr, + mintNftAddr, + eventManagerAddr, + ], + { + initializer: "initialize", + } + ); + mintRallyViewer = deployedMintRallyViewer; + await mintRallyViewer.deployed(); + + console.log("mintNFT address:", mintNftAddr); + console.log("eventManager address:", eventManagerAddr, "\n"); + console.log("mintRallyViewer address:", mintRallyViewer.address); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/hardhat/scripts/upgrades/upgrade_viewer.ts b/hardhat/scripts/upgrades/upgrade_viewer.ts new file mode 100644 index 00000000..df0f1478 --- /dev/null +++ b/hardhat/scripts/upgrades/upgrade_viewer.ts @@ -0,0 +1,30 @@ +import { ethers, upgrades } from "hardhat"; +import { + MintRallyViewer, +} from "../../typechain"; + +async function main() { + const ownerAddr = "0xc5952da2d393d3421D56bd5FBCac1F8a3df40567"; + const mintNftAddr = "0x225B131690c2648EE58E7684e613C07D01A1B946"; + const eventManagerAddr = "0x71BAfD0812b483054b7e0c66dB428eB4AA54E13C"; + const mintRallyViewerAddr = "0x283024996Bab0364A5Daa7a81A87eAF645a70eD6"; + + let mintRallyViewer: MintRallyViewer; + + const MintRallyViewerFactory = await ethers.getContractFactory("MintRallyViewer"); + const deployedMintRallyViewer: any = await upgrades.upgradeProxy( + mintRallyViewerAddr, + MintRallyViewerFactory + ); + mintRallyViewer = deployedMintRallyViewer; + await mintRallyViewer.deployed(); + + console.log("mintNFT address:", mintNftAddr); + console.log("eventManager address:", eventManagerAddr, "\n"); + console.log("mintRallyViewer address:", mintRallyViewer.address); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +});