├── .gas-snapshot ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .gitmodules ├── .husky └── pre-commit ├── .prettierignore ├── CODEOWNER ├── COPYING ├── README.md ├── audit └── Certik-Audit-CyberConnect.pdf ├── config ├── .solhint.json └── .solhintignore ├── docs ├── README.md ├── abi │ ├── CollectDisallowedMw.json │ ├── CollectFlexPaidMw.json │ ├── CollectLimitedTimePaidMw.json │ ├── CollectMerkleDropMw.json │ ├── CollectOnlySubscribedMw.json │ ├── CollectPaidMw.json │ ├── CollectPermissionMw.json │ ├── CollectPermissionPaidMw.json │ ├── CyberBoxNFT.json │ ├── CyberEngine.json │ ├── CyberGrandNFT.json │ ├── CyberVault.json │ ├── EssenceNFT.json │ ├── FrameNFT.json │ ├── Link3ProfileDescriptor.json │ ├── MBNFT.json │ ├── MiniShardNFT.json │ ├── PaidCollectMw.json │ ├── PaidSubscribeMw.json │ ├── PermissionedFeeCreationMw.json │ ├── ProfileNFT.json │ ├── RelationshipChecker.json │ ├── RolesAuthority.json │ ├── SignaturePermissionEssenceMw.json │ ├── StableFeeCreationMw.json │ ├── SubscribeDisallowedMw.json │ ├── SubscribeNFT.json │ ├── SubscribeOnlyOnceMw.json │ ├── SubscribePaidMw.json │ └── Treasury.json ├── deploy │ ├── bnb-56 │ │ └── contract.md │ ├── bnbt-97 │ │ └── contract.md │ ├── goerli-5 │ │ └── contract.md │ └── polygon-137 │ │ └── contract.md ├── template │ ├── anvil-31337 │ │ └── bafkreifjwei5tuvh5zjk7r6ti4wt7eon7dwnobchdinfmdzqhl2l2lrgve │ ├── bnb-56 │ │ └── bafkreiblu7mqgd43bmenvsyfcp33pkrtjyc52ofwectc2257uicatn6vzm │ ├── bnbt-97 │ │ └── bafkreigqqa3tkzqkl7bjylkya5nf5qsyyjcunsp4ix525icn5nycf7nw2m │ ├── goerli-5 │ │ └── bafkreic7ur7evrpy45md2xpth3zvy4mjcczzodjg7xciupty6dvmliye6i │ ├── mainnet-1 │ │ └── bafkreigjfjobgbh6voodb4z4u3nfpuchwb5usolon6i67kecelki2uzb6y │ ├── nova-42170 │ │ └── bafkreiaiurmd4gpnu4nqjlddbt2r57ipshpsz77bf7mybun36psiggrbui │ ├── polygon-137 │ │ └── bafkreiebcj2it5hirwrfbfhjlwr7pxbjqvojtxht4bcjhvvnjxqwomqqly │ └── rinkeby-4 │ │ └── bafkreifq5vu6gl4q4c5fb23m5w3wyijumonpfb7dki7eodx2222ogfb3lu └── test │ └── qrcode.md ├── foundry.toml ├── hardhat-scripts └── deployActions.ts ├── hardhat.config.ts ├── misc ├── cyberbox │ └── metadata.json ├── post_deploy.ts ├── pre_deploy.js ├── qrcode │ ├── QRSVG.t.sol.template │ ├── gen-html.js │ ├── gen-sol.js │ ├── puppet.js │ └── qr-test.html.template └── set_animation_url.ts ├── package.json ├── remappings.txt ├── script ├── AllowCurrency.s.sol ├── Deploy.s.sol ├── DeployAction.s.sol ├── DeployBox.s.sol ├── DeployChecker.s.sol ├── DeployCreate2Deployer.s.sol ├── DeployCyberToken.s.sol ├── DeployFrame.s.sol ├── DeployGrand.s.sol ├── DeployMB.s.sol ├── DeployMiddleware.s.sol ├── DeployMiniShard.s.sol ├── DeployNamespace.s.sol ├── DeployPermissionless.s.sol ├── DeployTimeLock.s.sol ├── DeployVault.s.sol ├── RegisterProfile.s.sol ├── SetAniURL.s.sol ├── SetAnimationURLV3.s.sol ├── SetFeeCreationMw.s.sol ├── SetProfileMw.s.sol ├── SetSigner.s.sol ├── SetStableFeeMw.s.sol ├── Tmp.s.sol ├── animation_url │ ├── anvil-31337 │ │ ├── SetAnimationURL.s.sol │ │ └── SetAnimationURL.s.sol.template │ ├── bnb-56 │ │ ├── SetAnimationURL.s.sol │ │ └── SetAnimationURL.s.sol.template │ ├── bnbt-97 │ │ ├── SetAnimationURL.s.sol │ │ └── SetAnimationURL.s.sol.template │ ├── goerli-5 │ │ ├── SetAnimationURL.s.sol │ │ └── SetAnimationURL.s.sol.template │ ├── mainnet-1 │ │ ├── SetAnimationURL.s.sol │ │ └── SetAnimationURL.s.sol.template │ ├── nova-42170 │ │ ├── SetAnimationURL.s.sol │ │ └── SetAnimationURL.s.sol.template │ ├── polygon-137 │ │ ├── SetAnimationURL.s.sol │ │ └── SetAnimationURL.s.sol.template │ └── rinkeby-4 │ │ ├── SetAnimationURL.s.sol │ │ └── SetAnimationURL.s.sol.template ├── libraries │ ├── DeployNamespace.sol │ ├── DeploySetting.sol │ └── LibDeploy.sol └── mainnet-upgrades │ └── 2022-7-18 │ └── UpgradeProfileMiddleware.s.sol ├── slither.config.json ├── src ├── base │ ├── CyberNFTBase.sol │ ├── CyberNFTBaseFlex.sol │ └── EIP712.sol ├── core │ ├── CyberEngine.sol │ ├── EssenceNFT.sol │ ├── ProfileNFT.sol │ └── SubscribeNFT.sol ├── dependencies │ ├── openzeppelin │ │ ├── Pausable.sol │ │ └── ReentrancyGuard.sol │ └── solmate │ │ ├── Auth.sol │ │ ├── ERC721.sol │ │ ├── Owned.sol │ │ └── RolesAuthority.sol ├── deployer │ ├── Create2Deployer.sol │ ├── EssenceDeployer.sol │ ├── ProfileDeployer.sol │ └── SubscribeDeployer.sol ├── interfaces │ ├── ICyberBox.sol │ ├── ICyberBoxEvents.sol │ ├── ICyberEngine.sol │ ├── ICyberEngineEvents.sol │ ├── ICyberGrand.sol │ ├── ICyberGrandEvents.sol │ ├── ICyberNFTBase.sol │ ├── IEssenceDeployer.sol │ ├── IEssenceMiddleware.sol │ ├── IEssenceNFT.sol │ ├── IEssenceNFTEvents.sol │ ├── IMB.sol │ ├── IMBEvents.sol │ ├── IProfileDeployer.sol │ ├── IProfileMiddleware.sol │ ├── IProfileNFT.sol │ ├── IProfileNFTDescriptor.sol │ ├── IProfileNFTDescriptorV2.sol │ ├── IProfileNFTEvents.sol │ ├── ISubscribeDeployer.sol │ ├── ISubscribeMiddleware.sol │ ├── ISubscribeNFT.sol │ ├── ISubscribeNFTEvents.sol │ ├── ITreasury.sol │ ├── ITreasuryEvents.sol │ └── IUpgradeable.sol ├── libraries │ ├── Actions.sol │ ├── Constants.sol │ ├── DataTypes.sol │ ├── LibString.sol │ └── QRSVG.sol ├── middlewares │ ├── base │ │ ├── FeeMw.sol │ │ ├── PermissionedMw.sol │ │ └── Treasury.sol │ ├── essence │ │ ├── CollectDisallowedMw.sol │ │ ├── CollectFlexPaidMw.sol │ │ ├── CollectLimitedTimePaidMw.sol │ │ ├── CollectMerkleDropMw.sol │ │ ├── CollectOnlySubscribedMw.sol │ │ ├── CollectPaidMw.sol │ │ ├── CollectPermissionMw.sol │ │ └── CollectPermissionPaidMw.sol │ ├── profile │ │ ├── FeeCreationMw.sol │ │ ├── PermissionedFeeCreationMw.sol │ │ └── StableFeeCreationMw.sol │ └── subscribe │ │ ├── SubscribeDisallowedMw.sol │ │ ├── SubscribeOnlyOnceMw.sol │ │ └── SubscribePaidMw.sol ├── periphery │ ├── CyberBoxNFT.sol │ ├── CyberGrandNFT.sol │ ├── CyberVault.sol │ ├── FrameNFT.sol │ ├── Link3ProfileDescriptor.sol │ ├── Link3ProfileDescriptorV2.sol │ ├── Link3ProfileDescriptorV3.sol │ ├── MBNFT.sol │ ├── MiniShardNFT.sol │ └── RelationshipChecker.sol ├── storages │ ├── CyberBoxNFTStorage.sol │ ├── CyberEngineStorage.sol │ ├── CyberGrandNFTStorage.sol │ ├── EssenceNFTStorage.sol │ ├── Link3ProfileDescriptorStorage.sol │ ├── Link3ProfileDescriptorStorageV2.sol │ ├── MBNFTStorage.sol │ ├── ProfileNFTStorage.sol │ └── SubscribeNFTStorage.sol ├── token │ └── CYBER.sol └── upgradeability │ └── UpgradeableBeacon.sol ├── template └── index.html ├── test ├── CyberEngine.t.sol ├── CyberEngineUpgrade.t.sol ├── CyberNFTBase.t.sol ├── CyberToken.t.sol ├── Deployer.t.sol ├── EssenceNFT.t.sol ├── LibString.t.sol ├── Pausable.t.sol ├── ProfileNFT.t.sol ├── ProfileNFTBehavior.sol ├── ProfileNFTUpgrade.t.sol ├── QRSVGBasic.t.sol ├── SubscribeNFT.t.sol ├── SubscribeNFTUpgrade.t.sol ├── Treasury.t.sol ├── UpgradeableBeacon.t.sol ├── integration │ ├── IntegrationBase.t.sol │ ├── IntegrationCollect.t.sol │ ├── IntegrationEngine.t.sol │ ├── IntegrationSubscribe.t.sol │ ├── IntegrationTimelock.t.sol │ └── middleware │ │ ├── essence │ │ ├── CollectDisallowedMw.t.sol │ │ ├── CollectFlexPaidMw.t.sol │ │ ├── CollectMerkleDropMw.t.sol │ │ ├── CollectPaidMw.t.sol │ │ └── CollectPermissionMw.t.sol │ │ ├── profile │ │ └── PermissionedFeeCreationMw.t.sol │ │ └── subscribe │ │ ├── SubscribeDisallowedMw.t.sol │ │ ├── SubscribeOnlyOnceMw.t.sol │ │ └── SubscribePaidMw.t.sol ├── periphery │ ├── CyberBoxNFT.t.sol │ ├── CyberBoxNFTUpgrade.t.sol │ ├── CyberVault.t.sol │ └── Link3ProfileDescriptor.t.sol └── utils │ ├── MockCyberBoxV2.sol │ ├── MockERC1155.sol │ ├── MockERC20.sol │ ├── MockERC721.sol │ ├── MockEngine.sol │ ├── MockEngineV2.sol │ ├── MockInitializable.sol │ ├── MockLink5NFTDescriptor.sol │ ├── MockNFT.sol │ ├── MockPausable.sol │ ├── MockProfile.sol │ ├── MockProfileV2.sol │ ├── MockSubscribeNFTV2.sol │ ├── TestDeployer.sol │ ├── TestIntegrationBase.sol │ ├── TestLib712.sol │ ├── TestLibFixture.sol │ └── TestProxy.sol ├── tsconfig.json └── yarn.lock /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: [push] 4 | 5 | env: 6 | FOUNDRY_PROFILE: default 7 | 8 | jobs: 9 | check: 10 | strategy: 11 | fail-fast: true 12 | 13 | name: Foundry project 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | with: 18 | submodules: recursive 19 | 20 | - name: Install Foundry 21 | uses: foundry-rs/foundry-toolchain@v1 22 | with: 23 | version: nightly 24 | 25 | # - name: Check gas snapshots 26 | # run: forge snapshot --check 27 | 28 | - name: Run Forge tests 29 | run: | 30 | forge test -vvv --gas-report 31 | id: test 32 | 33 | - uses: actions/setup-node@v3 34 | with: 35 | node-version: 14 36 | 37 | - name: Install modules 38 | run: yarn 39 | 40 | - name: Run lint 41 | run: yarn run lint:gh-check 42 | 43 | - name: Run Coverage 44 | run: forge coverage --report lcov 45 | 46 | - name: Upload coverage to Codecov 47 | uses: codecov/codecov-action@v3 48 | with: 49 | token: 5988e766-42d2-43ef-813c-56f5b7cbcc6d 50 | directory: . 51 | env_vars: OS,PYTHON 52 | fail_ci_if_error: true 53 | files: ./lcov.info 54 | name: cybercontracts-coverage 55 | verbose: true 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | cache/ 2 | cache_hardhat/ 3 | out/ 4 | node_modules 5 | .env* 6 | .constructor-args* 7 | broadcast/ 8 | .DS_Store 9 | artifacts/ 10 | test/qrcode 11 | misc/qrcode/svg 12 | misc/qrcode/html 13 | script/playground 14 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/forge-std"] 2 | path = lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | [submodule "lib/openzeppelin-contracts"] 5 | path = lib/openzeppelin-contracts 6 | url = https://github.com/OpenZeppelin/openzeppelin-contracts 7 | branch = release-v4.7 8 | [submodule "lib/chainlink"] 9 | path = lib/chainlink 10 | url = https://github.com/smartcontractkit/chainlink 11 | branch = v1.11.0 12 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged && forge test -vvv && forge snapshot --check 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | src/dependencies/ 4 | misc/qrcode/html/ 5 | src/upgradeability/ -------------------------------------------------------------------------------- /CODEOWNER: -------------------------------------------------------------------------------- 1 | /src/dependencies/ @ZhimaoL @ryanli-me -------------------------------------------------------------------------------- /audit/Certik-Audit-CyberConnect.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberconnecthq/cybercontracts/acf96eb70dc5d20cd8e9d1e79dd81bffd5aa9fff/audit/Certik-Audit-CyberConnect.pdf -------------------------------------------------------------------------------- /config/.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier"], 3 | "extends": "solhint:recommended", 4 | "rules": { 5 | "prettier/prettier": "error", 6 | "compiler-version": ["error", "^0.8.14"], 7 | "no-empty-blocks": "off", 8 | "func-visibility": ["warn", { "ignoreConstructors": true }], 9 | "quotes": ["off", "double"], 10 | "not-rely-on-time": "off" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /config/.solhintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | lib/ 3 | src/dependencies/ 4 | src/libraries/LibString.sol 5 | src/upgradeability/ 6 | src/dependencies/ 7 | src/base/Auth.sol 8 | src/base/ERC721.sol 9 | src/base/RolesAuthority.sol -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Rinkeby 2 | 3 | [deployment](./deploy/rinkeby.md) -------------------------------------------------------------------------------- /docs/abi/CollectDisallowedMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"setEssenceMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/CollectFlexPaidMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"namespace","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"essenceId","type":"uint256"},{"indexed":true,"internalType":"address","name":"collector","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"metadataId","type":"string"}],"name":"CollectFlexPaidMwPreprocessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"essenceId","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"CollectFlexPaidMwSet","type":"event"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setEssenceMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/CollectLimitedTimePaidMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"namespace","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"essenceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"indexed":false,"internalType":"bool","name":"profileRequired","type":"bool"},{"indexed":false,"internalType":"bool","name":"subscribeRequired","type":"bool"}],"name":"CollectLimitedTimePaidMwSet","type":"event"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setEssenceMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/CollectMerkleDropMw.json: -------------------------------------------------------------------------------- 1 | [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"essenceId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"CollectMerkleDropMwSet","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"bytes","name":"root","type":"bytes"}],"name":"setEssenceMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/CollectOnlySubscribedMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"setEssenceMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/CollectPaidMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"namespace","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"essenceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"bool","name":"subscribeRequired","type":"bool"}],"name":"CollectPaidMwSet","type":"event"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setEssenceMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/CollectPermissionMw.json: -------------------------------------------------------------------------------- 1 | [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"essenceId","type":"uint256"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"CollectPermissionMwSet","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"namespace","type":"address"},{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"uint256","name":"essenceId","type":"uint256"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setEssenceMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/CollectPermissionPaidMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"namespace","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"essenceId","type":"uint256"},{"indexed":false,"internalType":"address","name":"signer","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"}],"name":"CollectPermissionPaidMwSet","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"uint256","name":"essenceId","type":"uint256"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setEssenceMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/Link3ProfileDescriptor.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"preTemplate","type":"string"},{"indexed":false,"internalType":"string","name":"template","type":"string"}],"name":"SetAnimationTemplate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"animationTemplate","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_animationTemplate","type":"string"},{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"template","type":"string"}],"name":"setAnimationTemplate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"handle","type":"string"},{"internalType":"uint256","name":"subscribers","type":"uint256"}],"internalType":"struct DataTypes.ConstructTokenURIParams","name":"params","type":"tuple"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/PaidCollectMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"treasury","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"essenceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentCollect","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"bool","name":"subscribeRequired","type":"bool"}],"name":"PaidEssenceMwSet","type":"event"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setEssenceMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/PaidSubscribeMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"treasury","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"bool","name":"nftRequired","type":"bool"},{"indexed":false,"internalType":"address","name":"nftAddress","type":"address"}],"name":"PaidSubscribeMwSet","type":"event"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"address","name":"subscriber","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setSubscribeMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/PermissionedFeeCreationMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"engine","type":"address"},{"internalType":"address","name":"treasury","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":false,"internalType":"enum PermissionedFeeCreationMw.Tier","name":"tier","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetFeeByTier","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENGINE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"namespace","type":"address"},{"internalType":"enum PermissionedFeeCreationMw.Tier","name":"tier","type":"uint8"}],"name":"getFeeByTier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"namespace","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"namespace","type":"address"}],"name":"getRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"namespace","type":"address"}],"name":"getSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string","name":"handle","type":"string"},{"internalType":"string","name":"avatar","type":"string"},{"internalType":"string","name":"metadata","type":"string"},{"internalType":"address","name":"operator","type":"address"}],"internalType":"struct DataTypes.CreateProfileParams","name":"params","type":"tuple"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string","name":"handle","type":"string"},{"internalType":"string","name":"avatar","type":"string"},{"internalType":"string","name":"metadata","type":"string"},{"internalType":"address","name":"operator","type":"address"}],"internalType":"struct DataTypes.CreateProfileParams","name":"params","type":"tuple"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"namespace","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setProfileMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/RelationshipChecker.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"namespace","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"address","name":"me","type":"address"}],"name":"isCollectedByMe","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"address","name":"me","type":"address"}],"name":"isSubscribedByMe","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/SignaturePermissionEssenceMw.json: -------------------------------------------------------------------------------- 1 | [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"essenceId","type":"uint256"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"SignatureEssenceMwSignerSet","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"uint256","name":"essenceId","type":"uint256"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"address","name":"collector","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"essenceId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setEssenceMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/SubscribeDisallowedMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"address","name":"subscriber","type":"address"},{"internalType":"address","name":"subscribeNFT","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"setSubscribeMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/SubscribeOnlyOnceMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"address","name":"subscriber","type":"address"},{"internalType":"address","name":"subscribeNFT","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"subscriber","type":"address"},{"internalType":"address","name":"subscribeNFT","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"setSubscribeMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/SubscribePaidMw.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"namespace","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"namespace","type":"address"},{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"bool","name":"nftRequired","type":"bool"},{"indexed":false,"internalType":"address","name":"nftAddress","type":"address"}],"name":"SubscribePaidMwSet","type":"event"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"postProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"address","name":"subscriber","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"preProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setSubscribeMwData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/abi/Treasury.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"treasuryAddress","type":"address"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"currency","type":"address"},{"indexed":true,"internalType":"bool","name":"preAllowed","type":"bool"},{"indexed":true,"internalType":"bool","name":"newAllowed","type":"bool"}],"name":"AllowCurrency","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"preTreasuryAddress","type":"address"},{"indexed":true,"internalType":"address","name":"treasuryAddress","type":"address"}],"name":"SetTreasuryAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"preTreasuryFee","type":"uint16"},{"indexed":true,"internalType":"uint16","name":"treasuryFee","type":"uint16"}],"name":"SetTreasuryFee","type":"event"},{"inputs":[{"internalType":"address","name":"currency","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"allowCurrency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getTreasuryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTreasuryFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"currency","type":"address"}],"name":"isCurrencyAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"treasuryAddress","type":"address"}],"name":"setTreasuryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"treasuryFee","type":"uint16"}],"name":"setTreasuryFee","outputs":[],"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /docs/deploy/goerli-5/contract.md: -------------------------------------------------------------------------------- 1 | | Contract | Address | 2 | | ----------------------------------------- | ------------------------------------------ | 3 | | Action Lib | 0x781d0a455020024da046f823d9ea076b76a873f3 | 4 | | RolesAuthority | 0x1ae0b199a2180632947721d9c5ebc9daf0ec10e5 | 5 | | EngineImpl | 0xa6fdfff3955455897b746432f945eab3b5fb5c1f | 6 | | EngineProxy | 0xaf9104eb9c6b21efdc43baaaee70662d6cce8798 | 7 | | Profile Factory | 0x27361075ea6e85564a4b00f5828235fc4c8c2e32 | 8 | | Essence Factory | 0x216ba81b5fd81253fde6888039c6001d6f891efb | 9 | | Subscribe Factory | 0x958d142ef3a7b2ee34cdf1f81c135fb91a454a5c | 10 | | CC Profile (Impl) | 0xeD2788C005C8715cFC7C2A29fF81B40b479Cc6fb | 11 | | CC Profile (Proxy) | 0x57e12b7a5f38a7f9c23ebd0400e6e53f2a45f271 | 12 | | CyberConnect Treasury | 0x3963744012dadf90a9034ea1068f53108b1a3834 | 13 | | CC Descriptor (Impl) | 0x74788f90b8436afe91931c17a01023bce5d89c0f | 14 | | CC Descriptor (Proxy) | 0xa27b77f6b13bece78b63925edb3b35df495fdf8e | 15 | | CyberVault | 0x5e2a433774a51207d69bb432898b3626e20cda66 | 16 | | RelationshipChecker | 0xa52cc9b8219dce25bc791a8b253dec61f16d5ff0 | 17 | | CyberGrandNFT (Impl) | 0x4ae6d419b943c6a26b08f8969d5feb987b4e6deb | 18 | | CyberGrandNFT (Proxy) | 0x812f26e1ebacb28d129a02bce016098154335ebd | 19 | | CyberBoxNFT (Proxy) | 0x1cc24a44c4b51d3f9b0d0f5bdcf95b0f385b154f | 20 | | MBNFT (Impl) | 0x4f321fb85f09630d4a6c2295c89da39b4a6f791c | 21 | | MBNFT (Proxy) | 0xff0ab461778232a1480f7886ea1e2abd3324f338 | 22 | | FrameNFT | 0x58d8c07575339bf47392ad2bd0aeb9955f8495cf | 23 | | CC Profile MW (StableFeeCreationMw) | 0x940d11e9105d7c0ffee91e5e6b2375e3a58ec18a | 24 | | CC Profile MW (PermissionedFeeCreationMw) | 0xd1587f68e9d9f9ee93c9aa6fc60c7da414e90818 | 25 | | CC Profile MW (FeeCreationMw) | 0xf1d8512d08f3924768041d1063ef5517ca867f0d | 26 | | Essence MW (SignaturePermissionEssenceMw) | 0x733142f467904f9a2e8efa0119523d3cc7a99b0b | 27 | | Subscribe MW (SubscribePaidMw) | 0xd5d66dc7180fa4f3ae05b66ee34793146db6e3e9 | 28 | | Essence MW (CollectPaidMw) | 0x415648c28adb31629418498264f55d54e4c324db | 29 | | Essence MW (CollectPermissionMw) | 0x77ebd0aa021b39086e84b9d3afeb738cbbfe16fd | 30 | | Essence MW (CollectPermissionMw V2) | 0xbbbab0257edba5823ddb5aa62c08f07bd0d302d9 | 31 | | Essence MW (CollectLimitedTimePaidMw) | 0x3a6507d750c87b219920879f9e01fdd512580872 | 32 | -------------------------------------------------------------------------------- /docs/deploy/polygon-137/contract.md: -------------------------------------------------------------------------------- 1 | | Contract | Address | 2 | | ------------ | ------------------------------------------ | 3 | | MiniShardNFT | 0x49253c64e6fa46d299177b8a94ae49d2f82c5c95 | 4 | -------------------------------------------------------------------------------- /docs/test/qrcode.md: -------------------------------------------------------------------------------- 1 | # QRCode Library Fuzz Test 2 | 3 | 0. foundryup 4 | ```bash 5 | foundryup 6 | ``` 7 | 8 | clean up 9 | ```bash 10 | rm -rf ./test/qrcode ./misc/qrcode/html ./misc/qrcode/svg 11 | ``` 12 | 1. Set desired test parameter (data length and iteration) in `./misc/qrcode/gen-sol.js` to generate solidity test files (300 is probably max) 13 | 2. Run 14 | 15 | ```bash 16 | node misc/qrcode/gen-sol.js 17 | ``` 18 | 19 | 3. Make sure you have `./misc/qrcode/svg` folder created. 20 | 21 | ```bash 22 | mkdir -pv misc/qrcode/svg 23 | ``` 24 | 25 | 4. Run 26 | 27 | ```bash 28 | forge test --match-contract QRSVGIntegration -vvv 29 | ``` 30 | 31 | This runs QRSVG.sol against all generated input cases and write base64 encoded svg of the QRCode to `./misc/qrcode/svg`. 32 | 33 | 5. Run 34 | 35 | ```bash 36 | node misc/qrcode/gen-html.js 37 | ``` 38 | 39 | This generates html files for each svg QRCode for verifying the content. 40 | 41 | 6. Run 42 | 43 | ```bash 44 | node misc/qrcode/puppet.js 45 | ``` 46 | 47 | This runs a headless chrome for browser to read QRCode with Canvas and check if the content of QRCode is expected 48 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = 'src' 3 | out = 'out' 4 | libs = ['lib'] 5 | gas_reports = ["*"] 6 | fs_permissions = [{ access = "read-write", path = "./"}] 7 | 8 | [profile.goerli] 9 | src = 'src' 10 | out = 'out' 11 | libs = ['lib'] 12 | gas_reports = ["*"] 13 | libraries = [ 14 | './src/libraries/Actions.sol:Actions:0x781d0a455020024da046f823d9ea076b76a873f3' 15 | ] 16 | fs_permissions = [{ access = "read-write", path = "./"}] 17 | 18 | [profile.bnbt] 19 | src = 'src' 20 | out = 'out' 21 | libs = ['lib'] 22 | gas_reports = ["*"] 23 | libraries = [ 24 | './src/libraries/Actions.sol:Actions:0x781d0a455020024da046f823d9ea076b76a873f3' 25 | ] 26 | fs_permissions = [{ access = "read-write", path = "./"}] 27 | 28 | [profile.mainnet] 29 | src = 'src' 30 | out = 'out' 31 | libs = ['lib'] 32 | gas_reports = ["*"] 33 | libraries = [ 34 | './src/libraries/Actions.sol:Actions:0x8ccbe07f1e12a61e4fbb3a1895d35dce001ff73a' 35 | ] 36 | fs_permissions = [{ access = "read-write", path = "./"}] 37 | 38 | [profile.nova] 39 | src = 'src' 40 | out = 'out' 41 | libs = ['lib'] 42 | gas_reports = ["*"] 43 | libraries = [ 44 | './src/libraries/Actions.sol:Actions:0x8ccbe07f1e12a61e4fbb3a1895d35dce001ff73a' 45 | ] 46 | fs_permissions = [{ access = "read-write", path = "./"}] 47 | 48 | [profile.bnb] 49 | src = 'src' 50 | out = 'out' 51 | libs = ['lib'] 52 | gas_reports = ["*"] 53 | libraries = [ 54 | './src/libraries/Actions.sol:Actions:0x8ccbe07f1e12a61e4fbb3a1895d35dce001ff73a' 55 | ] 56 | fs_permissions = [{ access = "read-write", path = "./"}] 57 | 58 | [profile.polygon] 59 | src = 'src' 60 | out = 'out' 61 | libs = ['lib'] 62 | gas_reports = ["*"] 63 | libraries = [ 64 | './src/libraries/Actions.sol:Actions:0x8ccbe07f1e12a61e4fbb3a1895d35dce001ff73a' 65 | ] 66 | fs_permissions = [{ access = "read-write", path = "./"}] 67 | 68 | 69 | # See more config options https://github.com/foundry-rs/foundry/tree/master/config -------------------------------------------------------------------------------- /hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import "hardhat-preprocessor"; 3 | import "hardhat-contract-sizer"; 4 | import { HardhatUserConfig } from "hardhat/config"; 5 | import "@nomiclabs/hardhat-ethers"; 6 | require("dotenv").config({ path: __dirname + "/.env.goerli" }); 7 | //require("dotenv").config({ path: __dirname + "/.env.bnbt" }); 8 | //require("dotenv").config({ path: __dirname + "/.env.bnb" }); 9 | //require("dotenv").config({ path: __dirname + "/.env.nova" }); 10 | 11 | /** @type import('hardhat/config').HardhatUserConfig */ 12 | const config: HardhatUserConfig = { 13 | networks: { 14 | hardhat: {}, 15 | goerli: { 16 | url: process.env.GOERLI_RPC_URL, 17 | accounts: [process.env.PRIVATE_KEY as string], 18 | }, 19 | // bnbt: { 20 | // url: process.env.BNBT_RPC_URL, 21 | // accounts: [process.env.PRIVATE_KEY as string], 22 | // }, 23 | // bnb: { 24 | // url: process.env.BNB_RPC_URL, 25 | // accounts: [process.env.PRIVATE_KEY as string], 26 | // }, 27 | // nova: { 28 | // url: process.env.NOVA_RPC_URL, 29 | // accounts: [process.env.PRIVATE_KEY as string], 30 | // }, 31 | }, 32 | solidity: { 33 | version: "0.8.14", 34 | settings: { 35 | optimizer: { 36 | enabled: true, 37 | runs: 200, 38 | }, 39 | }, 40 | }, 41 | preprocess: { 42 | eachLine: (hre: any) => ({ 43 | transform: (line: string) => { 44 | if (line.match(/^\s*import /i)) { 45 | getRemappings().forEach(([find, replace]) => { 46 | // this matches all occurrences not just the start of import which could be a problem 47 | if (line.match(find)) { 48 | line = line.replace(find, replace); 49 | } 50 | }); 51 | } 52 | return line; 53 | }, 54 | }), 55 | }, 56 | paths: { 57 | sources: "./src", 58 | cache: "./cache_hardhat", 59 | }, 60 | }; 61 | function getRemappings() { 62 | return fs 63 | .readFileSync("remappings.txt", "utf8") 64 | .split("\n") 65 | .filter(Boolean) // remove empty lines 66 | .map((line) => line.trim().split("=")); 67 | } 68 | export default config; 69 | -------------------------------------------------------------------------------- /misc/cyberbox/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Link3 Mystery Box", 3 | "description": "Mystery Box is a mysterious and secret benefit designed to reward early Link3 adopters who're actively helping us build the layer of trust.", 4 | "image": "ipfs://QmVKQUCW4yb8YvJpVDs2gQLWNEJaQk5BD74Kb7jcGwBdQE", 5 | "animation_url": "ipfs://QmVKQUCW4yb8YvJpVDs2gQLWNEJaQk5BD74Kb7jcGwBdQE", 6 | "external_url": "https://link3.to", 7 | "attributes": [ 8 | ] 9 | } -------------------------------------------------------------------------------- /misc/post_deploy.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs/promises"; 2 | import * as path from "path"; 3 | 4 | const writeAbi = async () => { 5 | const folders = [ 6 | "RolesAuthority.sol/RolesAuthority.json", 7 | "CyberEngine.sol/CyberEngine.json", 8 | "EssenceNFT.sol/EssenceNFT.json", 9 | "ProfileNFT.sol/ProfileNFT.json", 10 | "SubscribeNFT.sol/SubscribeNFT.json", 11 | 12 | "Link3ProfileDescriptor.sol/Link3ProfileDescriptor.json", 13 | "CyberBoxNFT.sol/CyberBoxNFT.json", 14 | "CyberGrandNFT.sol/CyberGrandNFT.json", 15 | "MBNFT.sol/MBNFT.json", 16 | "FrameNFT.sol/FrameNFT.json", 17 | "MiniShardNFT.sol/MiniShardNFT.json", 18 | "CyberVault.sol/CyberVault.json", 19 | "RelationshipChecker.sol/RelationshipChecker.json", 20 | 21 | "Treasury.sol/Treasury.json", 22 | 23 | "CollectDisallowedMw.sol/CollectDisallowedMw.json", 24 | "CollectMerkleDropMw.sol/CollectMerkleDropMw.json", 25 | "CollectOnlySubscribedMw.sol/CollectOnlySubscribedMw.json", 26 | "CollectPaidMw.sol/CollectPaidMw.json", 27 | "CollectPermissionMw.sol/CollectPermissionMw.json", 28 | "CollectLimitedTimePaidMw.sol/CollectLimitedTimePaidMw.json", 29 | "CollectPermissionPaidMw.sol/CollectPermissionPaidMw.json", 30 | "CollectFlexPaidMw.sol/CollectFlexPaidMw.json", 31 | 32 | "PermissionedFeeCreationMw.sol/PermissionedFeeCreationMw.json", 33 | "StableFeeCreationMw.sol/StableFeeCreationMw.json", 34 | "SubscribeDisallowedMw.sol/SubscribeDisallowedMw.json", 35 | "SubscribeOnlyOnceMw.sol/SubscribeOnlyOnceMw.json", 36 | "SubscribePaidMw.sol/SubscribePaidMw.json", 37 | ]; 38 | const ps = folders.map(async (file) => { 39 | const f = await fs.readFile(path.join("./out", file), "utf8"); 40 | const json = JSON.parse(f); 41 | const fileName = path.parse(file).name; 42 | return fs.writeFile( 43 | path.join("docs/abi", `${fileName}.json`), 44 | JSON.stringify(json.abi) 45 | ); 46 | }); 47 | await Promise.all(ps); 48 | }; 49 | 50 | const main = async () => { 51 | await writeAbi(); 52 | }; 53 | 54 | main() 55 | .then(() => {}) 56 | .catch((err) => { 57 | console.error(err); 58 | }); 59 | -------------------------------------------------------------------------------- /misc/pre_deploy.js: -------------------------------------------------------------------------------- 1 | import * as fsSync from "fs"; 2 | import * as fs from "fs/promises"; 3 | import * as dotenv from "dotenv"; 4 | import * as path from "path"; 5 | dotenv.config({ debug: true, path: ".env.rinkeby" }); 6 | 7 | import { default as FormData } from "form-data"; 8 | import axios from "axios"; 9 | 10 | import { ethers } from "ethers"; 11 | 12 | const pinataBase = "https://cyberconnect.mypinata.cloud/ipfs/"; 13 | const pinataJWT = process.env.PINATA_JWT; 14 | 15 | const writeTemplate = async (profileProxy) => { 16 | const file = await fs.readFile(path.join("./template", "index.html"), "utf8"); 17 | const out = file.replace( 18 | /0x000000000000000000000000000000000000DEAD/g, 19 | profileProxy 20 | ); 21 | const dir = path.join("./docs/template"); 22 | await fs.rm(dir, { recursive: true, force: true }); 23 | 24 | const output = path.join(dir, "index.html"); 25 | await fs.mkdir(dir, { recursive: true }); 26 | await fs.writeFile(output, out); 27 | return { output, dir }; 28 | }; 29 | const writeToPinata = async ({ output, dir }) => { 30 | var data = new FormData(); 31 | data.append("file", fsSync.createReadStream(output)); 32 | data.append("pinataOptions", '{"cidVersion": 1}'); 33 | 34 | const config = { 35 | method: "post", 36 | url: "https://api.pinata.cloud/pinning/pinFileToIPFS", 37 | headers: { 38 | Authorization: "Bearer " + pinataJWT, 39 | ...data.getHeaders(), 40 | }, 41 | data: data, 42 | }; 43 | 44 | const res = await axios(config); 45 | console.log(res.data); 46 | 47 | await fs.rename(output, path.join(dir, res.data.IpfsHash)); 48 | return pinataBase + res.data.IpfsHash; 49 | }; 50 | 51 | const calc = async () => { 52 | const provider = new ethers.providers.JsonRpcProvider( 53 | process.env.RINKEBY_RPC_URL 54 | ); 55 | const deployer = new ethers.Wallet(process.env.PRIVATE_KEY); 56 | 57 | let deployerNonce = await provider.getTransactionCount(deployer.address); 58 | const profileProxyNonce = ethers.utils.hexlify(deployerNonce + 3); 59 | const profileProxyAddr = 60 | "0x" + 61 | ethers.utils 62 | .keccak256(ethers.utils.RLP.encode([deployer.address, profileProxyNonce])) 63 | .substr(26); 64 | return ethers.utils.getAddress(profileProxyAddr); // checksum 65 | }; 66 | 67 | const templateDeployScript = async (profileProxy, templateURL) => { 68 | console.log(templateURL); 69 | const p = path.join("./template", "Deploy.s.sol.template"); 70 | const outP = path.join("./script", "Deploy.s.sol"); 71 | const file = await fs.readFile(p, "utf8"); 72 | let out = file.replace(/0xDEAD/g, profileProxy); 73 | out = out.replace(/TEMPLATE_URL/g, templateURL); 74 | await fs.writeFile(outP, out); 75 | }; 76 | 77 | const main = async () => { 78 | const profileProxy = await calc(); 79 | const out = await writeTemplate(profileProxy); 80 | const pinataURL = await writeToPinata(out); 81 | console.log("profileProxy", profileProxy); 82 | await templateDeployScript(profileProxy, pinataURL); 83 | }; 84 | 85 | main() 86 | .then(() => {}) 87 | .catch((err) => { 88 | console.error(err); 89 | }); 90 | -------------------------------------------------------------------------------- /misc/qrcode/QRSVG.t.sol.template: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Test.sol"; 6 | import { QRSVG } from "../../src/libraries/QRSVG.sol"; 7 | import "forge-std/console.sol"; 8 | 9 | contract QRSVGIntegrationTest is Test { 10 | string[] names = NAMES; 11 | string[] urls = URLS; 12 | 13 | function testGenerateQR() public { 14 | assert(names.length == urls.length); 15 | for (uint256 i = 0; i < names.length; i++) { 16 | string memory name = names[i]; 17 | string memory url = urls[i]; 18 | string memory code = QRSVG.generateQRCode(url); 19 | vm.writeFile( 20 | string(abi.encodePacked("./misc/qrcode/svg/", name)), 21 | code 22 | ); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /misc/qrcode/gen-html.js: -------------------------------------------------------------------------------- 1 | import * as fs from "fs/promises"; 2 | import * as path from "path"; 3 | const dir = path.join("./misc/qrcode/html/"); 4 | 5 | const writeTemplate = async (url, content) => { 6 | const file = await fs.readFile( 7 | path.join("./misc/qrcode/", "qr-test.html.template"), 8 | "utf8" 9 | ); 10 | const out = file.replace(/REPLACE_ME/g, content); 11 | 12 | const output = path.join(dir, `${url}.html`); 13 | await fs.mkdir(dir, { recursive: true }); 14 | await fs.writeFile(output, out); 15 | return { output, dir }; 16 | }; 17 | 18 | const p = "./misc/qrcode/svg"; 19 | 20 | const main = async () => { 21 | try { 22 | const exists = await fs.access(dir, 0); 23 | if (exists) { 24 | await fs.rm(dir, { recursive: true, force: true }); 25 | } 26 | } catch (err) {} 27 | const files = await fs.readdir(p); 28 | console.log("total tests:", files.length); 29 | // console.log(files); 30 | const all = []; 31 | const a = async (aa) => { 32 | const content = await fs.readFile(path.join(p, aa)); 33 | return writeTemplate(aa, content); 34 | }; 35 | for (let i = 0; i < files.length; i++) { 36 | all.push(a(files[i])); 37 | } 38 | return Promise.all(all); 39 | }; 40 | 41 | main() 42 | .then(() => {}) 43 | .catch((err) => { 44 | console.error(err); 45 | }); 46 | -------------------------------------------------------------------------------- /misc/qrcode/gen-sol.js: -------------------------------------------------------------------------------- 1 | import * as fs from "fs/promises"; 2 | import * as path from "path"; 3 | const writeTemplate = async (i, batch) => { 4 | const file = await fs.readFile( 5 | path.join("./misc/qrcode", "QRSVG.t.sol.template"), 6 | "utf8" 7 | ); 8 | const urls = batch.map((str) => `https://link3.to/${str}`); 9 | let out = file.replace(/URLS/g, JSON.stringify(urls)); 10 | out = out.replace(/NAMES/g, JSON.stringify(batch)); 11 | 12 | const output = path.join(dir, `QRSVG-${i}-${batch.length}.t.sol`); 13 | await fs.mkdir(dir, { recursive: true }); 14 | await fs.writeFile(output, out); 15 | return { output, dir }; 16 | }; 17 | 18 | const dir = path.join("./test/qrcode/"); 19 | 20 | const main = async () => { 21 | try { 22 | const exists = await fs.access(dir, 0); 23 | if (exists) { 24 | await fs.rm(dir, { recursive: true, force: true }); 25 | } 26 | } catch (err) {} 27 | const all = []; 28 | let batch = []; 29 | let counter = 0; 30 | const length = 27; 31 | const iteration = 100; 32 | let total = []; 33 | for (let j = 1; j <= length; j++) { 34 | // 27 is the max length of the link3 handle 35 | for (let i = 0; i < iteration; i++) { 36 | // how many tries for each length 37 | const str = randomString(j, wordlist); 38 | batch.push(str); 39 | if (batch.length == 40) { 40 | all.push(writeTemplate(counter, batch)); 41 | total = total.concat(batch); 42 | batch = []; 43 | counter++; 44 | } 45 | } 46 | } 47 | if (batch) { 48 | all.push(writeTemplate(counter, batch)); 49 | total = total.concat(batch); 50 | } 51 | const toFindDuplicates = (arry) => 52 | arry.filter((item, index) => arry.indexOf(item) !== index); 53 | const duplicates = toFindDuplicates(total); 54 | console.log("random tests:", total.length); 55 | console.log("duplicate", duplicates.length); 56 | console.log("total unique tests", total.length - duplicates.length); 57 | return Promise.all(all); 58 | }; 59 | function randomString(length, chars) { 60 | var result = ""; 61 | for (var i = length; i > 0; --i) 62 | result += chars[Math.floor(Math.random() * chars.length)]; 63 | return result; 64 | } 65 | const wordlist = "0123456789abcdefghijklmnopqrstuvwxyz_"; 66 | 67 | main() 68 | .then(() => {}) 69 | .catch((err) => { 70 | console.error(err); 71 | }); 72 | -------------------------------------------------------------------------------- /misc/qrcode/puppet.js: -------------------------------------------------------------------------------- 1 | import * as path from "path"; 2 | import * as fs from "fs/promises"; 3 | import { Cluster } from "puppeteer-cluster"; 4 | 5 | (async () => { 6 | const cluster = await Cluster.launch({ 7 | concurrency: Cluster.CONCURRENCY_CONTEXT, 8 | maxConcurrency: 20, 9 | // monitor: true, 10 | }); 11 | const files = await fs.readdir("./misc/qrcode/html"); 12 | console.log("total tests:", files.length); 13 | await cluster.task(async ({ page, data: url }) => { 14 | const file = path.parse(url).name; 15 | page.on("console", (msg) => { 16 | if (msg.text() !== "https://link3.to/" + file) { 17 | console.error( 18 | "====================wrong url. got, expected: ", 19 | msg.text(), 20 | file 21 | ); 22 | } else { 23 | // console.log("Correct url:", msg.text()); 24 | } 25 | }); 26 | await page.goto(url); 27 | }); 28 | for (let i = 0; i < files.length; i++) { 29 | const dirUrl = new URL(".", import.meta.url); 30 | const f = dirUrl.href + "html/" + files[i]; 31 | cluster.queue(f); 32 | } 33 | 34 | await cluster.idle(); 35 | await cluster.close(); 36 | })(); 37 | -------------------------------------------------------------------------------- /misc/qrcode/qr-test.html.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | QrcodeDecoder - Image 8 | 9 | 10 | 11 | 12 | 16 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /remappings.txt: -------------------------------------------------------------------------------- 1 | ds-test/=lib/forge-std/lib/ds-test/src/ 2 | forge-std/=lib/forge-std/src/ 3 | openzeppelin-contracts/=lib/openzeppelin-contracts/ 4 | chainlink/=lib/chainlink/ 5 | -------------------------------------------------------------------------------- /script/AllowCurrency.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | 14 | if (block.chainid == DeploySetting.GOERLI) { 15 | LibDeploy.allowCurrency( 16 | vm, 17 | address(0x3963744012daDf90A9034Ea1068f53108B1A3834), // Treasury Address 18 | address(0x326C977E6efc84E512bB9C30f76E30c160eD06FB) // Currency Address 19 | ); 20 | } else if (block.chainid == DeploySetting.BNB) { 21 | LibDeploy.allowCurrency( 22 | vm, 23 | address(0x90137F1234C137C4284dd317303F2717c871f70A), // Treasury Address 24 | address(0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56) // Currency Address 25 | ); 26 | } 27 | vm.stopBroadcast(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /script/Deploy.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 7 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | 13 | vm.startBroadcast(); 14 | 15 | LibDeploy.deploy( 16 | vm, 17 | LibDeploy.DeployParams(true, true, deployParams), 18 | deployParams.link3Signer // mint test profile to signer 19 | ); 20 | 21 | vm.stopBroadcast(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /script/DeployAction.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | LibDeploy.deployActionLib(vm, deployParams.deployerContract, true); 14 | vm.stopBroadcast(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /script/DeployBox.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | if (block.chainid == DeploySetting.MAINNET) { 14 | LibDeploy.deployBox( 15 | vm, 16 | deployParams.deployerContract, 17 | deployParams.link3Owner, 18 | deployParams.link3Owner, // owner address 19 | true 20 | ); 21 | } else if (block.chainid == DeploySetting.BNBT) { 22 | LibDeploy.deployBox( 23 | vm, 24 | deployParams.deployerContract, 25 | deployParams.link3Signer, 26 | deployParams.link3Owner, // owner address 27 | true 28 | ); 29 | } else if (block.chainid == DeploySetting.BNB) { 30 | LibDeploy.deployBox( 31 | vm, 32 | deployParams.deployerContract, 33 | deployParams.link3Signer, 34 | address(0xf9E12df9428F1a15BC6CfD4092ADdD683738cE96), // owner address - safe 35 | true 36 | ); 37 | } 38 | 39 | vm.stopBroadcast(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /script/DeployChecker.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | 14 | if (block.chainid == DeploySetting.GOERLI) { 15 | LibDeploy.deployRelationshipChecker( 16 | vm, 17 | LibDeploy.DeployParams(true, true, deployParams), 18 | address(0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271), // link3 namespace 19 | true 20 | ); 21 | } else if (block.chainid == DeploySetting.BNBT) { 22 | LibDeploy.deployRelationshipChecker( 23 | vm, 24 | LibDeploy.DeployParams(true, true, deployParams), 25 | address(0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271), // link3 namespace 26 | true 27 | ); 28 | } else if (block.chainid == DeploySetting.BNB) { 29 | LibDeploy.deployRelationshipChecker( 30 | vm, 31 | LibDeploy.DeployParams(true, true, deployParams), 32 | address(0x2723522702093601e6360CAe665518C4f63e9dA6), // link3 namespace 33 | true 34 | ); 35 | } 36 | vm.stopBroadcast(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /script/DeployCreate2Deployer.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity ^0.8.13; 4 | 5 | import "forge-std/Script.sol"; 6 | import "../src/deployer/Create2Deployer.sol"; 7 | 8 | contract DeployerCreate2Deployer is Script { 9 | function run() external { 10 | uint256 nonce = vm.getNonce(msg.sender); 11 | if (block.chainid == 1 || block.chainid == 42170) { 12 | require(nonce == 0, "nonce must be 0"); 13 | console.log("deployer", msg.sender); 14 | require( 15 | msg.sender == 0xA7b6bEf855c1c57Df5b7C9c7a4e1eB757e544e7f, 16 | "address must be deployer" 17 | ); 18 | } 19 | 20 | vm.startBroadcast(); 21 | new Create2Deployer(); 22 | vm.stopBroadcast(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /script/DeployCyberToken.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | LibDeploy.deployCyberToken( 14 | vm, 15 | deployParams.cyberTokenOwner, 16 | deployParams.cyberTokenOwner, 17 | true 18 | ); 19 | vm.stopBroadcast(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /script/DeployFrame.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | 14 | if (block.chainid == DeploySetting.GOERLI) { 15 | LibDeploy.deployFrame( 16 | vm, 17 | deployParams.deployerContract, 18 | deployParams.link3Signer, 19 | true 20 | ); 21 | } else if (block.chainid == POLYGON) { 22 | LibDeploy.deployFrame( 23 | vm, 24 | deployParams.deployerContract, 25 | deployParams.link3Signer, 26 | true 27 | ); 28 | } 29 | vm.stopBroadcast(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /script/DeployGrand.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | LibDeploy.deployGrand( 14 | vm, 15 | deployParams.deployerContract, 16 | deployParams.link3Owner, 17 | deployParams.link3Signer, 18 | true 19 | ); 20 | vm.stopBroadcast(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /script/DeployMB.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | 14 | if (block.chainid == DeploySetting.GOERLI) { 15 | LibDeploy.deployMB( 16 | vm, 17 | deployParams.deployerContract, 18 | deployParams.link3Owner, 19 | address(0x1cC24A44c4b51D3F9B0d0F5BdCF95b0F385B154f), 20 | "https://mb-metadata.cyberconnect.dev", 21 | true 22 | ); 23 | } else if (block.chainid == DeploySetting.MAINNET) { 24 | LibDeploy.deployMB( 25 | vm, 26 | deployParams.deployerContract, 27 | deployParams.link3Owner, 28 | address(0xcE4F341622340d56E397740d325Fd357E62b91CB), 29 | "https://mbmetadata.cyberconnect.dev", 30 | true 31 | ); 32 | } else if (block.chainid == DeploySetting.BNB) { 33 | LibDeploy.deployMB( 34 | vm, 35 | deployParams.deployerContract, 36 | address(0xf9E12df9428F1a15BC6CfD4092ADdD683738cE96), // owner address - safe 37 | address(0xCAdC6C364E8fcad0F382FDdfd6ff5b41d82EB3e4), 38 | "https://mbmetadata.cyberconnect.dev/bnb", 39 | true 40 | ); 41 | } else if (block.chainid == DeploySetting.BNBT) { 42 | LibDeploy.deployMB( 43 | vm, 44 | deployParams.deployerContract, 45 | deployParams.link3Owner, 46 | address(0x54346edD22ef49bdcA1aaE6114F8B1a1E598b674), 47 | "https://mb-metadata.cyberconnect.dev/bnb", 48 | true 49 | ); 50 | } 51 | vm.stopBroadcast(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /script/DeployMiddleware.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | if (block.chainid == DeploySetting.BNBT) { 14 | LibDeploy.deployAllMiddleware( 15 | vm, 16 | LibDeploy.DeployParams(true, true, deployParams), 17 | address(0xAF9104Eb9c6B21Efdc43BaaaeE70662d6CcE8798), // engine proxy address 18 | address(0x3963744012daDf90A9034Ea1068f53108B1A3834), // cyber treasury address 19 | address(0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e), // bnb-usd oracle address 20 | address(0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271), // namespace 21 | true 22 | ); 23 | } else if (block.chainid == DeploySetting.BNB) { 24 | LibDeploy.deployAllMiddleware( 25 | vm, 26 | LibDeploy.DeployParams(true, true, deployParams), 27 | address(0x1cA51941a616D14C42D3e3B9E6E687d7F5054c3A), // engine proxy address 28 | address(0x90137F1234C137C4284dd317303F2717c871f70A), // cyber treasury address 29 | address(0x0567F2323251f0Aab15c8dFb1967E4e8A7D42aeE), // bnb-usd oracle address 30 | address(0x2723522702093601e6360CAe665518C4f63e9dA6), // namespace 31 | true 32 | ); 33 | } 34 | vm.stopBroadcast(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /script/DeployMiniShard.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | 14 | if (block.chainid == DeploySetting.BNBT) { 15 | LibDeploy.deployMiniShard( 16 | vm, 17 | deployParams.deployerContract, 18 | deployParams.link3Signer, 19 | "https://mb-metadata.cyberconnect.dev/minishards", 20 | true 21 | ); 22 | } else if (block.chainid == BNB) { 23 | LibDeploy.deployMiniShard( 24 | vm, 25 | deployParams.deployerContract, 26 | deployParams.link3Signer, 27 | "https://mbmetadata.cyberconnect.dev/minishards", 28 | true 29 | ); 30 | } else if (block.chainid == POLYGON) { 31 | LibDeploy.deployMiniShard( 32 | vm, 33 | deployParams.deployerContract, 34 | deployParams.link3Signer, 35 | "https://mbmetadata.cyberconnect.dev/minishards-polygon", 36 | true 37 | ); 38 | } 39 | vm.stopBroadcast(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /script/DeployNamespace.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | string internal constant CYBERCONNECT_NAME = "CyberConnect"; 11 | string internal constant CYBERCONNECT_SYMBOL = "CYBERCONNECT"; 12 | bytes32 constant CYBERCONNECT_SALT = keccak256(bytes(CYBERCONNECT_NAME)); 13 | 14 | function run() external { 15 | _setDeployParams(); 16 | vm.startBroadcast(); 17 | address profileAddr; 18 | if ( 19 | block.chainid == DeploySetting.BNBT || 20 | block.chainid == DeploySetting.GOERLI 21 | ) { 22 | (profileAddr, , ) = LibDeploy.createNamespace( 23 | address(0xAF9104Eb9c6B21Efdc43BaaaeE70662d6CcE8798), // engine proxy address 24 | address(0x927f355117721e0E8A7b5eA20002b65B8a551890), // link3Owner 25 | CYBERCONNECT_NAME, // LINK3_NAME, 26 | CYBERCONNECT_SYMBOL, // LINK3_SYMBOL, 27 | CYBERCONNECT_SALT, // LINK3_SALT, 28 | address(0x27361075Ea6E85564a4B00F5828235FC4C8C2e32), // addrs.profileFac, 29 | address(0x958d142Ef3a7B2ee34CDF1F81C135FB91a454A5C), // addrs.subFac, 30 | address(0x216BA81b5FD81253FDE6888039c6001D6f891eFb) // addrs.essFac 31 | ); 32 | } 33 | 34 | console.log("CyberConnect Profile:", profileAddr); 35 | vm.stopBroadcast(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /script/DeployPermissionless.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeployNamespace } from "./libraries/DeployNamespace.sol"; 7 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 8 | 9 | contract DeployPermissionlessScript is Script { 10 | DeployNamespace.DeployNamespaceParams params; 11 | 12 | function _setup() private { 13 | if (block.chainid == 5) { 14 | params.engineProxy = 0xadAEc1655D34c9E86394400e1cdEF3BaC3F0C117; 15 | params.namespaceOwner = 0x927f355117721e0E8A7b5eA20002b65B8a551890; 16 | params.name = "CyberConnect"; 17 | params.symbol = "CYBER"; 18 | params.profileFac = 0x5eB4f4d2b4A2C0E331e1c1767143EfcB91Bf56e7; 19 | params.subFac = 0xa97a8F309263658B77a2755be861173fB633020d; 20 | params.essFac = 0xcfB865f5F4a3c74cc2CAC0460273BB43f3D8E27C; 21 | } 22 | } 23 | 24 | function run() external { 25 | _setup(); 26 | vm.startBroadcast(); 27 | 28 | DeployNamespace.deployNamespace(vm, params); 29 | vm.stopBroadcast(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /script/DeployTimeLock.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | 14 | if (block.chainid == 5) { 15 | address timelock = LibDeploy.deployTimeLock( 16 | vm, 17 | deployParams.link3Owner, 18 | 600, 19 | true 20 | ); 21 | LibDeploy.changeOwnership( 22 | vm, 23 | timelock, 24 | deployParams.engineGov, 25 | address(0x12F7bBc1A79ECA365F9A833a298E6684458F93bF), // role auth 26 | address(0x1Dfc23a9A81202980711A334B07038A9A1789d73), // box proxy 27 | address(0x994d90C72aD3eeB327b6f6288D544384eF53a020), // desc proxy 28 | address(0xB9d6D688E1e051CB74E5B5d1627421De56F2B4aD) // treasury proxy 29 | ); 30 | } else if (block.chainid == 1) { 31 | address timelock = LibDeploy.deployTimeLock( 32 | vm, 33 | deployParams.cyberTokenOwner, 34 | 48 * 3600, 35 | true 36 | ); 37 | LibDeploy.changeOwnership( 38 | vm, 39 | timelock, 40 | deployParams.engineGov, 41 | address(0x5cf03F4997AFa9A94506990D24c12D6aBaD61E6F), // role auth 42 | address(0xcE4F341622340d56E397740d325Fd357E62b91CB), // box proxy 43 | address(0x818CBEE6081ae4C89caBc642Ac2542b2585F68Bb), // desc proxy 44 | address(0x5DA0eD64A9868d128F8d6f56dC78B727F85ff2D0) // treasury proxy 45 | ); 46 | } 47 | vm.stopBroadcast(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /script/DeployVault.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | LibDeploy.deployVault( 14 | vm, 15 | LibDeploy.DeployParams(true, true, deployParams), 16 | deployParams.link3Signer, 17 | true 18 | ); 19 | vm.stopBroadcast(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /script/RegisterProfile.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 7 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | 14 | LibDeploy.DeployParams memory params = LibDeploy.DeployParams( 15 | true, 16 | true, 17 | deployParams 18 | ); 19 | 20 | if (block.chainid == 97) { 21 | LibDeploy.registerLink3TestProfile( 22 | vm, 23 | LibDeploy.RegisterLink3TestProfileParams( 24 | address(0xc633795bE5E61F0363e239fC21cF32dbB073Fd21), // profile 25 | address(0x7294aB1F2C1601c3da46499574e16078a42c8056), // engine 26 | address(0x342456d340D705f6B58137b57bEbEAd0069ba646), // profile mw 27 | address(0x927f355117721e0E8A7b5eA20002b65B8a551890), // toEOA 28 | params.setting.link3Treasury, 29 | params.setting.engineTreasury 30 | ) 31 | ); 32 | } else if (block.chainid == 5) { 33 | LibDeploy.registerLink3TestProfile( 34 | vm, 35 | LibDeploy.RegisterLink3TestProfileParams( 36 | address(0x7B2bc3ae8f816a431Ff438d939C44E1A502EaD25), 37 | address(0x47C282Bef1dE396Defd13878859B580636b81796), 38 | address(0x8a07C56c28FC62CAC8F42fdD1F16f0cE3141c291), 39 | address(0x927f355117721e0E8A7b5eA20002b65B8a551890), 40 | params.setting.link3Treasury, 41 | params.setting.engineTreasury 42 | ) 43 | ); 44 | } 45 | vm.stopBroadcast(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /script/SetAniURL.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 7 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | 13 | vm.startBroadcast(); 14 | if (block.chainid == DeploySetting.MAINNET) { 15 | LibDeploy.setAniURL( 16 | vm, 17 | LibDeploy.DeployParams(true, true, deployParams), 18 | address(0x818CBEE6081ae4C89caBc642Ac2542b2585F68Bb) // link3 descriptor 19 | ); 20 | } 21 | 22 | vm.stopBroadcast(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /script/SetAnimationURLV3.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 7 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 8 | 9 | contract SetAnimationURLV3 is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | vm.startBroadcast(); 13 | 14 | if (block.chainid == DeploySetting.MAINNET) { 15 | LibDeploy.deployLink3DescriptorV3( 16 | vm, 17 | deployParams.deployerContract, 18 | true, 19 | address(0x8CC6517e45dB7a0803feF220D9b577326A12033f), // link3Profile 20 | deployParams.link3Owner 21 | ); 22 | } else if (block.chainid == DeploySetting.BNBT) { 23 | LibDeploy.deployLink3DescriptorV3( 24 | vm, 25 | deployParams.deployerContract, 26 | true, 27 | address(0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271), // link3Profile 28 | deployParams.link3Owner 29 | ); 30 | } else if (block.chainid == DeploySetting.BNB) { 31 | LibDeploy.deployLink3DescriptorV3( 32 | vm, 33 | deployParams.deployerContract, 34 | true, 35 | address(0x2723522702093601e6360CAe665518C4f63e9dA6), // link3Profile 36 | deployParams.link3Owner 37 | ); 38 | } 39 | 40 | vm.stopBroadcast(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /script/SetFeeCreationMw.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 7 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | 13 | vm.startBroadcast(); 14 | 15 | if (block.chainid == DeploySetting.GOERLI) { 16 | LibDeploy.setFeeCreationMw( 17 | vm, 18 | LibDeploy.DeployParams(true, true, deployParams), 19 | address(0xAF9104Eb9c6B21Efdc43BaaaeE70662d6CcE8798), //engineProxyAddress, 20 | address(0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271), //address link3Profile, 21 | address(0xf1D8512d08F3924768041d1063Ef5517Ca867f0d) //address feeCreationMw 22 | ); 23 | } else if (block.chainid == DeploySetting.BNB) { 24 | LibDeploy.setFeeCreationMw( 25 | vm, 26 | LibDeploy.DeployParams(true, true, deployParams), 27 | address(0x1cA51941a616D14C42D3e3B9E6E687d7F5054c3A), //engineProxyAddress, 28 | address(0x2723522702093601e6360CAe665518C4f63e9dA6), //address link3Profile, 29 | address(0xE072666997B472a908e45B4B73B430dfBA9F6d33) //address feeCreationMw 30 | ); 31 | } else if (block.chainid == DeploySetting.BNBT) { 32 | LibDeploy.setFeeCreationMw( 33 | vm, 34 | LibDeploy.DeployParams(true, true, deployParams), 35 | address(0xAF9104Eb9c6B21Efdc43BaaaeE70662d6CcE8798), //engineProxyAddress, 36 | address(0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271), //address link3Profile, 37 | address(0x708e5a5Ad95520fA8fddCE8F8C86b095723E32CF) //address feeCreationMw 38 | ); 39 | } 40 | 41 | vm.stopBroadcast(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /script/SetProfileMw.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 7 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | 13 | vm.startBroadcast(); 14 | 15 | if ( 16 | block.chainid == DeploySetting.BNBT || 17 | block.chainid == DeploySetting.GOERLI 18 | ) { 19 | LibDeploy.setProfileMw( 20 | vm, 21 | LibDeploy.DeployParams(true, true, deployParams), 22 | address(0xAF9104Eb9c6B21Efdc43BaaaeE70662d6CcE8798), //engineProxyAddress, 23 | address(0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271), //address link3Profile, 24 | address(0) //address link3ProfileMw 25 | ); 26 | } else if ( 27 | block.chainid == DeploySetting.BNB || 28 | block.chainid == DeploySetting.NOVA 29 | ) { 30 | LibDeploy.setProfileMw( 31 | vm, 32 | LibDeploy.DeployParams(true, true, deployParams), 33 | address(0x1cA51941a616D14C42D3e3B9E6E687d7F5054c3A), //engineProxyAddress, 34 | address(0x2723522702093601e6360CAe665518C4f63e9dA6), //address link3Profile, 35 | address(0xd37bbF27e39B2f8c4386BebcCdA0850EEfFD2a82) //address link3ProfileMw 36 | ); 37 | } else if (block.chainid == DeploySetting.POLYGON) { 38 | LibDeploy.setProfileMw( 39 | vm, 40 | LibDeploy.DeployParams(true, true, deployParams), 41 | address(0x64E1503a2419966c51332d7f6018dE9544AD78a1), //engineProxyAddress, 42 | address(0xbF029d040e3E6DA7b768b759dD9D67D84c73C06f), //address link3Profile, 43 | address(0x8323FFc73C027D8bEA4adb255447d3F5A8B3Ad12) //address link3ProfileMw 44 | ); 45 | } 46 | 47 | vm.stopBroadcast(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /script/SetSigner.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../src/core/ProfileNFT.sol"; 7 | import { CyberEngine } from "../src/core/CyberEngine.sol"; 8 | import { Link3ProfileDescriptor } from "../src/periphery/Link3ProfileDescriptor.sol"; 9 | import { RolesAuthority } from "../src/dependencies/solmate/RolesAuthority.sol"; 10 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 11 | import { PermissionedFeeCreationMw } from "../src/middlewares/profile/PermissionedFeeCreationMw.sol"; 12 | 13 | contract DeployScript is Script { 14 | function run() external { 15 | vm.startBroadcast(); 16 | // address link3Desc = 0x3B131D2d6694a60eb71dfF607cc64E6296daa71E; 17 | // address preOwner = 0x39e0c6E610A8D7F408dD688011591583cbc1c3ce; 18 | // address newOwner = 0xf9E12df9428F1a15BC6CfD4092ADdD683738cE96; 19 | 20 | // require(Link3ProfileDescriptor(link3Desc).owner() == preOwner, "WRONG_OWNER"); 21 | // Link3ProfileDescriptor(link3Desc).setOwner(newOwner); 22 | // require(Link3ProfileDescriptor(link3Desc).owner() == newOwner, "WRONG_NEW_OWNER"); 23 | 24 | // address roleAuth = 0x9937fb8ebe4Ebc7710fFAEd246584603F390BE3E; 25 | // address preOwner = 0xA7b6bEf855c1c57Df5b7C9c7a4e1eB757e544e7f; 26 | // address newOwner = 0xf9E12df9428F1a15BC6CfD4092ADdD683738cE96; 27 | 28 | // require(RolesAuthority(roleAuth).owner() == preOwner, "WRONG_OWNER"); 29 | // RolesAuthority(roleAuth).setOwner(newOwner); 30 | // require( 31 | // RolesAuthority(roleAuth).owner() == newOwner, 32 | // "WRONG_NEW_OWNER" 33 | // ); 34 | 35 | address link3Profile = 0x2723522702093601e6360CAe665518C4f63e9dA6; 36 | address preOwner = 0x39e0c6E610A8D7F408dD688011591583cbc1c3ce; 37 | address newOwner = 0xf9E12df9428F1a15BC6CfD4092ADdD683738cE96; 38 | 39 | require( 40 | ProfileNFT(link3Profile).getNamespaceOwner() == preOwner, 41 | "WRONG_NS_OWNER" 42 | ); 43 | ProfileNFT(link3Profile).setNamespaceOwner(newOwner); 44 | require( 45 | ProfileNFT(link3Profile).getNamespaceOwner() == newOwner, 46 | "WRONG_NEW_OWNER" 47 | ); 48 | 49 | vm.stopBroadcast(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /script/SetStableFeeMw.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 7 | import { DeploySetting } from "./libraries/DeploySetting.sol"; 8 | 9 | contract DeployScript is Script, DeploySetting { 10 | function run() external { 11 | _setDeployParams(); 12 | 13 | vm.startBroadcast(); 14 | 15 | if (block.chainid == DeploySetting.GOERLI) { 16 | LibDeploy.setStableFeeMw( 17 | vm, 18 | LibDeploy.DeployParams(true, true, deployParams), 19 | address(0xAF9104Eb9c6B21Efdc43BaaaeE70662d6CcE8798), //engineProxyAddress, 20 | address(0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271), //address link3Profile, 21 | address(0x940d11e9105d7C0FFEE91E5e6B2375E3A58ec18A) //address stableFeeMw 22 | ); 23 | } else if (block.chainid == DeploySetting.BNB) { 24 | LibDeploy.setStableFeeMw( 25 | vm, 26 | LibDeploy.DeployParams(true, true, deployParams), 27 | address(0x1cA51941a616D14C42D3e3B9E6E687d7F5054c3A), //engineProxyAddress, 28 | address(0x2723522702093601e6360CAe665518C4f63e9dA6), //address link3Profile, 29 | address(0x74bB8cb35f2187285319c60974CB278361940B30) //address stableFeeMw 30 | ); 31 | } else if (block.chainid == DeploySetting.BNBT) { 32 | LibDeploy.setStableFeeMw( 33 | vm, 34 | LibDeploy.DeployParams(true, true, deployParams), 35 | address(0xAF9104Eb9c6B21Efdc43BaaaeE70662d6CcE8798), //engineProxyAddress, 36 | address(0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271), //address link3Profile, 37 | address(0) //address stableFeeMw 38 | ); 39 | } else if (block.chainid == DeploySetting.MAINNET) { 40 | LibDeploy.setStableFeeMw( 41 | vm, 42 | LibDeploy.DeployParams(true, true, deployParams), 43 | address(0xE8805326f9DA84e70c680429eD46B924b3F158F2), //engineProxyAddress, 44 | address(0x8CC6517e45dB7a0803feF220D9b577326A12033f), //address link3Profile, 45 | address(0x4C4bfA07bd28D1817D90E63a088643956f248159) //address stableFeeMw 46 | ); 47 | } else if (block.chainid == DeploySetting.POLYGON) { 48 | LibDeploy.setStableFeeMw( 49 | vm, 50 | LibDeploy.DeployParams(true, true, deployParams), 51 | address(0x64E1503a2419966c51332d7f6018dE9544AD78a1), //engineProxyAddress, 52 | address(0xbF029d040e3E6DA7b768b759dD9D67D84c73C06f), //address link3Profile, 53 | address(0x45C3D3dC105Ba805E610f7fc2F3b4Ca5E29097a7) //address stableFeeMw 54 | ); 55 | } 56 | 57 | vm.stopBroadcast(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /script/Tmp.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../src/core/ProfileNFT.sol"; 7 | import { CyberEngine } from "../src/core/CyberEngine.sol"; 8 | import { LibDeploy } from "./libraries/LibDeploy.sol"; 9 | import { PermissionedFeeCreationMw } from "../src/middlewares/profile/PermissionedFeeCreationMw.sol"; 10 | 11 | contract TempScript is Script { 12 | function run() external { 13 | address engineProxy = address( 14 | 0xE8805326f9DA84e70c680429eD46B924b3F158F2 15 | ); 16 | address link3Profile = address( 17 | 0x8CC6517e45dB7a0803feF220D9b577326A12033f 18 | ); 19 | console.log( 20 | CyberEngine(engineProxy).getProfileMwByNamespace((link3Profile)) 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /script/animation_url/anvil-31337/SetAnimationURL.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = 0x84009d423898B1c371b4515fa6540A922fF5e40a; 14 | string internal animationUrl = 15 | "https://cyberconnect.mypinata.cloud/ipfs/bafkreifjwei5tuvh5zjk7r6ti4wt7eon7dwnobchdinfmdzqhl2l2lrgve"; 16 | 17 | function run() external { 18 | _setDeployParams(); 19 | // make sure only on anvil 20 | address deployerContract = 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512; 21 | require(block.chainid == 31337, "ONLY_ANVIL"); 22 | vm.startBroadcast(); 23 | 24 | LibDeploy.deployLink3Descriptor( 25 | vm, 26 | deployerContract, 27 | true, 28 | animationUrl, 29 | link3Profile, 30 | deployParams.link3Owner 31 | ); 32 | 33 | vm.stopBroadcast(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /script/animation_url/anvil-31337/SetAnimationURL.s.sol.template: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = LINK3_PROFILE; 14 | string internal animationUrl = "ANIMATION_URL"; 15 | 16 | function run() external { 17 | _setDeployParams(); 18 | // make sure only on anvil 19 | address deployerContract = 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512; 20 | require(block.chainid == 31337, "ONLY_ANVIL"); 21 | vm.startBroadcast(); 22 | 23 | LibDeploy.deployLink3Descriptor( 24 | vm, 25 | deployerContract, 26 | true, 27 | animationUrl, 28 | link3Profile, 29 | deployParams.link3Owner 30 | ); 31 | 32 | vm.stopBroadcast(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /script/animation_url/bnb-56/SetAnimationURL.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = 0x2723522702093601e6360CAe665518C4f63e9dA6; 14 | string internal animationUrl = 15 | "https://cyberconnect.mypinata.cloud/ipfs/bafkreiblu7mqgd43bmenvsyfcp33pkrtjyc52ofwectc2257uicatn6vzm"; 16 | 17 | function run() external { 18 | _setDeployParams(); 19 | // make sure only on anvil 20 | require(block.chainid == 56, "ONLY_BNB"); 21 | vm.startBroadcast(); 22 | 23 | LibDeploy.deployLink3Descriptor( 24 | vm, 25 | deployParams.deployerContract, 26 | true, 27 | animationUrl, 28 | link3Profile, 29 | deployParams.link3Owner 30 | ); 31 | 32 | vm.stopBroadcast(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /script/animation_url/bnb-56/SetAnimationURL.s.sol.template: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = LINK3_PROFILE; 14 | string internal animationUrl = "ANIMATION_URL"; 15 | 16 | function run() external { 17 | _setDeployParams(); 18 | // make sure only on anvil 19 | require(block.chainid == 56, "ONLY_BNB"); 20 | vm.startBroadcast(); 21 | 22 | LibDeploy.deployLink3Descriptor( 23 | vm, 24 | deployParams.deployerContract, 25 | true, 26 | animationUrl, 27 | link3Profile, 28 | deployParams.link3Owner 29 | ); 30 | 31 | vm.stopBroadcast(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /script/animation_url/bnbt-97/SetAnimationURL.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = 0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271; 14 | string internal animationUrl = 15 | "https://cyberconnect.mypinata.cloud/ipfs/bafkreigqqa3tkzqkl7bjylkya5nf5qsyyjcunsp4ix525icn5nycf7nw2m"; 16 | 17 | function run() external { 18 | _setDeployParams(); 19 | // make sure only on anvil 20 | require(block.chainid == 97, "ONLY_BNBT"); 21 | vm.startBroadcast(); 22 | 23 | LibDeploy.deployLink3Descriptor( 24 | vm, 25 | deployParams.deployerContract, 26 | true, 27 | animationUrl, 28 | link3Profile, 29 | deployParams.link3Owner 30 | ); 31 | 32 | vm.stopBroadcast(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /script/animation_url/bnbt-97/SetAnimationURL.s.sol.template: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = LINK3_PROFILE; 14 | string internal animationUrl = "ANIMATION_URL"; 15 | 16 | function run() external { 17 | _setDeployParams(); 18 | // make sure only on anvil 19 | require(block.chainid == 97, "ONLY_BNBT"); 20 | vm.startBroadcast(); 21 | 22 | LibDeploy.deployLink3Descriptor( 23 | vm, 24 | deployParams.deployerContract, 25 | true, 26 | animationUrl, 27 | link3Profile, 28 | deployParams.link3Owner 29 | ); 30 | 31 | vm.stopBroadcast(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /script/animation_url/goerli-5/SetAnimationURL.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = 0x57e12b7a5F38A7F9c23eBD0400e6E53F2a45F271; 14 | string internal animationUrl = 15 | "https://cyberconnect.mypinata.cloud/ipfs/bafkreic7ur7evrpy45md2xpth3zvy4mjcczzodjg7xciupty6dvmliye6i"; 16 | 17 | function run() external { 18 | _setDeployParams(); 19 | // make sure only on anvil 20 | require(block.chainid == 5, "ONLY_GOERLI"); 21 | vm.startBroadcast(); 22 | 23 | LibDeploy.deployLink3Descriptor( 24 | vm, 25 | deployParams.deployerContract, 26 | true, 27 | animationUrl, 28 | link3Profile, 29 | deployParams.link3Owner 30 | ); 31 | 32 | vm.stopBroadcast(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /script/animation_url/goerli-5/SetAnimationURL.s.sol.template: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = LINK3_PROFILE; 14 | string internal animationUrl = "ANIMATION_URL"; 15 | 16 | function run() external { 17 | _setDeployParams(); 18 | // make sure only on anvil 19 | require(block.chainid == 5, "ONLY_GOERLI"); 20 | vm.startBroadcast(); 21 | 22 | LibDeploy.deployLink3Descriptor( 23 | vm, 24 | deployParams.deployerContract, 25 | true, 26 | animationUrl, 27 | link3Profile, 28 | deployParams.link3Owner 29 | ); 30 | 31 | vm.stopBroadcast(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /script/animation_url/mainnet-1/SetAnimationURL.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = 0x8CC6517e45dB7a0803feF220D9b577326A12033f; 14 | string internal animationUrl = 15 | "https://cyberconnect.mypinata.cloud/ipfs/bafkreigjfjobgbh6voodb4z4u3nfpuchwb5usolon6i67kecelki2uzb6y"; 16 | 17 | function run() external { 18 | _setDeployParams(); 19 | // make sure only on anvil 20 | require(block.chainid == 1, "ONLY_MAINNET"); 21 | vm.startBroadcast(); 22 | 23 | LibDeploy.deployLink3Descriptor( 24 | vm, 25 | deployParams.deployerContract, 26 | true, 27 | animationUrl, 28 | link3Profile, 29 | deployParams.link3Owner 30 | ); 31 | 32 | vm.stopBroadcast(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /script/animation_url/mainnet-1/SetAnimationURL.s.sol.template: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = LINK3_PROFILE; 14 | string internal animationUrl = "ANIMATION_URL"; 15 | 16 | function run() external { 17 | _setDeployParams(); 18 | // make sure only on anvil 19 | require(block.chainid == 1, "ONLY_MAINNET"); 20 | vm.startBroadcast(); 21 | 22 | LibDeploy.deployLink3Descriptor( 23 | vm, 24 | deployParams.deployerContract, 25 | true, 26 | animationUrl, 27 | link3Profile, 28 | deployParams.link3Owner 29 | ); 30 | 31 | vm.stopBroadcast(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /script/animation_url/nova-42170/SetAnimationURL.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = 0x2723522702093601e6360CAe665518C4f63e9dA6; 14 | string internal animationUrl = 15 | "https://cyberconnect.mypinata.cloud/ipfs/bafkreiaiurmd4gpnu4nqjlddbt2r57ipshpsz77bf7mybun36psiggrbui"; 16 | 17 | function run() external { 18 | _setDeployParams(); 19 | // make sure only on anvil 20 | require(block.chainid == 42170, "ONLY_NOVA"); 21 | vm.startBroadcast(); 22 | 23 | LibDeploy.deployLink3Descriptor( 24 | vm, 25 | deployParams.deployerContract, 26 | true, 27 | animationUrl, 28 | link3Profile, 29 | deployParams.link3Owner 30 | ); 31 | 32 | vm.stopBroadcast(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /script/animation_url/nova-42170/SetAnimationURL.s.sol.template: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = LINK3_PROFILE; 14 | string internal animationUrl = "ANIMATION_URL"; 15 | 16 | function run() external { 17 | _setDeployParams(); 18 | // make sure only on anvil 19 | require(block.chainid == 42170, "ONLY_NOVA"); 20 | vm.startBroadcast(); 21 | 22 | LibDeploy.deployLink3Descriptor( 23 | vm, 24 | deployParams.deployerContract, 25 | true, 26 | animationUrl, 27 | link3Profile, 28 | deployParams.link3Owner 29 | ); 30 | 31 | vm.stopBroadcast(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /script/animation_url/polygon-137/SetAnimationURL.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = 0xbF029d040e3E6DA7b768b759dD9D67D84c73C06f; 14 | string internal animationUrl = 15 | "https://cyberconnect.mypinata.cloud/ipfs/bafkreiebcj2it5hirwrfbfhjlwr7pxbjqvojtxht4bcjhvvnjxqwomqqly"; 16 | 17 | function run() external { 18 | _setDeployParams(); 19 | // make sure only on anvil 20 | require(block.chainid == 137, "ONLY_POLYGON"); 21 | vm.startBroadcast(); 22 | 23 | LibDeploy.deployLink3Descriptor( 24 | vm, 25 | deployParams.deployerContract, 26 | true, 27 | animationUrl, 28 | link3Profile, 29 | deployParams.link3Owner 30 | ); 31 | 32 | vm.stopBroadcast(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /script/animation_url/polygon-137/SetAnimationURL.s.sol.template: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = LINK3_PROFILE; 14 | string internal animationUrl = "ANIMATION_URL"; 15 | 16 | function run() external { 17 | _setDeployParams(); 18 | // make sure only on anvil 19 | require(block.chainid == 137, "ONLY_POLYGON"); 20 | vm.startBroadcast(); 21 | 22 | LibDeploy.deployLink3Descriptor( 23 | vm, 24 | deployParams.deployerContract, 25 | true, 26 | animationUrl, 27 | link3Profile, 28 | deployParams.link3Owner 29 | ); 30 | 31 | vm.stopBroadcast(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /script/animation_url/rinkeby-4/SetAnimationURL.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = 0xb9FDA6C1C56dC7AC3aE787a46fD3434DA991626D; 14 | string internal animationUrl = 15 | "https://cyberconnect.mypinata.cloud/ipfs/bafkreifq5vu6gl4q4c5fb23m5w3wyijumonpfb7dki7eodx2222ogfb3lu"; 16 | 17 | function run() external { 18 | _setDeployParams(); 19 | // make sure only on anvil 20 | require(block.chainid == 4, "ONLY_RINKEBY"); 21 | vm.startBroadcast(); 22 | 23 | LibDeploy.deployLink3Descriptor( 24 | vm, 25 | deployParams.deployerContract, 26 | true, 27 | animationUrl, 28 | link3Profile, 29 | deployParams.link3Owner 30 | ); 31 | 32 | vm.stopBroadcast(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /script/animation_url/rinkeby-4/SetAnimationURL.s.sol.template: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Script.sol"; 6 | import { ProfileNFT } from "../../../src/core/ProfileNFT.sol"; 7 | import { Link3ProfileDescriptor } from "../../../src/periphery/Link3ProfileDescriptor.sol"; 8 | import { Create2Deployer } from "../../../src/deployer/Create2Deployer.sol"; 9 | import { LibDeploy } from "../../libraries/LibDeploy.sol"; 10 | import { DeploySetting } from "../../libraries/DeploySetting.sol"; 11 | 12 | contract SetAnimationURL is Script, DeploySetting { 13 | address internal link3Profile = LINK3_PROFILE; 14 | string internal animationUrl = "ANIMATION_URL"; 15 | 16 | function run() external { 17 | _setDeployParams(); 18 | // make sure only on anvil 19 | require(block.chainid == 4, "ONLY_RINKEBY"); 20 | vm.startBroadcast(); 21 | 22 | LibDeploy.deployLink3Descriptor( 23 | vm, 24 | deployParams.deployerContract, 25 | true, 26 | animationUrl, 27 | link3Profile, 28 | deployParams.link3Owner 29 | ); 30 | 31 | vm.stopBroadcast(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /script/libraries/DeployNamespace.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | import "forge-std/console.sol"; 5 | import "forge-std/Vm.sol"; 6 | import "./LibDeploy.sol"; 7 | 8 | library DeployNamespace { 9 | struct DeployNamespaceParams { 10 | address engineProxy; 11 | address namespaceOwner; 12 | string name; 13 | string symbol; 14 | address profileFac; 15 | address subFac; 16 | address essFac; 17 | } 18 | 19 | function deployNamespace(Vm vm, DeployNamespaceParams memory params) 20 | internal 21 | returns (address) 22 | { 23 | bytes32 salt = keccak256(bytes(params.name)); 24 | (address profile, , ) = LibDeploy.createNamespace( 25 | params.engineProxy, 26 | params.namespaceOwner, 27 | params.name, 28 | params.symbol, 29 | salt, 30 | params.profileFac, 31 | params.subFac, 32 | params.essFac 33 | ); 34 | LibDeploy._write( 35 | vm, 36 | string(abi.encodePacked(params.name, " profile")), 37 | profile 38 | ); 39 | return profile; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /slither.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "filter_paths": "lib|test|src/dependencies", 3 | "solc_remaps": [ 4 | "ds-test/=lib/ds-test/src/", 5 | "forge-std/=lib/forge-std/src/", 6 | "openzeppelin-contracts/=lib/openzeppelin-contracts/", 7 | "solmate/=lib/solmate/src/" 8 | ] 9 | } -------------------------------------------------------------------------------- /src/base/EIP712.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { DataTypes } from "../libraries/DataTypes.sol"; 6 | 7 | abstract contract EIP712 { 8 | /*////////////////////////////////////////////////////////////// 9 | STATES 10 | //////////////////////////////////////////////////////////////*/ 11 | bytes32 internal constant _HASHED_VERSION = keccak256("1"); 12 | bytes32 private constant _TYPE_HASH = 13 | keccak256( 14 | "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" 15 | ); 16 | 17 | /*////////////////////////////////////////////////////////////// 18 | PUBLIC VIEW 19 | //////////////////////////////////////////////////////////////*/ 20 | 21 | /** 22 | * @notice Returns the contract's {EIP712} domain separator. 23 | * 24 | * @return bytes32 the contract's {EIP712} domain separator. 25 | */ 26 | // solhint-disable-next-line func-name-mixedcase 27 | function DOMAIN_SEPARATOR() public view returns (bytes32) { 28 | return 29 | keccak256( 30 | abi.encode( 31 | _TYPE_HASH, 32 | keccak256(bytes(_domainSeparatorName())), 33 | _HASHED_VERSION, 34 | block.chainid, 35 | address(this) 36 | ) 37 | ); 38 | } 39 | 40 | /*////////////////////////////////////////////////////////////// 41 | INTERNAL 42 | //////////////////////////////////////////////////////////////*/ 43 | 44 | function _requiresExpectedSigner( 45 | bytes32 digest, 46 | address expectedSigner, 47 | uint8 v, 48 | bytes32 r, 49 | bytes32 s, 50 | uint256 deadline 51 | ) internal view { 52 | require(deadline >= block.timestamp, "DEADLINE_EXCEEDED"); 53 | require( 54 | uint256(s) <= 55 | 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, 56 | "INVALID_SIGNATURE_S_VAULE" 57 | ); 58 | 59 | address recoveredAddress = ecrecover(digest, v, r, s); 60 | require(recoveredAddress == expectedSigner, "INVALID_SIGNATURE"); 61 | } 62 | 63 | function _requiresExpectedSigner( 64 | bytes32 digest, 65 | address expectedSigner, 66 | DataTypes.EIP712Signature calldata sig 67 | ) internal view { 68 | _requiresExpectedSigner( 69 | digest, 70 | expectedSigner, 71 | sig.v, 72 | sig.r, 73 | sig.s, 74 | sig.deadline 75 | ); 76 | } 77 | 78 | function _hashTypedDataV4(bytes32 structHash) 79 | internal 80 | view 81 | virtual 82 | returns (bytes32) 83 | { 84 | return 85 | keccak256( 86 | abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), structHash) 87 | ); 88 | } 89 | 90 | function _domainSeparatorName() 91 | internal 92 | view 93 | virtual 94 | returns (string memory); 95 | } 96 | -------------------------------------------------------------------------------- /src/dependencies/openzeppelin/Pausable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev modified from OpenZeppelin Pausable.sol, removing Context 8 | * 9 | * @dev Contract module which allows children to implement an emergency stop 10 | * mechanism that can be triggered by an authorized account. 11 | * 12 | * This module is used through inheritance. It will make available the 13 | * modifiers `whenNotPaused` and `whenPaused`, which can be applied to 14 | * the functions of your contract. Note that they will not be pausable by 15 | * simply including this module, only once the modifiers are put in place. 16 | */ 17 | abstract contract Pausable { 18 | /** 19 | * @dev Emitted when the pause is triggered by `account`. 20 | */ 21 | event Paused(address account); 22 | 23 | /** 24 | * @dev Emitted when the pause is lifted by `account`. 25 | */ 26 | event Unpaused(address account); 27 | 28 | bool private _paused; 29 | 30 | /** 31 | * @dev Modifier to make a function callable only when the contract is not paused. 32 | * 33 | * Requirements: 34 | * 35 | * - The contract must not be paused. 36 | */ 37 | modifier whenNotPaused() { 38 | _requireNotPaused(); 39 | _; 40 | } 41 | 42 | /** 43 | * @dev Modifier to make a function callable only when the contract is paused. 44 | * 45 | * Requirements: 46 | * 47 | * - The contract must be paused. 48 | */ 49 | modifier whenPaused() { 50 | _requirePaused(); 51 | _; 52 | } 53 | 54 | /** 55 | * @dev Returns true if the contract is paused, and false otherwise. 56 | */ 57 | function paused() public view virtual returns (bool) { 58 | return _paused; 59 | } 60 | 61 | /** 62 | * @dev Throws if the contract is paused. 63 | */ 64 | function _requireNotPaused() internal view virtual { 65 | require(!paused(), "Pausable: paused"); 66 | } 67 | 68 | /** 69 | * @dev Throws if the contract is not paused. 70 | */ 71 | function _requirePaused() internal view virtual { 72 | require(paused(), "Pausable: not paused"); 73 | } 74 | 75 | /** 76 | * @dev Triggers stopped state. 77 | * 78 | * Requirements: 79 | * 80 | * - The contract must not be paused. 81 | */ 82 | function _pause() internal virtual whenNotPaused { 83 | _paused = true; 84 | emit Paused(msg.sender); 85 | } 86 | 87 | /** 88 | * @dev Returns to normal state. 89 | * 90 | * Requirements: 91 | * 92 | * - The contract must be paused. 93 | */ 94 | function _unpause() internal virtual whenPaused { 95 | _paused = false; 96 | emit Unpaused(msg.sender); 97 | } 98 | } -------------------------------------------------------------------------------- /src/dependencies/openzeppelin/ReentrancyGuard.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // OpenZeppelin Contracts v4.7.0 (security/ReentrancyGuard.sol) 3 | 4 | import { Initializable } from "openzeppelin-contracts/contracts/proxy/utils/Initializable.sol"; 5 | 6 | pragma solidity ^0.8.0; 7 | 8 | /** 9 | * @dev modified from OpenZeppelin ReentrancyGuard.sol adding initialize func 10 | * 11 | * @dev Contract module that helps prevent reentrant calls to a function. 12 | * 13 | * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier 14 | * available, which can be applied to functions to make sure there are no nested 15 | * (reentrant) calls to them. 16 | * 17 | * Note that because there is a single `nonReentrant` guard, functions marked as 18 | * `nonReentrant` may not call one another. This can be worked around by making 19 | * those functions `private`, and then adding `external` `nonReentrant` entry 20 | * points to them. 21 | * 22 | * TIP: If you would like to learn more about reentrancy and alternative ways 23 | * to protect against it, check out our blog post 24 | * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. 25 | */ 26 | abstract contract ReentrancyGuard is Initializable { 27 | // Booleans are more expensive than uint256 or any type that takes up a full 28 | // word because each write operation emits an extra SLOAD to first read the 29 | // slot's contents, replace the bits taken up by the boolean, and then write 30 | // back. This is the compiler's defense against contract upgrades and 31 | // pointer aliasing, and it cannot be disabled. 32 | 33 | // The values being non-zero value makes deployment a bit more expensive, 34 | // but in exchange the refund on every call to nonReentrant will be lower in 35 | // amount. Since refunds are capped to a percentage of the total 36 | // transaction's gas, it is best to keep them low in cases like this one, to 37 | // increase the likelihood of the full refund coming into effect. 38 | uint256 private constant _NOT_ENTERED = 1; 39 | uint256 private constant _ENTERED = 2; 40 | 41 | uint256 private _status; 42 | 43 | 44 | function __ReentrancyGuard_init() internal onlyInitializing { 45 | _status = _NOT_ENTERED; 46 | } 47 | 48 | /** 49 | * @dev Prevents a contract from calling itself, directly or indirectly. 50 | * Calling a `nonReentrant` function from another `nonReentrant` 51 | * function is not supported. It is possible to prevent this from happening 52 | * by making the `nonReentrant` function external, and making it call a 53 | * `private` function that does the actual work. 54 | */ 55 | modifier nonReentrant() { 56 | // On the first call to nonReentrant, _notEntered will be true 57 | require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); 58 | 59 | // Any calls to nonReentrant after this point will fail 60 | _status = _ENTERED; 61 | 62 | _; 63 | 64 | // By storing the original value once again, a refund is triggered (see 65 | // https://eips.ethereum.org/EIPS/eip-2200) 66 | _status = _NOT_ENTERED; 67 | } 68 | } -------------------------------------------------------------------------------- /src/dependencies/solmate/Auth.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity >=0.8.0; 4 | 5 | import { Initializable } from "openzeppelin-contracts/contracts/proxy/utils/Initializable.sol"; 6 | 7 | /// @notice Adapted from Solmate's Auth.sol with initializer replacing the constructor. 8 | 9 | /// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic. 10 | /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Auth.sol) 11 | /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) 12 | abstract contract Auth is Initializable { 13 | event OwnerUpdated(address indexed user, address indexed newOwner); 14 | 15 | event AuthorityUpdated(address indexed user, Authority indexed newAuthority); 16 | 17 | address public owner; 18 | 19 | Authority public authority; 20 | 21 | function __Auth_Init(address _owner, Authority _authority) internal onlyInitializing { 22 | owner = _owner; 23 | authority = _authority; 24 | 25 | emit OwnerUpdated(msg.sender, _owner); 26 | emit AuthorityUpdated(msg.sender, _authority); 27 | } 28 | 29 | modifier requiresAuth() virtual { 30 | require(isAuthorized(msg.sender, msg.sig), "UNAUTHORIZED"); 31 | 32 | _; 33 | } 34 | 35 | function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) { 36 | Authority auth = authority; // Memoizing authority saves us a warm SLOAD, around 100 gas. 37 | 38 | // Checking if the caller is the owner only after calling the authority saves gas in most cases, but be 39 | // aware that this makes protected functions uncallable even to the owner if the authority is out of order. 40 | return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) || user == owner; 41 | } 42 | 43 | function setAuthority(Authority newAuthority) public virtual { 44 | // We check if the caller is the owner first because we want to ensure they can 45 | // always swap out the authority even if it's reverting or using up a lot of gas. 46 | require(msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig), "UNAUTHORIZED"); 47 | 48 | authority = newAuthority; 49 | 50 | emit AuthorityUpdated(msg.sender, newAuthority); 51 | } 52 | 53 | function setOwner(address newOwner) public virtual requiresAuth { 54 | owner = newOwner; 55 | 56 | emit OwnerUpdated(msg.sender, newOwner); 57 | } 58 | } 59 | 60 | /// @notice A generic interface for a contract which provides authorization data to an Auth instance. 61 | /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Auth.sol) 62 | /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) 63 | interface Authority { 64 | function canCall( 65 | address user, 66 | address target, 67 | bytes4 functionSig 68 | ) external view returns (bool); 69 | } -------------------------------------------------------------------------------- /src/dependencies/solmate/Owned.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | import { Initializable } from "openzeppelin-contracts/contracts/proxy/utils/Initializable.sol"; 4 | 5 | pragma solidity >=0.8.0; 6 | 7 | /// @notice Adapted from Solmate's Owned.sol with initializer replacing the constructor. 8 | 9 | /// @notice Simple single owner authorization mixin. 10 | /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol) 11 | abstract contract Owned is Initializable { 12 | /*////////////////////////////////////////////////////////////// 13 | EVENTS 14 | //////////////////////////////////////////////////////////////*/ 15 | 16 | event OwnerUpdated(address indexed user, address indexed newOwner); 17 | 18 | /*////////////////////////////////////////////////////////////// 19 | OWNERSHIP STORAGE 20 | //////////////////////////////////////////////////////////////*/ 21 | 22 | address public owner; 23 | 24 | modifier onlyOwner() virtual { 25 | require(msg.sender == owner, "UNAUTHORIZED"); 26 | 27 | _; 28 | } 29 | 30 | /*////////////////////////////////////////////////////////////// 31 | CONSTRUCTOR 32 | //////////////////////////////////////////////////////////////*/ 33 | 34 | function __Owned_Init(address _owner) internal onlyInitializing { 35 | require(_owner != address(0), "ZERO_ADDRESS"); 36 | owner = _owner; 37 | 38 | emit OwnerUpdated(address(0), _owner); 39 | } 40 | 41 | /*////////////////////////////////////////////////////////////// 42 | OWNERSHIP LOGIC 43 | //////////////////////////////////////////////////////////////*/ 44 | 45 | function setOwner(address newOwner) public virtual onlyOwner { 46 | require(newOwner != address(0), "ZERO_ADDRESS"); 47 | owner = newOwner; 48 | 49 | emit OwnerUpdated(msg.sender, newOwner); 50 | } 51 | } -------------------------------------------------------------------------------- /src/deployer/Create2Deployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity 0.8.14; 3 | 4 | contract Create2Deployer { 5 | event Deployed(address addr, bytes32 salt); 6 | 7 | function deploy(bytes memory code, bytes32 salt) public returns (address) { 8 | address addr; 9 | require(code.length != 0, "Create2: bytecode length is zero"); 10 | assembly { 11 | addr := create2(0, add(code, 0x20), mload(code), salt) 12 | if iszero(extcodesize(addr)) { 13 | revert(0, 0) 14 | } 15 | } 16 | 17 | emit Deployed(addr, salt); 18 | return addr; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/deployer/EssenceDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { IEssenceDeployer } from "../interfaces/IEssenceDeployer.sol"; 6 | 7 | import { DataTypes } from "../libraries/DataTypes.sol"; 8 | 9 | import { EssenceNFT } from "../core/EssenceNFT.sol"; 10 | 11 | contract EssenceDeployer is IEssenceDeployer { 12 | DataTypes.EssenceDeployParameters public override essParams; 13 | 14 | /// @inheritdoc IEssenceDeployer 15 | function deployEssence(bytes32 salt, address profileProxy) 16 | external 17 | override 18 | returns (address addr) 19 | { 20 | essParams.profileProxy = profileProxy; 21 | addr = address(new EssenceNFT{ salt: salt }()); 22 | delete essParams; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/deployer/ProfileDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { IProfileDeployer } from "../interfaces/IProfileDeployer.sol"; 6 | 7 | import { DataTypes } from "../libraries/DataTypes.sol"; 8 | 9 | import { ProfileNFT } from "../core/ProfileNFT.sol"; 10 | 11 | contract ProfileDeployer is IProfileDeployer { 12 | DataTypes.ProfileDeployParameters public override profileParams; 13 | 14 | /// @inheritdoc IProfileDeployer 15 | function deployProfile( 16 | bytes32 salt, 17 | address engine, 18 | address subscribeBeacon, 19 | address essenceBeacon 20 | ) external override returns (address addr) { 21 | profileParams.engine = engine; 22 | profileParams.essenceBeacon = essenceBeacon; 23 | profileParams.subBeacon = subscribeBeacon; 24 | addr = address(new ProfileNFT{ salt: salt }()); 25 | delete profileParams; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/deployer/SubscribeDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ISubscribeDeployer } from "../interfaces/ISubscribeDeployer.sol"; 6 | 7 | import { DataTypes } from "../libraries/DataTypes.sol"; 8 | 9 | import { SubscribeNFT } from "../core/SubscribeNFT.sol"; 10 | 11 | contract SubscribeDeployer is ISubscribeDeployer { 12 | DataTypes.SubscribeDeployParameters public override subParams; 13 | 14 | /// @inheritdoc ISubscribeDeployer 15 | function deploySubscribe(bytes32 salt, address profileProxy) 16 | external 17 | override 18 | returns (address addr) 19 | { 20 | subParams.profileProxy = profileProxy; 21 | addr = address(new SubscribeNFT{ salt: salt }()); 22 | delete subParams; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/interfaces/ICyberBox.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ICyberBoxEvents } from "../interfaces/ICyberBoxEvents.sol"; 6 | 7 | interface ICyberBox is ICyberBoxEvents { 8 | /** 9 | * @notice Gets the signer for the CyberBox NFT. 10 | * 11 | * @return address The signer of CyberBox NFT. 12 | */ 13 | function getSigner() external view returns (address); 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/ICyberBoxEvents.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface ICyberBoxEvents { 6 | /** 7 | * @notice Emiited when the CyberBox is initialized. 8 | * 9 | * @param owner The address of the CyberBox owner. 10 | * @param signer The address of the CyberBox signer. 11 | * @param name The name for the CyberBox. 12 | * @param symbol The symbol for the CyberBox. 13 | */ 14 | event Initialize( 15 | address indexed owner, 16 | address indexed signer, 17 | string name, 18 | string symbol 19 | ); 20 | 21 | /** 22 | * @notice Emitted when a new signer has been set. 23 | * 24 | * @param preSigner The previous signer address. 25 | * @param newSigner The newly set signer address. 26 | */ 27 | event SetSigner(address indexed preSigner, address indexed newSigner); 28 | 29 | /** 30 | * @notice Emitted when a profile claims a box nft. 31 | * 32 | * @param to The claimer address. 33 | * @param boxId The box id that has been claimed. 34 | */ 35 | event ClaimBox(address indexed to, uint256 indexed boxId); 36 | } 37 | -------------------------------------------------------------------------------- /src/interfaces/ICyberEngineEvents.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { DataTypes } from "../libraries/DataTypes.sol"; 6 | 7 | interface ICyberEngineEvents { 8 | /** 9 | * @notice Emiited when the engine is initialized 10 | * 11 | * @param owner The address of the engine owner. 12 | * @param rolesAuthority The address of the role authority. 13 | */ 14 | event Initialize(address indexed owner, address indexed rolesAuthority); 15 | 16 | /** 17 | * @notice Emitted when a profile middleware has been allowed. 18 | * 19 | * @param mw The middleware address. 20 | * @param preAllowed The previously allow state. 21 | * @param newAllowed The newly set allow state. 22 | */ 23 | event AllowProfileMw( 24 | address indexed mw, 25 | bool indexed preAllowed, 26 | bool indexed newAllowed 27 | ); 28 | 29 | /** 30 | * @notice Emitted when a profile middleware has been set. 31 | * 32 | * @param namespace The namespace address. 33 | * @param mw The middleware address. 34 | * @param returnData The profile middeware data. 35 | */ 36 | event SetProfileMw(address indexed namespace, address mw, bytes returnData); 37 | 38 | /** 39 | * @notice Emitted when a subscription middleware has been allowed. 40 | * 41 | * @param mw The middleware address. 42 | * @param preAllowed The previously allow state. 43 | * @param newAllowed The newly set allow state. 44 | */ 45 | event AllowSubscribeMw( 46 | address indexed mw, 47 | bool indexed preAllowed, 48 | bool indexed newAllowed 49 | ); 50 | 51 | /** 52 | * @notice Emitted when a essence middleware has been allowed. 53 | * 54 | * @param mw The middleware address. 55 | * @param preAllowed The previously allow state. 56 | * @param newAllowed The newly set allow state. 57 | */ 58 | event AllowEssenceMw( 59 | address indexed mw, 60 | bool indexed preAllowed, 61 | bool indexed newAllowed 62 | ); 63 | 64 | /** 65 | * @notice Emitted when a namespace has been created 66 | * 67 | * @param namespace The namespace address. 68 | * @param name The namespace name. 69 | * @param symbol The namespace symbol. 70 | */ 71 | event CreateNamespace( 72 | address indexed namespace, 73 | string name, 74 | string symbol 75 | ); 76 | } 77 | -------------------------------------------------------------------------------- /src/interfaces/ICyberGrand.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ICyberGrandEvents } from "../interfaces/ICyberGrandEvents.sol"; 6 | 7 | interface ICyberGrand is ICyberGrandEvents { 8 | /** 9 | * @notice Gets the signer for the CyberGrand NFT. 10 | * 11 | * @return address The signer of CyberGrand NFT. 12 | */ 13 | function getSigner() external view returns (address); 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/ICyberGrandEvents.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface ICyberGrandEvents { 6 | /** 7 | * @notice Emiited when the CyberGrand is initialized. 8 | * 9 | * @param owner The address of the CyberGrand owner. 10 | * @param signer The address of the CyberGrand signer. 11 | * @param name The name for the CyberGrand. 12 | * @param symbol The symbol for the CyberGrand. 13 | * @param uri The uri for the CyberGrand. 14 | */ 15 | event Initialize( 16 | address indexed owner, 17 | address indexed signer, 18 | string name, 19 | string symbol, 20 | string uri 21 | ); 22 | 23 | /** 24 | * @notice Emitted when a new signer has been set. 25 | * 26 | * @param preSigner The previous signer address. 27 | * @param newSigner The newly set signer address. 28 | */ 29 | event SetSigner(address indexed preSigner, address indexed newSigner); 30 | 31 | /** 32 | * @notice Emitted when a grand nft has been claimed. 33 | * 34 | * @param to The claimer address. 35 | * @param tokenId The token id that has been claimed. 36 | */ 37 | event ClaimGrand(address indexed to, uint256 indexed tokenId); 38 | } 39 | -------------------------------------------------------------------------------- /src/interfaces/ICyberNFTBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { DataTypes } from "../libraries/DataTypes.sol"; 6 | 7 | interface ICyberNFTBase { 8 | /** 9 | * @notice Gets total number of tokens in existence, burned tokens will reduce the count. 10 | * 11 | * @return uint256 The total supply. 12 | */ 13 | function totalSupply() external view returns (uint256); 14 | 15 | /** 16 | * @notice Gets the total number of minted tokens. 17 | * 18 | * @return uint256 The total minted tokens. 19 | */ 20 | function totalMinted() external view returns (uint256); 21 | 22 | /** 23 | * @notice Gets the total number of burned tokens. 24 | * 25 | * @return uint256 The total burned tokens. 26 | */ 27 | function totalBurned() external view returns (uint256); 28 | 29 | /** 30 | * @notice The EIP-712 permit function. 31 | * 32 | * @param spender The spender address. 33 | * @param tokenId The token ID to approve. 34 | * @param sig Must produce valid EIP712 signature with `s`, `r`, `v` and `deadline`. 35 | */ 36 | function permit( 37 | address spender, 38 | uint256 tokenId, 39 | DataTypes.EIP712Signature calldata sig 40 | ) external; 41 | 42 | /** 43 | * @notice Burns a token. 44 | * 45 | * @param tokenId The token ID to burn. 46 | */ 47 | function burn(uint256 tokenId) external; 48 | } 49 | -------------------------------------------------------------------------------- /src/interfaces/IEssenceDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface IEssenceDeployer { 6 | /** 7 | * @notice Parameters when constructing a EssenceNFT. 8 | * 9 | * @return profileProxy The ProfileNFT proxy address. 10 | */ 11 | function essParams() external view returns (address profileProxy); 12 | 13 | /** 14 | * @notice Deploy a new EssenceNFT. 15 | * 16 | * @param salt The salt used to generate contract address in a deterministic way. 17 | * @param profileProxy The CyberEngine address. 18 | * 19 | * @return addr The newly deployed EssenceNFT address. 20 | */ 21 | function deployEssence(bytes32 salt, address profileProxy) 22 | external 23 | returns (address addr); 24 | } 25 | -------------------------------------------------------------------------------- /src/interfaces/IEssenceMiddleware.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface IEssenceMiddleware { 6 | /** 7 | * @notice Sets essence related data for middleware. 8 | * 9 | * @param profileId The profile id that owns this middleware. 10 | * @param essenceId The essence id that owns this middleware. 11 | * @param data Extra data to set. 12 | */ 13 | function setEssenceMwData( 14 | uint256 profileId, 15 | uint256 essenceId, 16 | bytes calldata data 17 | ) external returns (bytes memory); 18 | 19 | /** 20 | * @notice Process that runs before the essenceNFT mint happens. 21 | * 22 | * @param profileId The profile Id. 23 | * @param essenceId The essence Id. 24 | * @param collector The collector address. 25 | * @param essenceNFT The essence nft address. 26 | * @param data Extra data to process. 27 | */ 28 | function preProcess( 29 | uint256 profileId, 30 | uint256 essenceId, 31 | address collector, 32 | address essenceNFT, 33 | bytes calldata data 34 | ) external; 35 | 36 | /** 37 | * @notice Process that runs after the essenceNFT mint happens. 38 | * 39 | * @param profileId The profile Id. 40 | * @param essenceId The essence Id. 41 | * @param collector The collector address. 42 | * @param essenceNFT The essence nft address. 43 | * @param data Extra data to process. 44 | */ 45 | function postProcess( 46 | uint256 profileId, 47 | uint256 essenceId, 48 | address collector, 49 | address essenceNFT, 50 | bytes calldata data 51 | ) external; 52 | } 53 | -------------------------------------------------------------------------------- /src/interfaces/IEssenceNFT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { IEssenceNFTEvents } from "./IEssenceNFTEvents.sol"; 6 | 7 | interface IEssenceNFT is IEssenceNFTEvents { 8 | /** 9 | * @notice Mints the Essence NFT. 10 | * 11 | * @param to The recipient address. 12 | * @return uint256 The token id. 13 | */ 14 | function mint(address to) external returns (uint256); 15 | 16 | /** 17 | * @notice Initializes the Essence NFT. 18 | * 19 | * @param profileId The profile ID for the Essence NFT. 20 | * @param essenceId The essence ID for the Essence NFT. 21 | * @param name The name for the Essence NFT. 22 | * @param symbol The symbol for the Essence NFT. 23 | * @param transferable Whether the Essence NFT is transferable. 24 | */ 25 | function initialize( 26 | uint256 profileId, 27 | uint256 essenceId, 28 | string calldata name, 29 | string calldata symbol, 30 | bool transferable 31 | ) external; 32 | 33 | /** 34 | * @notice Check if this essence NFT is transferable. 35 | * 36 | * @return bool Whether this Essence NFT is transferable. 37 | */ 38 | function isTransferable() external returns (bool); 39 | } 40 | -------------------------------------------------------------------------------- /src/interfaces/IEssenceNFTEvents.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface IEssenceNFTEvents { 6 | /** 7 | * @notice Emiited when the essence NFT is initialized 8 | * 9 | * @param profileId The profile ID for the Essence NFT. 10 | * @param essenceId The essence ID for the Essence NFT. 11 | * @param name The name for the Essence NFT. 12 | * @param symbol The symbol for the Essence NFT. 13 | * @param transferable Whether the Essence NFT is transferable. 14 | */ 15 | event Initialize( 16 | uint256 indexed profileId, 17 | uint256 indexed essenceId, 18 | string name, 19 | string symbol, 20 | bool transferable 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /src/interfaces/IMB.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { IMBEvents } from "../interfaces/IMBEvents.sol"; 6 | 7 | interface IMB is IMBEvents { 8 | /** 9 | * @notice Gets the Box address. 10 | * 11 | * @return address The Box NFT address. 12 | */ 13 | function getBoxAddr() external view returns (address); 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/IMBEvents.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface IMBEvents { 6 | /** 7 | * @notice Emiited when the MB is initialized. 8 | * 9 | * @param owner The address of the MB owner. 10 | * @param boxAddr The address of the box NFT. 11 | * @param name The name for the MB. 12 | * @param symbol The symbol for the MB. 13 | * @param uri The uri for the MB. 14 | */ 15 | event Initialize( 16 | address indexed owner, 17 | address indexed boxAddr, 18 | string name, 19 | string symbol, 20 | string uri 21 | ); 22 | 23 | /** 24 | * @notice Emitted when a box NFT has been opened. 25 | * 26 | * @param to The claimer address. 27 | * @param boxId The token id for MB NFT. 28 | */ 29 | event OpenBox( 30 | address indexed to, 31 | uint256 indexed boxId 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/interfaces/IProfileDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface IProfileDeployer { 6 | /** 7 | * @notice Parameters when constructing a ProfileNFT. 8 | * 9 | * @return engine The CyberEngine address. 10 | * @return subBeacon The Subscribe Beacon address. 11 | * @return essenceBeacon The Essence Beacon address. 12 | */ 13 | function profileParams() 14 | external 15 | view 16 | returns ( 17 | address engine, 18 | address subBeacon, 19 | address essenceBeacon 20 | ); 21 | 22 | /** 23 | * @notice Deploy a new ProfileNFT. 24 | * 25 | * @param salt The salt used to generate contract address in a deterministic way. 26 | * @param engine The CyberEngine address. 27 | * @param subscribeBeacon The Subscribe Beacon address. 28 | * @param essenceBeacon The Essence Beacon address. 29 | * 30 | * @return addr The newly deployed ProfileNFT address. 31 | */ 32 | function deployProfile( 33 | bytes32 salt, 34 | address engine, 35 | address subscribeBeacon, 36 | address essenceBeacon 37 | ) external returns (address addr); 38 | } 39 | -------------------------------------------------------------------------------- /src/interfaces/IProfileMiddleware.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { DataTypes } from "../libraries/DataTypes.sol"; 6 | 7 | interface IProfileMiddleware { 8 | /** 9 | * @notice Sets namespace related data for middleware. 10 | * 11 | * @param namespace The related namespace address. 12 | * @param data Extra data to set. 13 | */ 14 | function setProfileMwData(address namespace, bytes calldata data) 15 | external 16 | returns (bytes memory); 17 | 18 | /** 19 | * @notice Process that runs before the profileNFT creation happens. 20 | * 21 | * @param params The params for creating profile. 22 | * @param data Extra data to process. 23 | */ 24 | function preProcess( 25 | DataTypes.CreateProfileParams calldata params, 26 | bytes calldata data 27 | ) external payable; 28 | 29 | /** 30 | * @notice Process that runs after the profileNFT creation happens. 31 | * 32 | * @param params The params for creating profile. 33 | * @param data Extra data to process. 34 | */ 35 | function postProcess( 36 | DataTypes.CreateProfileParams calldata params, 37 | bytes calldata data 38 | ) external; 39 | } 40 | -------------------------------------------------------------------------------- /src/interfaces/IProfileNFTDescriptor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { DataTypes } from "../libraries/DataTypes.sol"; 6 | 7 | interface IProfileNFTDescriptor { 8 | /** 9 | * @notice Sets the profile NFT animation template. 10 | * 11 | * @param template The new template. 12 | */ 13 | function setAnimationTemplate(string calldata template) external; 14 | 15 | /** 16 | * @notice Generate the Profile NFT Token URI. 17 | * 18 | * @param params The dependences of token URI. 19 | * @return string The token URI. 20 | */ 21 | function tokenURI(DataTypes.ConstructTokenURIParams calldata params) 22 | external 23 | view 24 | returns (string memory); 25 | } 26 | -------------------------------------------------------------------------------- /src/interfaces/IProfileNFTDescriptorV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { DataTypes } from "../libraries/DataTypes.sol"; 6 | 7 | interface IProfileNFTDescriptorV2 { 8 | /** 9 | * @notice Generate the Profile NFT Token URI. 10 | * 11 | * @param params The dependences of token URI. 12 | * @return string The token URI. 13 | */ 14 | function tokenURI(DataTypes.ConstructTokenURIParams calldata params) 15 | external 16 | view 17 | returns (string memory); 18 | } 19 | -------------------------------------------------------------------------------- /src/interfaces/ISubscribeDeployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface ISubscribeDeployer { 6 | /** 7 | * @notice Parameters when constructing a SubscribeNFT. 8 | * 9 | * @return profileProxy The ProfileNFT proxy address. 10 | */ 11 | function subParams() external view returns (address profileProxy); 12 | 13 | /** 14 | * @notice Deploy a new SubscribeNFT. 15 | * 16 | * @param salt The salt used to generate contract address in a deterministic way. 17 | * @param profileProxy The ProfileNFT proxy address. 18 | * 19 | * @return addr The newly deployed SubscribeNFT address. 20 | */ 21 | function deploySubscribe(bytes32 salt, address profileProxy) 22 | external 23 | returns (address addr); 24 | } 25 | -------------------------------------------------------------------------------- /src/interfaces/ISubscribeMiddleware.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface ISubscribeMiddleware { 6 | /** 7 | * @notice Sets subscribe related data for middleware. 8 | * 9 | * @param profileId The profile id that owns this middleware. 10 | * @param data Extra data to set. 11 | */ 12 | function setSubscribeMwData(uint256 profileId, bytes calldata data) 13 | external 14 | returns (bytes memory); 15 | 16 | /** 17 | * @notice Process that runs before the subscribeNFT mint happens. 18 | * 19 | * @param profileId The profile Id. 20 | * @param subscriber The subscriber address. 21 | * @param subscribeNFT The subscribe nft address. 22 | * @param data Extra data to process. 23 | */ 24 | function preProcess( 25 | uint256 profileId, 26 | address subscriber, 27 | address subscribeNFT, 28 | bytes calldata data 29 | ) external; 30 | 31 | /** 32 | * @notice Process that runs after the subscribeNFT mint happens. 33 | * 34 | * @param profileId The profile Id. 35 | * @param subscriber The subscriber address. 36 | * @param subscribeNFT The subscribe nft address. 37 | * @param data Extra data to process. 38 | */ 39 | function postProcess( 40 | uint256 profileId, 41 | address subscriber, 42 | address subscribeNFT, 43 | bytes calldata data 44 | ) external; 45 | } 46 | -------------------------------------------------------------------------------- /src/interfaces/ISubscribeNFT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ISubscribeNFTEvents } from "./ISubscribeNFTEvents.sol"; 6 | 7 | interface ISubscribeNFT is ISubscribeNFTEvents { 8 | /** 9 | * @notice Mints the Subscribe NFT. 10 | * 11 | * @param to The recipient address. 12 | * @return uint256 The token id. 13 | */ 14 | function mint(address to) external returns (uint256); 15 | 16 | /** 17 | * @notice Initializes the Subscribe NFT. 18 | * 19 | * @param profileId The profile ID to set for the Subscribe NFT. 20 | * @param name The name for the Subscribe NFT. 21 | * @param symbol The symbol for the Subscribe NFT. 22 | */ 23 | function initialize( 24 | uint256 profileId, 25 | string calldata name, 26 | string calldata symbol 27 | ) external; 28 | } 29 | -------------------------------------------------------------------------------- /src/interfaces/ISubscribeNFTEvents.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface ISubscribeNFTEvents { 6 | /** 7 | * @notice Emiited when the subscribe NFT is initialized 8 | * 9 | * @param profileId The profile ID for the Susbcribe NFT. 10 | * @param name The name for the Subscribe NFT. 11 | * @param symbol The symbol for the Subscribe NFT. 12 | */ 13 | event Initialize(uint256 indexed profileId, string name, string symbol); 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/ITreasury.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ITreasuryEvents } from "../interfaces/ITreasuryEvents.sol"; 6 | 7 | interface ITreasury is ITreasuryEvents { 8 | /** 9 | * @notice Gets the treasury address. 10 | * 11 | * @return address The treasury address. 12 | */ 13 | function getTreasuryAddress() external view returns (address); 14 | 15 | /** 16 | * @notice Gets the treasury fee. The percentage is calculated as: treasuryFee/_MAX_BPS. 17 | * 18 | * @return address The treasury fee. 19 | */ 20 | function getTreasuryFee() external view returns (uint256); 21 | 22 | /** 23 | * @notice Checks if the currency is allowed. 24 | * 25 | * @return bool The status of allowance for the currency. 26 | */ 27 | function isCurrencyAllowed(address currency) external view returns (bool); 28 | } 29 | -------------------------------------------------------------------------------- /src/interfaces/ITreasuryEvents.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { DataTypes } from "../libraries/DataTypes.sol"; 6 | 7 | interface ITreasuryEvents { 8 | /** 9 | * @notice Emitted when a currency has been allowed. 10 | * 11 | * @param currency The ERC20 token contract address. 12 | * @param preAllowed The previously allow state. 13 | * @param newAllowed The newly set allow state. 14 | */ 15 | event AllowCurrency( 16 | address indexed currency, 17 | bool indexed preAllowed, 18 | bool indexed newAllowed 19 | ); 20 | 21 | /** 22 | * @notice Emitted when a new treasuryAddress has been set. 23 | * 24 | * @param preTreasuryAddress The previous treasuryAddress. 25 | * @param treasuryAddress The new treasuryAddress. 26 | */ 27 | event SetTreasuryAddress( 28 | address indexed preTreasuryAddress, 29 | address indexed treasuryAddress 30 | ); 31 | 32 | /** 33 | * @notice Emitted when a new treasuryFee has been set. 34 | * 35 | * @param preTreasuryFee The previous treasuryFee. 36 | * @param treasuryFee The new treasuryFee. 37 | */ 38 | event SetTreasuryFee( 39 | uint16 indexed preTreasuryFee, 40 | uint16 indexed treasuryFee 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /src/interfaces/IUpgradeable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | interface IUpgradeable { 6 | /** 7 | * @notice Contract version number. 8 | * 9 | * @return uint256 The version number. 10 | */ 11 | function version() external pure returns (uint256); 12 | } 13 | -------------------------------------------------------------------------------- /src/middlewares/base/FeeMw.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ITreasury } from "../../interfaces/ITreasury.sol"; 6 | 7 | abstract contract FeeMw { 8 | /*////////////////////////////////////////////////////////////// 9 | STATES 10 | //////////////////////////////////////////////////////////////*/ 11 | address public immutable TREASURY; // solhint-disable-line 12 | 13 | /*////////////////////////////////////////////////////////////// 14 | CONSTRUCTOR 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | constructor(address treasury) { 18 | require(treasury != address(0), "ZERO_TREASURY_ADDRESS"); 19 | TREASURY = treasury; 20 | } 21 | 22 | /*////////////////////////////////////////////////////////////// 23 | INTERNAL 24 | //////////////////////////////////////////////////////////////*/ 25 | 26 | function _currencyAllowed(address currency) internal view returns (bool) { 27 | return ITreasury(TREASURY).isCurrencyAllowed(currency); 28 | } 29 | 30 | function _treasuryAddress() internal view returns (address) { 31 | return ITreasury(TREASURY).getTreasuryAddress(); 32 | } 33 | 34 | function _treasuryFee() internal view returns (uint256) { 35 | return ITreasury(TREASURY).getTreasuryFee(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/middlewares/base/PermissionedMw.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ICyberEngine } from "../../interfaces/ICyberEngine.sol"; 6 | 7 | abstract contract PermissionedMw { 8 | /*////////////////////////////////////////////////////////////// 9 | STATES 10 | //////////////////////////////////////////////////////////////*/ 11 | address public immutable ENGINE; // solhint-disable-line 12 | 13 | /*////////////////////////////////////////////////////////////// 14 | MODIFIERS 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | /** 18 | * @notice Checks that the sender is the engine address. 19 | */ 20 | modifier onlyEngine() { 21 | require(ENGINE == msg.sender, "NON_ENGINE_ADDRESS"); 22 | _; 23 | } 24 | 25 | /*////////////////////////////////////////////////////////////// 26 | CONSTRUCTOR 27 | //////////////////////////////////////////////////////////////*/ 28 | 29 | constructor(address engine) { 30 | require(engine != address(0), "ENGINE_ADDRESS_ZERO"); 31 | ENGINE = engine; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/middlewares/essence/CollectDisallowedMw.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { IEssenceMiddleware } from "../../interfaces/IEssenceMiddleware.sol"; 6 | 7 | /** 8 | * @title Collect Disallowed Middleware 9 | * @author CyberConnect 10 | * @notice This contract is a middleware to disallow any collection to the essence that uses it. 11 | */ 12 | contract CollectDisallowedMw is IEssenceMiddleware { 13 | /*////////////////////////////////////////////////////////////// 14 | EXTERNAL 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | /// @inheritdoc IEssenceMiddleware 18 | function setEssenceMwData( 19 | uint256, 20 | uint256, 21 | bytes calldata 22 | ) external pure returns (bytes memory) { 23 | // do nothing 24 | return new bytes(0); 25 | } 26 | 27 | /** 28 | * @inheritdoc IEssenceMiddleware 29 | * @notice This process denies any attempts to collect the essence 30 | */ 31 | function preProcess( 32 | uint256, 33 | uint256, 34 | address, 35 | address, 36 | bytes calldata 37 | ) external pure override { 38 | revert("COLLECT_DISALLOWED"); 39 | } 40 | 41 | /// @inheritdoc IEssenceMiddleware 42 | function postProcess( 43 | uint256, 44 | uint256, 45 | address, 46 | address, 47 | bytes calldata 48 | ) external { 49 | // do nothing 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/middlewares/essence/CollectOnlySubscribedMw.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ERC721 } from "../../dependencies/solmate/ERC721.sol"; 6 | 7 | import { IEssenceMiddleware } from "../../interfaces/IEssenceMiddleware.sol"; 8 | import { IProfileNFT } from "../../interfaces/IProfileNFT.sol"; 9 | 10 | /** 11 | * @title Collect only when subscribed Middleware 12 | * @author CyberConnect 13 | * @notice This contract is a middleware to allow the address to collect an essence only if they are subscribed 14 | */ 15 | contract CollectOnlySubscribedMw is IEssenceMiddleware { 16 | /*////////////////////////////////////////////////////////////// 17 | EXTERNAL VIEW 18 | //////////////////////////////////////////////////////////////*/ 19 | 20 | /// @inheritdoc IEssenceMiddleware 21 | function setEssenceMwData( 22 | uint256, 23 | uint256, 24 | bytes calldata 25 | ) external pure returns (bytes memory) { 26 | // do nothing 27 | return new bytes(0); 28 | } 29 | 30 | /** 31 | * @inheritdoc IEssenceMiddleware 32 | * @notice Process that checks if the user is already subscribed to the essence owner 33 | */ 34 | function preProcess( 35 | uint256 profileId, 36 | uint256, 37 | address collector, 38 | address, 39 | bytes calldata 40 | ) external view override { 41 | require( 42 | _checkSubscribe(msg.sender, profileId, collector), 43 | "NOT_SUBSCRIBED" 44 | ); 45 | } 46 | 47 | /// @inheritdoc IEssenceMiddleware 48 | function postProcess( 49 | uint256, 50 | uint256, 51 | address, 52 | address, 53 | bytes calldata 54 | ) external { 55 | // do nothing 56 | } 57 | 58 | /*////////////////////////////////////////////////////////////// 59 | INTERNAL 60 | //////////////////////////////////////////////////////////////*/ 61 | 62 | function _checkSubscribe( 63 | address namespace, 64 | uint256 profileId, 65 | address collector 66 | ) internal view returns (bool) { 67 | address essenceOwnerSubscribeNFT = IProfileNFT(namespace) 68 | .getSubscribeNFT(profileId); 69 | 70 | return (essenceOwnerSubscribeNFT != address(0) && 71 | ERC721(essenceOwnerSubscribeNFT).balanceOf(collector) != 0); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/middlewares/subscribe/SubscribeDisallowedMw.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ISubscribeMiddleware } from "../../interfaces/ISubscribeMiddleware.sol"; 6 | 7 | /** 8 | * @title Subscribe Disallowed Middleware 9 | * @author CyberConnect 10 | * @notice This contract is a middleware to disallow any subscriptions to the user. 11 | */ 12 | contract SubscribeDisallowedMw is ISubscribeMiddleware { 13 | /*////////////////////////////////////////////////////////////// 14 | EXTERNAL VIEW 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | /// @inheritdoc ISubscribeMiddleware 18 | function setSubscribeMwData(uint256, bytes calldata) 19 | external 20 | pure 21 | override 22 | returns (bytes memory) 23 | { 24 | // do nothing 25 | return new bytes(0); 26 | } 27 | 28 | /** 29 | * @inheritdoc ISubscribeMiddleware 30 | * @notice Process that disallows a subscription 31 | */ 32 | function preProcess( 33 | uint256, 34 | address, 35 | address, 36 | bytes calldata 37 | ) external pure override { 38 | revert("SUBSCRIBE_DISALLOWED"); 39 | } 40 | 41 | /// @inheritdoc ISubscribeMiddleware 42 | function postProcess( 43 | uint256 profileId, 44 | address subscriber, 45 | address subscribeNFT, 46 | bytes calldata data 47 | ) external override { 48 | // do nothing 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/middlewares/subscribe/SubscribeOnlyOnceMw.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ERC721 } from "../../dependencies/solmate/ERC721.sol"; 6 | 7 | import { ISubscribeMiddleware } from "../../interfaces/ISubscribeMiddleware.sol"; 8 | 9 | /** 10 | * @title Subscribe Only Once Middleware 11 | * @author CyberConnect 12 | * @notice This contract is a middleware to allow the address to subscribe only once to another address. 13 | */ 14 | contract SubscribeOnlyOnceMw is ISubscribeMiddleware { 15 | /*////////////////////////////////////////////////////////////// 16 | EXTERNAL VIEW 17 | //////////////////////////////////////////////////////////////*/ 18 | 19 | /// @inheritdoc ISubscribeMiddleware 20 | function setSubscribeMwData(uint256, bytes calldata) 21 | external 22 | pure 23 | override 24 | returns (bytes memory) 25 | { 26 | // do nothing 27 | return new bytes(0); 28 | } 29 | 30 | /** 31 | * @inheritdoc ISubscribeMiddleware 32 | * @notice Process that checks if the subscriber is already subscribed. 33 | */ 34 | function preProcess( 35 | uint256, 36 | address subscriber, 37 | address subscribeNFT, 38 | bytes calldata 39 | ) external view override { 40 | require( 41 | ERC721(subscribeNFT).balanceOf(subscriber) == 0, 42 | "Already subscribed" 43 | ); 44 | } 45 | 46 | /// @inheritdoc ISubscribeMiddleware 47 | function postProcess( 48 | uint256 profileId, 49 | address subscriber, 50 | address subscribeNFT, 51 | bytes calldata data 52 | ) external override { 53 | // do nothing 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/periphery/RelationshipChecker.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { IERC721 } from "openzeppelin-contracts/contracts/token/ERC721/IERC721.sol"; 6 | 7 | import { IProfileNFT } from "../interfaces/IProfileNFT.sol"; 8 | 9 | contract RelationshipChecker { 10 | address internal _namespace; 11 | 12 | /*////////////////////////////////////////////////////////////// 13 | CONSTRUCTOR 14 | //////////////////////////////////////////////////////////////*/ 15 | 16 | constructor(address namespace) { 17 | _namespace = namespace; 18 | } 19 | 20 | /*////////////////////////////////////////////////////////////// 21 | EXTERNAL VIEW 22 | //////////////////////////////////////////////////////////////*/ 23 | 24 | /** 25 | * @notice Check if the profile issued EssenceNFT is collected by me. 26 | * 27 | * @param profileId The profile id. 28 | * @param essenceId The essence id. 29 | * @param me The address to check. 30 | */ 31 | function isCollectedByMe( 32 | uint256 profileId, 33 | uint256 essenceId, 34 | address me 35 | ) external view returns (bool) { 36 | address essNFTAddr = IProfileNFT(_namespace).getEssenceNFT( 37 | profileId, 38 | essenceId 39 | ); 40 | if (essNFTAddr == address(0)) { 41 | return false; 42 | } 43 | 44 | return IERC721(essNFTAddr).balanceOf(me) > 0; 45 | } 46 | 47 | /** 48 | * @notice Check if the profile is subscribed by me. 49 | * 50 | * @param profileId The profile id. 51 | * @param me The address to check. 52 | */ 53 | function isSubscribedByMe(uint256 profileId, address me) 54 | external 55 | view 56 | returns (bool) 57 | { 58 | address subNFTAddr = IProfileNFT(_namespace).getSubscribeNFT(profileId); 59 | if (subNFTAddr == address(0)) { 60 | return false; 61 | } 62 | return IERC721(subNFTAddr).balanceOf(me) > 0; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/storages/CyberBoxNFTStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | abstract contract CyberBoxNFTStorage { 6 | // constant 7 | uint256 internal constant _VERSION = 1; 8 | 9 | // storage 10 | address internal _signer; 11 | } 12 | -------------------------------------------------------------------------------- /src/storages/CyberEngineStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { DataTypes } from "../libraries/DataTypes.sol"; 6 | 7 | abstract contract CyberEngineStorage { 8 | // constant 9 | string internal constant _VERSION_STRING = "1"; // for 712, should never change 10 | uint256 internal constant _VERSION = 2; 11 | 12 | // storage 13 | mapping(address => bool) internal _profileMwAllowlist; 14 | mapping(address => bool) internal _essenceMwAllowlist; 15 | mapping(address => bool) internal _subscribeMwAllowlist; 16 | mapping(bytes32 => address) internal _namespaceByName; 17 | mapping(address => DataTypes.NamespaceStruct) internal _namespaceInfo; 18 | } 19 | -------------------------------------------------------------------------------- /src/storages/CyberGrandNFTStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | abstract contract CyberGrandNFTStorage { 6 | // constant 7 | uint256 internal constant _VERSION = 1; 8 | 9 | // storage 10 | address internal _signer; 11 | string internal _tokenURI; 12 | } 13 | -------------------------------------------------------------------------------- /src/storages/EssenceNFTStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | contract EssenceNFTStorage { 6 | // constant 7 | uint256 internal constant _VERSION = 2; 8 | 9 | // storage 10 | uint256 internal _profileId; 11 | uint256 internal _essenceId; 12 | bool internal _transferable; 13 | } 14 | -------------------------------------------------------------------------------- /src/storages/Link3ProfileDescriptorStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | contract Link3ProfileDescriptorStorage { 6 | // constant 7 | string internal constant _BASE_URL = "https://link3.to/"; 8 | uint256 internal constant _VERSION = 1; 9 | 10 | // storage 11 | string public animationTemplate; 12 | } 13 | -------------------------------------------------------------------------------- /src/storages/Link3ProfileDescriptorStorageV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | contract Link3ProfileDescriptorStorageV2 { 6 | // constant 7 | string internal constant _BASE_URL = "https://link3.to/"; 8 | uint256 internal constant _VERSION = 1; 9 | } 10 | -------------------------------------------------------------------------------- /src/storages/MBNFTStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | abstract contract MBNFTStorage { 6 | // constant 7 | uint256 internal constant _VERSION = 1; 8 | 9 | // storage 10 | string internal _tokenURI; 11 | address internal _boxAddr; 12 | } 13 | -------------------------------------------------------------------------------- /src/storages/ProfileNFTStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { DataTypes } from "../libraries/DataTypes.sol"; 6 | 7 | abstract contract ProfileNFTStorage { 8 | // constant 9 | uint256 internal constant _VERSION = 2; 10 | 11 | // storage 12 | address internal _nftDescriptor; 13 | address internal _namespaceOwner; 14 | mapping(uint256 => DataTypes.ProfileStruct) internal _profileById; 15 | mapping(bytes32 => uint256) internal _profileIdByHandleHash; 16 | mapping(uint256 => string) internal _metadataById; 17 | mapping(uint256 => mapping(address => bool)) internal _operatorApproval; 18 | mapping(address => uint256) internal _addressToPrimaryProfile; 19 | mapping(uint256 => DataTypes.SubscribeStruct) 20 | internal _subscribeByProfileId; 21 | mapping(uint256 => mapping(uint256 => DataTypes.EssenceStruct)) 22 | internal _essenceByIdByProfileId; 23 | } 24 | -------------------------------------------------------------------------------- /src/storages/SubscribeNFTStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | abstract contract SubscribeNFTStorage { 6 | // storage 7 | uint256 internal _profileId; 8 | uint256 internal constant _VERSION = 2; 9 | } 10 | -------------------------------------------------------------------------------- /src/token/CYBER.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ERC20 } from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; 6 | import { ERC20Permit } from "openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol"; 7 | import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; 8 | 9 | contract CYBER is ERC20, ERC20Permit, Ownable { 10 | // Total supply of cyber token is 100M 11 | uint256 public TOTAL_SUPPLY = 100_000_000 * 10**uint256(decimals()); 12 | 13 | constructor(address owner, address to) 14 | ERC20("CyberConnect", "CYBER") 15 | ERC20Permit("CyberConnect") 16 | { 17 | _transferOwnership(owner); 18 | 19 | _mint(to, TOTAL_SUPPLY); 20 | } 21 | 22 | function mint(address to, uint256 amount) external onlyOwner { 23 | _mint(to, amount); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/upgradeability/UpgradeableBeacon.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | // OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol"; 7 | import "openzeppelin-contracts/contracts/utils/Address.sol"; 8 | 9 | /** 10 | * @dev Adapted from Openzepelin's UpgradeableBeacon.sol with RolesAuthority auth 11 | * 12 | * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their 13 | * implementation contract, which is where they will delegate all function calls. 14 | * 15 | * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon. 16 | */ 17 | contract UpgradeableBeacon is IBeacon { 18 | address private _implementation; 19 | address public immutable OWNER; 20 | 21 | /** 22 | * @dev Emitted when the implementation returned by the beacon is changed. 23 | */ 24 | event Upgraded(address indexed implementation); 25 | 26 | /** 27 | * @dev Sets the address of the initial implementation, and the owner can upgrade the 28 | * beacon. 29 | */ 30 | constructor(address implementation_, address owner) { 31 | require(owner != address(0), "ZERO_OWNER_ADDRESS"); 32 | _setImplementation(implementation_); 33 | OWNER = owner; 34 | } 35 | 36 | /** 37 | * @dev Returns the current implementation address. 38 | */ 39 | function implementation() public view virtual override returns (address) { 40 | return _implementation; 41 | } 42 | 43 | /** 44 | * @dev Upgrades the beacon to a new implementation. 45 | * 46 | * Emits an {Upgraded} event. 47 | * 48 | * Requirements: 49 | * 50 | * - msg.sender must be the owner of the contract. 51 | * - `newImplementation` must be a contract. 52 | */ 53 | function upgradeTo(address newImplementation) public virtual { 54 | require(msg.sender == address(OWNER), "ONLY_OWNER"); 55 | _setImplementation(newImplementation); 56 | emit Upgraded(newImplementation); 57 | } 58 | 59 | /** 60 | * @dev Sets the implementation contract address for this beacon 61 | * 62 | * Requirements: 63 | * 64 | * - `newImplementation` must be a contract. 65 | */ 66 | function _setImplementation(address newImplementation) private { 67 | require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract"); 68 | _implementation = newImplementation; 69 | } 70 | } -------------------------------------------------------------------------------- /test/Deployer.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Test.sol"; 6 | 7 | import { ProfileDeployer } from "../src/deployer/ProfileDeployer.sol"; 8 | import { SubscribeDeployer } from "../src/deployer/SubscribeDeployer.sol"; 9 | import { EssenceDeployer } from "../src/deployer/EssenceDeployer.sol"; 10 | 11 | contract DeployerTest is Test { 12 | ProfileDeployer pd; 13 | SubscribeDeployer sd; 14 | EssenceDeployer ed; 15 | bytes32 salt = keccak256(bytes("salt")); 16 | 17 | function setUp() public { 18 | pd = new ProfileDeployer(); 19 | sd = new SubscribeDeployer(); 20 | ed = new EssenceDeployer(); 21 | } 22 | 23 | function testCannotDeploySubcribeWithZeroProfile() public { 24 | vm.expectRevert("ZERO_ADDRESS"); 25 | sd.deploySubscribe(salt, address(0)); 26 | } 27 | 28 | function testCannotDeployEssenceWithZeroProfile() public { 29 | vm.expectRevert("ZERO_ADDRESS"); 30 | ed.deployEssence(salt, address(0)); 31 | } 32 | 33 | function testCannotDeployProfileWithZeroEngine() public { 34 | vm.expectRevert("ENGINE_NOT_SET"); 35 | pd.deployProfile(salt, address(0), address(0xdead), address(0xdead)); 36 | } 37 | 38 | function testCannotDeployProfileWithZeroSubscribe() public { 39 | vm.expectRevert("SUBSCRIBE_BEACON_NOT_SET"); 40 | pd.deployProfile(salt, address(0xdead), address(0), address(0xdead)); 41 | } 42 | 43 | function testCannotDeployProfileWithZeroEssence() public { 44 | vm.expectRevert("ESSENCE_BEACON_NOT_SET"); 45 | pd.deployProfile(salt, address(0xdead), address(0xdead), address(0)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/Pausable.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Test.sol"; 6 | 7 | import { MockPausable } from "./utils/MockPausable.sol"; 8 | 9 | contract PausableTest is Test { 10 | event Paused(address account); 11 | event Unpaused(address account); 12 | 13 | MockPausable internal pausableContract; 14 | 15 | function setUp() public { 16 | pausableContract = new MockPausable(); 17 | } 18 | 19 | function testcanPerformNormalProcessInNonPause() public { 20 | assertEq(pausableContract.count(), 0); 21 | pausableContract.normalProcess(); 22 | assertEq(pausableContract.count(), 1); 23 | } 24 | 25 | function testCannotTakeDrasticMeasureInNonPause() public { 26 | vm.expectRevert("Pausable: not paused"); 27 | pausableContract.drasticMeasure(); 28 | } 29 | 30 | function testEmitPauseEvent() public { 31 | vm.expectEmit(true, false, false, true); 32 | emit Paused(address(this)); 33 | pausableContract.pause(); 34 | } 35 | 36 | function testCannotPerformNormalProcessInPause() public { 37 | pausableContract.pause(); 38 | vm.expectRevert("Pausable: paused"); 39 | pausableContract.normalProcess(); 40 | } 41 | 42 | function testCanTakeADrasticMeasureInAPause() public { 43 | pausableContract.pause(); 44 | pausableContract.drasticMeasure(); 45 | assertEq(pausableContract.drasticMeasureTaken(), true); 46 | } 47 | 48 | function testCannotRepause() public { 49 | pausableContract.pause(); 50 | vm.expectRevert("Pausable: paused"); 51 | pausableContract.pause(); 52 | } 53 | 54 | function testIsUnpausableByThePauser() public { 55 | pausableContract.pause(); 56 | pausableContract.unpause(); 57 | assertEq(pausableContract.paused(), false); 58 | } 59 | 60 | function testUnPausedEvent() public { 61 | pausableContract.pause(); 62 | vm.expectEmit(true, false, false, true); 63 | emit Unpaused(address(this)); 64 | pausableContract.unpause(); 65 | } 66 | 67 | function shouldResumeAllowingNormalProcess() public { 68 | pausableContract.pause(); 69 | pausableContract.unpause(); 70 | assertEq(pausableContract.count(), 0); 71 | pausableContract.normalProcess(); 72 | assertEq(pausableContract.count(), 1); 73 | } 74 | 75 | function testShouldPreventDrasticMeasure() public { 76 | pausableContract.pause(); 77 | pausableContract.unpause(); 78 | vm.expectRevert("Pausable: not paused"); 79 | pausableContract.drasticMeasure(); 80 | } 81 | 82 | function testCannotReUnpause() public { 83 | pausableContract.pause(); 84 | pausableContract.unpause(); 85 | vm.expectRevert("Pausable: not paused"); 86 | pausableContract.unpause(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /test/SubscribeNFTUpgrade.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Test.sol"; 6 | import { BeaconProxy } from "openzeppelin-contracts/contracts/proxy/beacon/BeaconProxy.sol"; 7 | 8 | import { MockSubscribeNFTV2 } from "./utils/MockSubscribeNFTV2.sol"; 9 | import { TestDeployer } from "./utils/TestDeployer.sol"; 10 | import { UpgradeableBeacon } from "../src/upgradeability/UpgradeableBeacon.sol"; 11 | import { SubscribeNFT } from "../src/core/SubscribeNFT.sol"; 12 | 13 | contract SubscribeNFTUpgradeTest is Test, TestDeployer { 14 | UpgradeableBeacon internal beacon; 15 | BeaconProxy internal proxy; 16 | BeaconProxy internal proxyB; 17 | address internal profile; 18 | 19 | uint256 internal profileId = 1; 20 | address constant alice = address(0xA11CE); 21 | 22 | function _deployV2(address _profile) 23 | internal 24 | returns (MockSubscribeNFTV2 addr) 25 | { 26 | subParams.profileProxy = _profile; 27 | addr = new MockSubscribeNFTV2{ salt: _salt }(); 28 | delete subParams; 29 | } 30 | 31 | function setUp() public { 32 | profile = address(0xdead); 33 | address impl = deploySubscribe(_salt, address(profile)); 34 | beacon = new UpgradeableBeacon(impl, address(profile)); 35 | bytes memory functionData = abi.encodeWithSelector( 36 | SubscribeNFT.initialize.selector, 37 | profileId, 38 | "name", 39 | "SYMBOL" 40 | ); 41 | proxy = new BeaconProxy(address(beacon), functionData); 42 | proxyB = new BeaconProxy(address(beacon), functionData); 43 | } 44 | 45 | function testAuth() public { 46 | assertEq(beacon.OWNER(), address(profile)); 47 | } 48 | 49 | function testUpgrade() public { 50 | MockSubscribeNFTV2 implB = _deployV2(profile); 51 | 52 | vm.prank(address(profile)); 53 | beacon.upgradeTo(address(implB)); 54 | 55 | MockSubscribeNFTV2 p = MockSubscribeNFTV2(address(proxy)); 56 | MockSubscribeNFTV2 pB = MockSubscribeNFTV2(address(proxyB)); 57 | 58 | assertEq(p.version(), 100); 59 | assertEq(pB.version(), 100); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /test/Treasury.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Test.sol"; 6 | 7 | import { ITreasuryEvents } from "../src/interfaces/ITreasuryEvents.sol"; 8 | 9 | import { Constants } from "../src/libraries/Constants.sol"; 10 | 11 | import { Treasury } from "../src/middlewares/base/Treasury.sol"; 12 | 13 | contract TreasuryTest is Test, ITreasuryEvents { 14 | Treasury t; 15 | address constant owner = address(0xA11CE); 16 | address constant bob = address(0xB0B); 17 | address constant gov = address(0x8888); 18 | address constant token = address(0x111); 19 | 20 | function setUp() public { 21 | t = new Treasury(owner, bob, 200); 22 | } 23 | 24 | function testBasic() public { 25 | assertEq(t.getTreasuryAddress(), bob); 26 | assertEq(t.getTreasuryFee(), 200); 27 | } 28 | 29 | function testSetTreasuryFee() public { 30 | vm.prank(owner); 31 | 32 | vm.expectEmit(true, true, false, true); 33 | emit SetTreasuryFee(200, 300); 34 | 35 | t.setTreasuryFee(300); 36 | assertEq(t.getTreasuryFee(), 300); 37 | } 38 | 39 | function testCannotSetTreasuryFeeExceedMax() public { 40 | vm.prank(owner); 41 | vm.expectRevert("INVALID_TREASURY_FEE"); 42 | t.setTreasuryFee(Constants._MAX_BPS + 1); 43 | } 44 | 45 | function testCannotSetTreasuryFeeNonOwner() public { 46 | vm.expectRevert("UNAUTHORIZED"); 47 | t.setTreasuryFee(Constants._MAX_BPS); 48 | } 49 | 50 | function testSetTreasuryAddress() public { 51 | vm.prank(owner); 52 | 53 | vm.expectEmit(true, true, false, true); 54 | emit SetTreasuryAddress(bob, gov); 55 | 56 | t.setTreasuryAddress(gov); 57 | assertEq(t.getTreasuryAddress(), gov); 58 | } 59 | 60 | function testCannotSetTreasuryAddressNonOwner() public { 61 | vm.expectRevert("UNAUTHORIZED"); 62 | t.setTreasuryAddress(bob); 63 | } 64 | 65 | function testAllowCurrency() public { 66 | vm.startPrank(owner); 67 | assertEq(t.isCurrencyAllowed(token), false); 68 | t.allowCurrency(token, true); 69 | assertEq(t.isCurrencyAllowed(token), true); 70 | } 71 | 72 | function testCannotAllowCurrencyNonOwner() public { 73 | vm.expectRevert("UNAUTHORIZED"); 74 | t.allowCurrency(token, true); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /test/UpgradeableBeacon.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Test.sol"; 6 | import "openzeppelin-contracts/contracts/mocks/RegressionImplementation.sol"; 7 | 8 | import "../src/upgradeability/UpgradeableBeacon.sol"; 9 | 10 | contract UpgradeableBeaconTest is Test { 11 | address internal owner = address(0xA11CE); 12 | address internal other = address(0xB0B); 13 | event Upgraded(address indexed implementation); 14 | Implementation1 v1; 15 | UpgradeableBeacon beacon; 16 | 17 | function setUp() public { 18 | v1 = new Implementation1(); 19 | beacon = new UpgradeableBeacon(address(v1), owner); 20 | } 21 | 22 | function testCannotCreatedWithNonContractImplementation() public { 23 | vm.expectRevert("UpgradeableBeacon: implementation is not a contract"); 24 | new UpgradeableBeacon(owner, address(this)); 25 | } 26 | 27 | function testReturnsImplementation() public { 28 | assertEq(beacon.implementation(), address(v1)); 29 | } 30 | 31 | function testCanBeUpgradedByTheOwner() public { 32 | Implementation2 v2 = new Implementation2(); 33 | vm.prank(owner); 34 | vm.expectEmit(true, false, false, true); 35 | emit Upgraded(address(v2)); 36 | beacon.upgradeTo(address(v2)); 37 | assertEq(beacon.implementation(), address(v2)); 38 | } 39 | 40 | function testCannotUpgradeByNonContract() public { 41 | vm.expectRevert("ONLY_OWNER"); 42 | beacon.upgradeTo(other); 43 | } 44 | 45 | function testCannotUpgradeByOtherAccount() public { 46 | Implementation2 v2 = new Implementation2(); 47 | vm.expectRevert("ONLY_OWNER"); 48 | beacon.upgradeTo(address(v2)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/integration/IntegrationBase.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | import { LibDeploy } from "../../script/libraries/LibDeploy.sol"; 5 | import { RolesAuthority } from "../../src/dependencies/solmate/RolesAuthority.sol"; 6 | import { ERC1967Proxy } from "openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol"; 7 | import { IProfileNFTEvents } from "../../src/interfaces/IProfileNFTEvents.sol"; 8 | import { ProfileNFT } from "../../src/core/ProfileNFT.sol"; 9 | import { TestLibFixture } from "../utils/TestLibFixture.sol"; 10 | import { Base64 } from "openzeppelin-contracts/contracts/utils/Base64.sol"; 11 | import { LibString } from "../../src/libraries/LibString.sol"; 12 | import { Link3ProfileDescriptor } from "../../src/periphery/Link3ProfileDescriptor.sol"; 13 | import { PermissionedFeeCreationMw } from "../../src/middlewares/profile/PermissionedFeeCreationMw.sol"; 14 | import { TestIntegrationBase } from "../utils/TestIntegrationBase.sol"; 15 | 16 | contract IntegrationBaseTest is TestIntegrationBase, IProfileNFTEvents { 17 | function setUp() public { 18 | _setUp(); 19 | } 20 | 21 | function testRegistrationTwice() public { 22 | assertEq(profileMw.getSigner(address(link3Profile)), link3Signer); 23 | string memory handle = "bob"; 24 | address to = bob; 25 | // Register bob profile 26 | vm.expectEmit(true, true, false, true); 27 | emit SetPrimaryProfile(to, 2); // hardcode profileid 28 | uint256 bobProfileId = TestLibFixture.registerProfile( 29 | vm, 30 | link3Profile, 31 | profileMw, 32 | handle, 33 | to, 34 | link3SignerPk 35 | ); 36 | 37 | // check bob profile details 38 | string memory gotHandle = link3Profile.getHandleByProfileId( 39 | bobProfileId 40 | ); 41 | string memory avatar = link3Profile.getAvatar(bobProfileId); 42 | string memory metadata = link3Profile.getMetadata(bobProfileId); 43 | address descriptor = link3Profile.getNFTDescriptor(); 44 | assertEq(gotHandle, handle); 45 | assertEq(avatar, "avatar"); 46 | assertEq(metadata, "metadata"); 47 | 48 | // check bob balance 49 | assertEq(link3Profile.balanceOf(to), 1); 50 | 51 | // check bob profile ownership 52 | assertEq(link3Profile.ownerOf(bobProfileId), to); 53 | 54 | assertEq(link3Profile.getPrimaryProfile(to), bobProfileId); 55 | assertEq(link3Profile.getPrimaryProfile(to), bobProfileId); 56 | 57 | // register second time will not set primary profile 58 | uint256 secondId = TestLibFixture.registerProfile( 59 | vm, 60 | link3Profile, 61 | profileMw, 62 | "handle2", 63 | to, 64 | link3SignerPk 65 | ); 66 | assertEq(secondId, 3); 67 | 68 | // primary profile is still 2 69 | assertEq(link3Profile.getPrimaryProfile(to), 2); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /test/integration/middleware/subscribe/SubscribeOnlyOnceMw.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Test.sol"; 6 | 7 | import { IProfileNFTEvents } from "../../../../src/interfaces/IProfileNFTEvents.sol"; 8 | 9 | import { LibDeploy } from "../../../../script/libraries/LibDeploy.sol"; 10 | import { Constants } from "../../../../src/libraries/Constants.sol"; 11 | import { DataTypes } from "../../../../src/libraries/DataTypes.sol"; 12 | 13 | import { TestLibFixture } from "../../../utils/TestLibFixture.sol"; 14 | import { SubscribeOnlyOnceMw } from "../../../../src/middlewares/subscribe/SubscribeOnlyOnceMw.sol"; 15 | import { ProfileNFT } from "../../../../src/core/ProfileNFT.sol"; 16 | import { TestIntegrationBase } from "../../../utils/TestIntegrationBase.sol"; 17 | 18 | contract SubscribeOnlyOnceMwTest is TestIntegrationBase, IProfileNFTEvents { 19 | uint256 bobProfileId; 20 | address profileDescriptorAddress; 21 | SubscribeOnlyOnceMw subMw; 22 | 23 | event Transfer( 24 | address indexed from, 25 | address indexed to, 26 | uint256 indexed id 27 | ); 28 | 29 | function setUp() public { 30 | _setUp(); 31 | subMw = new SubscribeOnlyOnceMw(); 32 | vm.label(address(subMw), "SubscribeMiddleware"); 33 | string memory handle = "bob"; 34 | address to = bob; 35 | string memory uri = "uri"; 36 | 37 | bobProfileId = TestLibFixture.registerProfile( 38 | vm, 39 | link3Profile, 40 | profileMw, 41 | handle, 42 | to, 43 | link3SignerPk 44 | ); 45 | 46 | engine.allowSubscribeMw(address(subMw), true); 47 | vm.prank(bob); 48 | link3Profile.setSubscribeData( 49 | bobProfileId, 50 | uri, 51 | address(subMw), 52 | new bytes(0) 53 | ); 54 | } 55 | 56 | function testSubscribeOnlyOnce() public { 57 | uint256[] memory ids = new uint256[](1); 58 | ids[0] = bobProfileId; 59 | bytes[] memory data = new bytes[](1); 60 | 61 | address subscribeProxy = getDeployedSubProxyAddress( 62 | addrs.subBeacon, 63 | bobProfileId, 64 | address(link3Profile), 65 | "bob" 66 | ); 67 | vm.expectEmit(true, true, false, true, address(link3Profile)); 68 | emit DeploySubscribeNFT(bobProfileId, address(subscribeProxy)); 69 | 70 | vm.expectEmit(true, true, true, true, address(subscribeProxy)); 71 | emit Transfer(address(0), alice, 1); 72 | 73 | vm.expectEmit(true, false, false, true, address(link3Profile)); 74 | emit Subscribe(alice, ids, data, data); 75 | 76 | vm.prank(alice); 77 | link3Profile.subscribe(DataTypes.SubscribeParams(ids), data, data); 78 | 79 | assertEq(link3Profile.getSubscribeNFT(bobProfileId), subscribeProxy); 80 | 81 | // Second subscribe will fail 82 | vm.expectRevert("Already subscribed"); 83 | vm.prank(alice); 84 | link3Profile.subscribe(DataTypes.SubscribeParams(ids), data, data); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /test/periphery/CyberBoxNFTUpgrade.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Test.sol"; 6 | import { ERC1967Proxy } from "openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol"; 7 | 8 | import { ICyberBoxEvents } from "../../src/interfaces/ICyberBoxEvents.sol"; 9 | 10 | import { Constants } from "../../src/libraries/Constants.sol"; 11 | 12 | import { MockCyberBoxV2 } from "../utils/MockCyberBoxV2.sol"; 13 | import { CyberBoxNFT } from "../../src/periphery/CyberBoxNFT.sol"; 14 | 15 | contract CyberBoxNFTUpgradeTest is Test, ICyberBoxEvents { 16 | CyberBoxNFT internal cyberBox; 17 | address constant owner = address(0xe); 18 | 19 | function setUp() public { 20 | CyberBoxNFT impl = new CyberBoxNFT(); 21 | bytes memory data = abi.encodeWithSelector( 22 | CyberBoxNFT.initialize.selector, 23 | owner, 24 | owner, 25 | "TestBox", 26 | "TB" 27 | ); 28 | ERC1967Proxy proxy = new ERC1967Proxy(address(impl), data); 29 | cyberBox = CyberBoxNFT(address(proxy)); 30 | } 31 | 32 | function testCannotUpgradeToAndCallAsNonOwner() public { 33 | assertEq(CyberBoxNFT(address(cyberBox)).version(), 1); 34 | MockCyberBoxV2 implV2 = new MockCyberBoxV2(); 35 | 36 | vm.expectRevert("UNAUTHORIZED"); 37 | CyberBoxNFT(address(cyberBox)).upgradeToAndCall( 38 | address(implV2), 39 | abi.encodeWithSelector(MockCyberBoxV2.version.selector) 40 | ); 41 | assertEq(CyberBoxNFT(address(cyberBox)).version(), 1); 42 | } 43 | 44 | function testCannotUpgradeAsNonOwner() public { 45 | assertEq(CyberBoxNFT(address(cyberBox)).version(), 1); 46 | MockCyberBoxV2 implV2 = new MockCyberBoxV2(); 47 | 48 | vm.expectRevert("UNAUTHORIZED"); 49 | CyberBoxNFT(address(cyberBox)).upgradeTo(address(implV2)); 50 | assertEq(CyberBoxNFT(address(cyberBox)).version(), 1); 51 | } 52 | 53 | function testUpgrade() public { 54 | assertEq(CyberBoxNFT(address(cyberBox)).version(), 1); 55 | MockCyberBoxV2 implV2 = new MockCyberBoxV2(); 56 | 57 | vm.prank(owner); 58 | CyberBoxNFT(address(cyberBox)).upgradeTo(address(implV2)); 59 | assertEq(CyberBoxNFT(address(cyberBox)).version(), 2); 60 | } 61 | 62 | function testUpgradeToAndCall() public { 63 | assertEq(CyberBoxNFT(address(cyberBox)).version(), 1); 64 | MockCyberBoxV2 implV2 = new MockCyberBoxV2(); 65 | 66 | vm.prank(owner); 67 | CyberBoxNFT(address(cyberBox)).upgradeToAndCall( 68 | address(implV2), 69 | abi.encodeWithSelector(MockCyberBoxV2.version.selector) 70 | ); 71 | assertEq(CyberBoxNFT(address(cyberBox)).version(), 2); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /test/utils/MockCyberBoxV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { CyberBoxNFT } from "../../src/periphery/CyberBoxNFT.sol"; 6 | 7 | contract MockCyberBoxV2 is CyberBoxNFT { 8 | function version() external pure override returns (uint256) { 9 | return 2; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/utils/MockERC1155.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "openzeppelin-contracts/contracts/token/ERC1155/ERC1155.sol"; 6 | 7 | contract MockERC1155 is ERC1155 { 8 | constructor(string memory url) ERC1155(url) {} 9 | 10 | function mint( 11 | address to, 12 | uint256 tokenId, 13 | uint256 amount 14 | ) external { 15 | _mint(to, tokenId, amount, ""); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/utils/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; 6 | 7 | contract MockERC20 is ERC20 { 8 | constructor(string memory name, string memory symbol) ERC20(name, symbol) { 9 | // Mint tokens to msg.sender 10 | // Similar to how 11 | // 1 dollar = 100 cents 12 | // 1 token = 1 * (10 ** decimals) 13 | _mint(msg.sender, 100 * 10**uint256(decimals())); 14 | } 15 | 16 | function mint(address to, uint256 amount) external { 17 | _mint(to, amount); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/utils/MockERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "openzeppelin-contracts/contracts/token/ERC721/ERC721.sol"; 6 | 7 | contract MockERC721 is ERC721 { 8 | constructor(string memory name, string memory symbol) ERC721(name, symbol) { 9 | // mint four NFT tokens to msg.sender 10 | _mint(msg.sender, 1); 11 | _mint(msg.sender, 2); 12 | _mint(msg.sender, 3); 13 | _mint(msg.sender, 4); 14 | } 15 | 16 | function mint(address to, uint256 tokenId) external { 17 | _mint(to, tokenId); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/utils/MockEngine.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { CyberEngine } from "../../src/core/CyberEngine.sol"; 6 | 7 | contract MockEngine is CyberEngine { 8 | function setNamespaceInfo( 9 | string calldata name, 10 | address profileMw, 11 | address namespace 12 | ) external { 13 | _namespaceInfo[namespace].name = name; 14 | _namespaceInfo[namespace].profileMw = profileMw; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/utils/MockEngineV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { CyberEngine } from "../../src/core/CyberEngine.sol"; 6 | 7 | contract MockEngineV2 is CyberEngine { 8 | function version() external pure override returns (uint256) { 9 | return 100; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/utils/MockInitializable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import { Initializable } from "openzeppelin-contracts/contracts/proxy/utils/Initializable.sol"; 6 | 7 | /** 8 | * @title MockInitializable 9 | * @dev This contract is a mock to test initializable functionality 10 | */ 11 | contract MockInitializable is Initializable { 12 | bool public initializerRan; 13 | bool public onlyInitializingRan; 14 | uint256 public x; 15 | 16 | function initialize() public initializer { 17 | initializerRan = true; 18 | } 19 | 20 | function initializeOnlyInitializing() public onlyInitializing { 21 | onlyInitializingRan = true; 22 | } 23 | 24 | function initializerNested() public initializer { 25 | initialize(); 26 | } 27 | 28 | function onlyInitializingNested() public initializer { 29 | initializeOnlyInitializing(); 30 | } 31 | 32 | function initializeWithX(uint256 _x) public payable initializer { 33 | x = _x; 34 | } 35 | 36 | function nonInitializable(uint256 _x) public payable { 37 | x = _x; 38 | } 39 | 40 | function fail() public pure { 41 | require(false, "InitializableMock forced failure"); 42 | } 43 | } 44 | 45 | contract MockConstructorInitializable is Initializable { 46 | bool public initializerRan; 47 | bool public onlyInitializingRan; 48 | 49 | constructor() initializer { 50 | initialize(); 51 | initializeOnlyInitializing(); 52 | } 53 | 54 | function initialize() public initializer { 55 | initializerRan = true; 56 | } 57 | 58 | function initializeOnlyInitializing() public onlyInitializing { 59 | onlyInitializingRan = true; 60 | } 61 | } 62 | 63 | contract MockChildConstructorInitializable is MockConstructorInitializable { 64 | bool public childInitializerRan; 65 | 66 | constructor() initializer { 67 | childInitialize(); 68 | } 69 | 70 | function childInitialize() public initializer { 71 | childInitializerRan = true; 72 | } 73 | } 74 | 75 | contract DisableNew is Initializable { 76 | constructor() { 77 | _disableInitializers(); 78 | } 79 | } 80 | 81 | contract DisableOld is Initializable { 82 | constructor() initializer {} 83 | } 84 | 85 | contract DisableBad1 is DisableNew, DisableOld {} 86 | 87 | contract DisableBad2 is Initializable { 88 | constructor() initializer { 89 | _disableInitializers(); 90 | } 91 | } 92 | 93 | contract DisableOk is DisableOld, DisableNew {} 94 | -------------------------------------------------------------------------------- /test/utils/MockLink5NFTDescriptor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { IProfileNFTDescriptor } from "../../src/interfaces/IProfileNFTDescriptor.sol"; 6 | 7 | import { DataTypes } from "../../src/libraries/DataTypes.sol"; 8 | 9 | contract MockLink5NFTDescriptor is IProfileNFTDescriptor { 10 | function tokenURI(DataTypes.ConstructTokenURIParams calldata) 11 | external 12 | pure 13 | returns (string memory) 14 | { 15 | return "Link5TokenURI"; 16 | } 17 | 18 | function setAnimationTemplate(string calldata template) external {} 19 | } 20 | -------------------------------------------------------------------------------- /test/utils/MockNFT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { CyberNFTBase } from "../../src/base/CyberNFTBase.sol"; 6 | 7 | contract MockNFT is CyberNFTBase { 8 | function tokenURI(uint256) public pure override returns (string memory) { 9 | return ""; 10 | } 11 | 12 | function mint(address _to) public returns (uint256) { 13 | return super._mint(_to); 14 | } 15 | 16 | function initialize(string calldata _name, string calldata _symbol) 17 | external 18 | initializer 19 | { 20 | super._initialize(_name, _symbol); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/utils/MockPausable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import { Pausable } from "../../src/dependencies/openzeppelin/Pausable.sol"; 6 | 7 | contract MockPausable is Pausable { 8 | bool public drasticMeasureTaken; 9 | uint256 public count; 10 | 11 | constructor() { 12 | drasticMeasureTaken = false; 13 | count = 0; 14 | } 15 | 16 | function normalProcess() external whenNotPaused { 17 | count++; 18 | } 19 | 20 | function drasticMeasure() external whenPaused { 21 | drasticMeasureTaken = true; 22 | } 23 | 24 | function pause() external { 25 | _pause(); 26 | } 27 | 28 | function unpause() external { 29 | _unpause(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/utils/MockProfile.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { DataTypes } from "../../src/libraries/DataTypes.sol"; 6 | 7 | import { ProfileNFT } from "../../src/core/ProfileNFT.sol"; 8 | 9 | contract MockProfile is ProfileNFT { 10 | // set internal states for testing 11 | function setSubscribeNFTAddress(uint256 profileId, address subscribeAddr) 12 | external 13 | { 14 | _subscribeByProfileId[profileId].subscribeNFT = subscribeAddr; 15 | } 16 | 17 | // set internal states for testing 18 | function setEssenceNFTAddress( 19 | uint256 profileId, 20 | uint256 essenceId, 21 | address essenceAddr 22 | ) external { 23 | _essenceByIdByProfileId[profileId][essenceId].essenceNFT = essenceAddr; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/utils/MockProfileV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { ProfileNFT } from "../../src/core/ProfileNFT.sol"; 6 | 7 | contract MockProfileV2 is ProfileNFT { 8 | function version() external pure override returns (uint256) { 9 | return 100; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/utils/MockSubscribeNFTV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { SubscribeNFT } from "../../src/core/SubscribeNFT.sol"; 6 | 7 | contract MockSubscribeNFTV2 is SubscribeNFT { 8 | function version() external pure override returns (uint256) { 9 | return 100; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/utils/TestIntegrationBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Test.sol"; 6 | 7 | import { ProfileNFT } from "../../src/core/ProfileNFT.sol"; 8 | import { CyberEngine } from "../../src/core/CyberEngine.sol"; 9 | import { Link3ProfileDescriptor } from "../../src/periphery/Link3ProfileDescriptor.sol"; 10 | import { PermissionedFeeCreationMw } from "../../src/middlewares/profile/PermissionedFeeCreationMw.sol"; 11 | import { CollectOnlySubscribedMw } from "../../src/middlewares/essence/CollectOnlySubscribedMw.sol"; 12 | import { Treasury } from "../../src/middlewares/base/Treasury.sol"; 13 | 14 | import { LibDeploy } from "../../script/libraries/LibDeploy.sol"; 15 | 16 | import { TestProxy } from "./TestProxy.sol"; 17 | 18 | abstract contract TestIntegrationBase is Test, TestProxy { 19 | uint256 internal constant link3SignerPk = 1890; 20 | address internal immutable link3Signer = vm.addr(link3SignerPk); 21 | address internal constant alice = address(0xDEADA11CE); 22 | uint256 internal constant bobPk = 548; 23 | address internal immutable bob = vm.addr(bobPk); 24 | address internal constant carly = address(0xDEADCA11); 25 | address internal constant dixon = address(0xDEADD1); 26 | address internal constant link3Treasury = address(0xDEAD3333); 27 | 28 | address internal constant engineTreasury = address(0xDEADEEEE); 29 | 30 | address link3EssBeacon; 31 | address link3SubBeacon; 32 | 33 | ProfileNFT link3Profile; 34 | Link3ProfileDescriptor profileDescriptor; 35 | PermissionedFeeCreationMw profileMw; 36 | CollectOnlySubscribedMw collectMw; 37 | CyberEngine engine; 38 | Treasury treasury; 39 | 40 | LibDeploy.ContractAddresses addrs; 41 | 42 | function _setUp() internal { 43 | addrs = LibDeploy.deployInTest( 44 | vm, 45 | link3Signer, 46 | link3Treasury, 47 | engineTreasury 48 | ); 49 | link3Profile = ProfileNFT(addrs.link3Profile); 50 | profileDescriptor = Link3ProfileDescriptor(addrs.link3DescriptorProxy); 51 | profileMw = PermissionedFeeCreationMw(addrs.link3ProfileMw); 52 | engine = CyberEngine(addrs.engineProxyAddress); 53 | treasury = Treasury(addrs.cyberTreasury); 54 | link3EssBeacon = addrs.essBeacon; 55 | link3SubBeacon = addrs.subBeacon; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /test/utils/TestLib712.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | library TestLib712 { 6 | bytes32 private constant _TYPE_HASH = 7 | keccak256( 8 | "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" 9 | ); 10 | 11 | // Util function 12 | function hashTypedDataV4( 13 | address addr, 14 | bytes32 structHash, 15 | string memory name, 16 | string memory version 17 | ) internal view returns (bytes32) { 18 | bytes32 ds = domainSeparator(name, version, addr); 19 | return keccak256(abi.encodePacked("\x19\x01", ds, structHash)); 20 | } 21 | 22 | function domainSeparator( 23 | string memory name, 24 | string memory version, 25 | address addr 26 | ) internal view returns (bytes32) { 27 | return 28 | keccak256( 29 | abi.encode( 30 | _TYPE_HASH, 31 | keccak256(bytes(name)), 32 | keccak256(bytes(version)), 33 | block.chainid, 34 | addr 35 | ) 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/utils/TestLibFixture.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import "forge-std/Vm.sol"; 6 | import { RolesAuthority } from "../../src/dependencies/solmate/RolesAuthority.sol"; 7 | 8 | import { IProfileNFT } from "../../src/interfaces/IProfileNFT.sol"; 9 | 10 | import { Constants } from "../../src/libraries/Constants.sol"; 11 | import { DataTypes } from "../../src/libraries/DataTypes.sol"; 12 | import { ProfileNFT } from "../../src/core/ProfileNFT.sol"; 13 | import { LibDeploy } from "../../script/libraries/LibDeploy.sol"; 14 | 15 | import { TestLib712 } from "./TestLib712.sol"; 16 | import { PermissionedFeeCreationMw } from "../../src/middlewares/profile/PermissionedFeeCreationMw.sol"; 17 | 18 | // Only for testing, not for deploying script 19 | // TODO: move to test folder 20 | library TestLibFixture { 21 | // Need to be called after auth 22 | string private constant avatar = "avatar"; 23 | string private constant metadata = "metadata"; 24 | 25 | function registerProfile( 26 | Vm vm, 27 | ProfileNFT profile, 28 | PermissionedFeeCreationMw mw, 29 | string memory handle, 30 | address mintToEOA, 31 | uint256 signerPk 32 | ) internal returns (uint256 profileId) { 33 | uint256 deadline = block.timestamp + 60 * 60; 34 | uint256 nonce = mw.getNonce(address(profile), mintToEOA); 35 | address operator = address(0); 36 | 37 | bytes32 digest = TestLib712.hashTypedDataV4( 38 | address(mw), 39 | keccak256( 40 | abi.encode( 41 | Constants._CREATE_PROFILE_TYPEHASH, 42 | mintToEOA, 43 | keccak256(bytes(handle)), 44 | keccak256(bytes(avatar)), 45 | keccak256(bytes(metadata)), 46 | operator, 47 | nonce, 48 | deadline 49 | ) 50 | ), 51 | "PermissionedFeeCreationMw", 52 | "1" 53 | ); 54 | (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPk, digest); 55 | profileId = profile.createProfile{ 56 | value: LibDeploy._INITIAL_FEE_TIER2 57 | }( 58 | DataTypes.CreateProfileParams( 59 | mintToEOA, 60 | handle, 61 | avatar, 62 | metadata, 63 | address(0) 64 | ), 65 | abi.encode(v, r, s, deadline), 66 | new bytes(0) 67 | ); 68 | require(mw.getNonce(address(profile), mintToEOA) == nonce + 1); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /test/utils/TestProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity 0.8.14; 4 | 5 | import { BeaconProxy } from "openzeppelin-contracts/contracts/proxy/beacon/BeaconProxy.sol"; 6 | 7 | import { ISubscribeNFT } from "../../src/interfaces/ISubscribeNFT.sol"; 8 | import { IEssenceNFT } from "../../src/interfaces/IEssenceNFT.sol"; 9 | import { LibString } from "../../src/libraries/LibString.sol"; 10 | import { Constants } from "../../src/libraries/Constants.sol"; 11 | 12 | import { LibDeploy } from "../../script/libraries/LibDeploy.sol"; 13 | 14 | contract TestProxy { 15 | function getDeployedSubProxyAddress( 16 | address subscribeBeacon, 17 | uint256 profileId, 18 | address profile, 19 | string memory handle 20 | ) internal pure returns (address) { 21 | string memory name = string( 22 | abi.encodePacked(handle, Constants._SUBSCRIBE_NFT_NAME_SUFFIX) 23 | ); 24 | string memory symbol = string( 25 | abi.encodePacked( 26 | LibString.toUpper(handle), 27 | Constants._SUBSCRIBE_NFT_SYMBOL_SUFFIX 28 | ) 29 | ); 30 | return 31 | LibDeploy._computeAddress( 32 | abi.encodePacked( 33 | type(BeaconProxy).creationCode, 34 | abi.encode( 35 | subscribeBeacon, 36 | abi.encodeWithSelector( 37 | ISubscribeNFT.initialize.selector, 38 | profileId, 39 | name, 40 | symbol 41 | ) 42 | ) 43 | ), 44 | bytes32(profileId), 45 | profile 46 | ); 47 | } 48 | 49 | function getDeployedEssProxyAddress( 50 | address essBeacon, 51 | uint256 profileId, 52 | uint256 essenceId, 53 | address profile, 54 | string memory name, 55 | string memory symbol, 56 | bool transferable 57 | ) internal pure returns (address) { 58 | return 59 | LibDeploy._computeAddress( 60 | abi.encodePacked( 61 | type(BeaconProxy).creationCode, 62 | abi.encode( 63 | essBeacon, 64 | abi.encodeWithSelector( 65 | IEssenceNFT.initialize.selector, 66 | profileId, 67 | essenceId, 68 | name, 69 | symbol, 70 | transferable 71 | ) 72 | ) 73 | ), 74 | bytes32(profileId), 75 | profile 76 | ); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true 9 | } 10 | } 11 | --------------------------------------------------------------------------------