diff --git a/packages/hyperverse-evm-mintpass/.gitignore b/packages/hyperverse-evm-mintpass/.gitignore new file mode 100644 index 00000000..14ccdfb0 --- /dev/null +++ b/packages/hyperverse-evm-mintpass/.gitignore @@ -0,0 +1,10 @@ +node_modules +.env +coverage +coverage.json +typechain +distribution + +#Hardhat files +cache +artifacts diff --git a/packages/hyperverse-evm-mintpass/CHANGELOG.md b/packages/hyperverse-evm-mintpass/CHANGELOG.md new file mode 100644 index 00000000..4f3df015 --- /dev/null +++ b/packages/hyperverse-evm-mintpass/CHANGELOG.md @@ -0,0 +1,23 @@ +# @decentology/hyperverse-ethereum-erc721 + +## 1.0.2 + +### Patch Changes + +- Milestone. Version bump +- Updated dependencies + - @decentology/hyperverse@1.0.10 + - @decentology/hyperverse-evm@1.0.10 + - @decentology/hyperverse-storage-skynet@1.0.9 + - @decentology/unstated-next@1.1.3 + +## 1.0.1 + +### Patch Changes + +- Milestone update. Added token and er721 modules +- Updated dependencies + - @decentology/unstated-next@1.1.1 + - @decentology/hyperverse@1.0.9 + - @decentology/hyperverse-ethereum@1.0.9 + - @decentology/hyperverse-storage-skynet@1.0.8 diff --git a/packages/hyperverse-evm-mintpass/README.md b/packages/hyperverse-evm-mintpass/README.md new file mode 100644 index 00000000..cb97640d --- /dev/null +++ b/packages/hyperverse-evm-mintpass/README.md @@ -0,0 +1,15 @@ +# Basic Sample Hardhat Project + +This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, a sample script that deploys that contract, and an example of a task implementation, which simply lists the available accounts. + +Try running some of the following tasks: + +```shell +npx hardhat accounts +npx hardhat compile +npx hardhat clean +npx hardhat test +npx hardhat node +node scripts/sample-script.js +npx hardhat help +``` diff --git a/packages/hyperverse-evm-mintpass/contracts.json b/packages/hyperverse-evm-mintpass/contracts.json new file mode 100644 index 00000000..119eece6 --- /dev/null +++ b/packages/hyperverse-evm-mintpass/contracts.json @@ -0,0 +1,30 @@ +{ + "metis": { + "testnet": { + "contractAddress": "0xACec20ad889Ba58Ec9d65AB0aA7C0e0D151222e0", + "factoryAddress": "0xb38d8C98646C7F07fdc0512e1DB9ee25BfE77F30" + }, + "mainnet": {} + }, + "avalanche": { + "testnet": { + "contractAddress": "0x995d701c0CaAeDA88DBF21727202F3a61AF01177", + "factoryAddress": "0xACec20ad889Ba58Ec9d65AB0aA7C0e0D151222e0" + }, + "mainnet": {} + }, + "ethereum": { + "testnet": { + "contractAddress": "0xe1a3efDbC4Cb1d69013b016cab589D323153E812", + "factoryAddress": "0x9ECA54f6b69B571798DC11FD57a989d437A286B3" + }, + "mainnet": {} + }, + "polygon": { + "testnet": { + "contractAddress": "0x1f6c0449EA114c4A5A542d20801650066Ef8767D", + "factoryAddress": "0x17f32a93376C24b4EFdAaeA72a1173606e7A2d1C" + }, + "mainnet": {} + } +} diff --git a/packages/hyperverse-evm-mintpass/contracts/MintPass.sol b/packages/hyperverse-evm-mintpass/contracts/MintPass.sol new file mode 100644 index 00000000..c10d7ed2 --- /dev/null +++ b/packages/hyperverse-evm-mintpass/contracts/MintPass.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import './hyperverse/IHyperverseModule.sol'; +import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract MintPass is ERC1155, Ownable, IHyperverseModule { + string public _name; + string public _symbol; + + uint256 public tokenCounter; + bool public initialized; + + mapping(uint => string) public tokenURI; + + // Account used to deploy contract + address public immutable contractOwner; + + //stores the tenant owner + address private tenantOwner; + + constructor() ERC1155("ipfs://ipfs/") { + contractOwner = msg.sender; + + metadata = ModuleMetadata( + 'Token', + Author(msg.sender, 'https://externallink.net'), + '0.0.1', + 3479831479814, + 'https://externalLink.net' + ); + } + + function init( + string memory name_, + string memory symbol_, + address _tenant + ) external { + require(!initialized, 'Already initialized the state.'); + _name = name_; + _symbol = symbol_; + initialized = true; + tenantOwner = _tenant; + tokenCounter = 0; + } + + function mint(address _to, uint _id, uint _amount) external { + require(msg.sender == tenantOwner, 'Only the Tenant owner can mint an NFT'); + _mint(_to, _id, _amount, ""); + } + + function mintBatch(address _to, uint[] memory _ids, uint[] memory _amounts) external { + require(msg.sender == tenantOwner, 'Only the Tenant owner can mint an NFT'); + _mintBatch(_to, _ids, _amounts, ""); + } + + function burn(uint _id, uint _amount) external { + _burn(msg.sender, _id, _amount); + } + + function burnBatch(uint[] memory _ids, uint[] memory _amounts) external { + _burnBatch(msg.sender, _ids, _amounts); + } + + function burnForMint(address _from, uint[] memory _burnIds, uint[] memory _burnAmounts, uint[] memory _mintIds, uint[] memory _mintAmounts) external onlyOwner { + _burnBatch(_from, _burnIds, _burnAmounts); + _mintBatch(_from, _mintIds, _mintAmounts, ""); + } + + function setURI(uint _id, string memory _uri) external { + require(msg.sender == tenantOwner, 'Only the Tenant owner can mint an NFT'); + tokenURI[_id] = _uri; + emit URI(_uri, _id); + } + + function uri(uint _id) public override view returns (string memory) { + return tokenURI[_id]; + } + + function name() public view returns (string memory) { + return _name; + } + + function symbol() public view returns (string memory) { + return _symbol; + } + +} \ No newline at end of file diff --git a/packages/hyperverse-evm-mintpass/contracts/MintPassFactory.sol b/packages/hyperverse-evm-mintpass/contracts/MintPassFactory.sol new file mode 100644 index 00000000..ee07f3a6 --- /dev/null +++ b/packages/hyperverse-evm-mintpass/contracts/MintPassFactory.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; +pragma experimental ABIEncoderV2; + +import './hyperverse/CloneFactory.sol'; +import './hyperverse/IHyperverseModule.sol'; +import './MintPass.sol'; + +/** + * @dev Clone Factory Implementation for ERC20 Token + */ + +contract MintPassFactory is CloneFactory { + /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ S T A T E @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + struct Tenant { + MintPass mintpass; + address owner; + } + + mapping(address => Tenant) public tenants; + + address public immutable masterContract; + address private hyperverseAdmin = 0xD847C7408c48b6b6720CCa75eB30a93acbF5163D; + + /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ M O D I F I E R S @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + modifier isOwner(address _tenant) { + require( + tenants[_tenant].owner == msg.sender, + 'The calling address is not an owner of a tenant' + ); + _; + } + + modifier isAllowedToCreateInstance(address _tenant) { + require( + msg.sender == _tenant || msg.sender == hyperverseAdmin, + 'Please use a valid address to create an instance' + ); + _; + } + + /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ E V E N T S @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ C O N S T R U C T O R @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + constructor(address _masterContract) { + masterContract = _masterContract; + } + + /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ F U N C T I O N S @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + function createInstance(string memory name, string memory symbol) external { + address tenant = msg.sender; + MintPass mintpass = MintPass(createClone(masterContract)); + + //initializing tenant state of clone + mintpass.init(name, symbol, tenant); + + //set Tenant data + Tenant storage newTenant = tenants[tenant]; + newTenant.mintpass = mintpass; + newTenant.owner = tenant; + } + + function getProxy(address _tenant) public view returns (MintPass) { + return tenants[_tenant].mintpass; + } +} diff --git a/packages/hyperverse-evm-mintpass/contracts/hyperverse/CloneFactory.sol b/packages/hyperverse-evm-mintpass/contracts/hyperverse/CloneFactory.sol new file mode 100644 index 00000000..7893fe82 --- /dev/null +++ b/packages/hyperverse-evm-mintpass/contracts/hyperverse/CloneFactory.sol @@ -0,0 +1,52 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/* +The MIT License (MIT) +Copyright (c) 2018 Murray Software, LLC. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +//solhint-disable max-line-length +//solhint-disable no-inline-assembly + +contract CloneFactory { + function createClone(address target) internal returns (address result) { + bytes20 targetBytes = bytes20(target); + assembly { + let clone := mload(0x40) + mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) + mstore(add(clone, 0x14), targetBytes) + mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) + result := create(0, clone, 0x37) + } + } + + function isClone(address target, address query) internal view returns (bool result) { + bytes20 targetBytes = bytes20(target); + assembly { + let clone := mload(0x40) + mstore(clone, 0x363d3d373d3d3d363d7300000000000000000000000000000000000000000000) + mstore(add(clone, 0xa), targetBytes) + mstore(add(clone, 0x1e), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) + + let other := add(clone, 0x40) + extcodecopy(query, other, 0, 0x2d) + result := and(eq(mload(clone), mload(other)), eq(mload(add(clone, 0xd)), mload(add(other, 0xd)))) + } + } +} diff --git a/packages/hyperverse-evm-mintpass/contracts/hyperverse/IHyperverseModule.sol b/packages/hyperverse-evm-mintpass/contracts/hyperverse/IHyperverseModule.sol new file mode 100644 index 00000000..c5dea23c --- /dev/null +++ b/packages/hyperverse-evm-mintpass/contracts/hyperverse/IHyperverseModule.sol @@ -0,0 +1,26 @@ +/** +## The Decentology Smart Module standard on Ethereum +## `IHyperverseModule` interface +*/ + +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.0; + +abstract contract IHyperverseModule { + ModuleMetadata public metadata; + address private owner; + + struct ModuleMetadata { + bytes title; + Author author; + bytes version; + uint64 publishedAt; + bytes externalLink; + } + + struct Author { + address authorAddress; + string externalLink; + } +} diff --git a/packages/hyperverse-evm-mintpass/hardhat.config.js b/packages/hyperverse-evm-mintpass/hardhat.config.js new file mode 100644 index 00000000..4fc34a63 --- /dev/null +++ b/packages/hyperverse-evm-mintpass/hardhat.config.js @@ -0,0 +1,45 @@ +require('dotenv').config(); +require('@nomiclabs/hardhat-waffle'); + +// This is a sample Hardhat task. To learn how to create your own go to +// https://hardhat.org/guides/create-task.html +task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => { + const accounts = await hre.ethers.getSigners(); + + for (const account of accounts) { + console.log(account.address); + } +}); + +// You need to export an object to set up your config +// Go to https://hardhat.org/config/ to learn more + +/** + * @type import('hardhat/config').HardhatUserConfig + */ + +const accounts = process.env.NEXT_PRIVATE_KEY !== undefined ? [process.env.NEXT_PRIVATE_KEY] : []; + +module.exports = { + solidity: '0.8.4', + defaultNetwork: 'hardhat', + networks: { + hardhat: {}, + ethereum: { + url: `https://rinkeby.infura.io/v3/${process.env.NEXT_PUBLIC_INFURA_API_KEY}`, + accounts, + }, + metis: { + url: 'https://stardust.metis.io/?owner=588', + accounts, + }, + avalanche: { + url: 'https://api.avax-test.network/ext/bc/C/rpc', + accounts, + }, + polygon: { + url: 'https://rpc-mumbai.maticvigil.com', + accounts, + }, + }, +}; diff --git a/packages/hyperverse-evm-mintpass/index.tsx b/packages/hyperverse-evm-mintpass/index.tsx new file mode 100644 index 00000000..6c52417c --- /dev/null +++ b/packages/hyperverse-evm-mintpass/index.tsx @@ -0,0 +1 @@ +export * from "./source"; \ No newline at end of file diff --git a/packages/hyperverse-evm-mintpass/package.json b/packages/hyperverse-evm-mintpass/package.json new file mode 100644 index 00000000..acc26e2c --- /dev/null +++ b/packages/hyperverse-evm-mintpass/package.json @@ -0,0 +1,53 @@ +{ + "name": "@decentology/hyperverse-evm-mintpass", + "version": "1.0.2", + "source": "./source/index.ts", + "types": "./distribution/index.d.ts", + "main": "./distribution/index.js", + "license": "MIT", + "scripts": { + "test": "hardhat test", + "build": "parcel build", + "clean": "rimraf ./distribution", + "compile": "hardhat compile", + "deploy": "run-p deploy-ethereum deploy-metis deploy-avalanche deploy-polygon", + "deploy-ethereum": "hardhat run scripts/deploy.js --network ethereum ", + "deploy-metis": "hardhat run scripts/deploy.js --network metis", + "deploy-avalanche": "hardhat run scripts/deploy.js --network avalanche", + "deploy-polygon": "hardhat run scripts/deploy.js --network polygon", + "lint": "tsc --noEmit" + }, + "publishConfig": { + "access": "public" + }, + "peerDependencies": { + "react": "^17.0.2" + }, + "files": [ + "distribution", + "utils" + ], + "dependencies": { + "@decentology/hyperverse": "^1.0.10", + "@decentology/hyperverse-evm": "^1.0.10", + "@decentology/hyperverse-storage-skynet": "^1.0.9", + "@decentology/unstated-next": "^1.1.3", + "@openzeppelin/contracts": "^4.5.0", + "ethers": "^5.5.3", + "react-query": "^3.34.7", + "react-use": "^17.3.2", + "skynet-js": "^4.0.23-beta" + }, + "devDependencies": { + "@decentology/config": "^1.0.1", + "@nomiclabs/hardhat-ethers": "^2.0.4", + "@nomiclabs/hardhat-waffle": "^2.0.2", + "chai": "^4.3.4", + "ethereum-waffle": "^3.4.0", + "fs-extra": "^10.0.1", + "hardhat": "^2.8.3", + "npm-run-all": "^4.1.5", + "parcel": "^2.2.1", + "rimraf": "^3.0.2" + } +} diff --git a/packages/hyperverse-evm-mintpass/scripts/deploy.js b/packages/hyperverse-evm-mintpass/scripts/deploy.js new file mode 100644 index 00000000..aedb572c --- /dev/null +++ b/packages/hyperverse-evm-mintpass/scripts/deploy.js @@ -0,0 +1,44 @@ +// We require the Hardhat Runtime Environment explicitly here. This is optional +// but useful for running the script in a standalone fashion through `node