├── .github
└── workflows
│ ├── publish.yaml
│ └── push.yaml
├── .gitignore
├── .mocharc.json
├── .prettierrc
├── Dockerfile
├── LICENSE
├── README.md
├── contracts
├── attesters
│ ├── hydra-s1
│ │ ├── HydraS1AccountboundAttester.sol
│ │ ├── HydraS1SimpleAttester.sol
│ │ ├── base
│ │ │ ├── HydraS1Base.sol
│ │ │ └── IHydraS1Base.sol
│ │ ├── interfaces
│ │ │ ├── IHydraS1AccountboundAttester.sol
│ │ │ └── IHydraS1SimpleAttester.sol
│ │ └── libs
│ │ │ ├── HydraS1AccountboundLib.sol
│ │ │ └── HydraS1Lib.sol
│ └── pythia-1
│ │ ├── Pythia1SimpleAttester.sol
│ │ ├── base
│ │ ├── IPythia1Base.sol
│ │ └── Pythia1Base.sol
│ │ ├── interfaces
│ │ └── IPythia1SimpleAttester.sol
│ │ └── libs
│ │ └── Pythia1Lib.sol
├── core
│ ├── AttestationsRegistry.sol
│ ├── Attester.sol
│ ├── Badges.sol
│ ├── Front.sol
│ ├── interfaces
│ │ ├── IAttestationsRegistry.sol
│ │ ├── IAttestationsRegistryConfigLogic.sol
│ │ ├── IAttester.sol
│ │ ├── IBadges.sol
│ │ └── IFront.sol
│ ├── libs
│ │ ├── Structs.sol
│ │ ├── attestations-registry
│ │ │ ├── AttestationsRegistryConfigLogic.sol
│ │ │ ├── AttestationsRegistryState.sol
│ │ │ ├── InitializableLogic.sol
│ │ │ ├── OwnableLogic.sol
│ │ │ └── PausableLogic.sol
│ │ └── utils
│ │ │ ├── Address.sol
│ │ │ ├── Bitmap256Bit.sol
│ │ │ ├── Context.sol
│ │ │ └── RangeLib.sol
│ └── utils
│ │ ├── AddressesProvider.sol
│ │ └── interfaces
│ │ └── IAddressesProvider.sol
├── libs
│ ├── SismoLib.sol
│ └── using-sismo
│ │ └── UsingSismo.sol
├── periphery
│ └── utils
│ │ ├── AvailableRootsRegistry.sol
│ │ ├── CommitmentMapperRegistry.sol
│ │ ├── FrontendLib.sol
│ │ ├── TransparentUpgradeableProxy.sol
│ │ └── interfaces
│ │ ├── IAvailableRootsRegistry.sol
│ │ └── ICommitmentMapperRegistry.sol
├── tests
│ ├── MockHydraS1SimpleAttester.sol
│ └── mocks
│ │ ├── MockAttestationsRegistry.sol
│ │ ├── MockAttester.sol
│ │ └── mockContractUsingSismoLib.sol
└── zkdrop
│ └── ZKBadgeboundERC721.sol
├── deployments
├── gnosis
│ ├── .chainId
│ ├── AttestationsRegistry.json
│ ├── AttestationsRegistryImplem.json
│ ├── AttestationsRegistryProxy.json
│ ├── AvailableRootsRegistry.json
│ ├── AvailableRootsRegistryImplem.json
│ ├── AvailableRootsRegistryProxy.json
│ ├── Badges.json
│ ├── BadgesImplem.json
│ ├── BadgesProxy.json
│ ├── CommitmentMapperRegistry.json
│ ├── CommitmentMapperRegistryImplem.json
│ ├── CommitmentMapperRegistryProxy.json
│ ├── Front.json
│ ├── FrontImplem.json
│ ├── FrontProxy.json
│ ├── FrontendLib.json
│ ├── HydraS1AccountboundAttester.json
│ ├── HydraS1AccountboundAttesterImplem.json
│ ├── HydraS1AccountboundAttesterProxy.json
│ ├── HydraS1Verifier.json
│ ├── Pythia1SimpleAttester.json
│ ├── Pythia1SimpleAttesterImplem.json
│ ├── Pythia1SimpleAttesterProxy.json
│ ├── Pythia1Verifier.json
│ └── solcInputs
│ │ └── 61c38ae61d36c4e0fe74ede913f00b14.json
├── goerliStaging
│ ├── .chainId
│ ├── AddressesProviderStaging.json
│ ├── AddressesProviderStagingImplem.json
│ ├── AddressesProviderStagingProxy.json
│ ├── AttestationsRegistry.json
│ ├── AttestationsRegistryImplem.json
│ ├── AttestationsRegistryProxy.json
│ ├── AvailableRootsRegistry.json
│ ├── AvailableRootsRegistryImplem.json
│ ├── AvailableRootsRegistryProxy.json
│ ├── Badges.json
│ ├── BadgesImplem.json
│ ├── BadgesProxy.json
│ ├── CommitmentMapperRegistry.json
│ ├── CommitmentMapperRegistryImplem.json
│ ├── CommitmentMapperRegistryProxy.json
│ ├── Front.json
│ ├── FrontImplem.json
│ ├── FrontProxy.json
│ ├── FrontendLib.json
│ ├── HydraS1AccountboundAttester.json
│ ├── HydraS1AccountboundAttesterImplem.json
│ ├── HydraS1AccountboundAttesterProxy.json
│ ├── HydraS1SimpleAttester.json
│ ├── HydraS1SimpleAttesterImplem.json
│ ├── HydraS1SimpleAttesterImplemV2.json
│ ├── HydraS1SimpleAttesterImplemV3.json
│ ├── HydraS1SimpleAttesterProxy.json
│ ├── HydraS1SoulboundAttester.json
│ ├── HydraS1SoulboundAttesterImplem.json
│ ├── HydraS1SoulboundAttesterProxy.json
│ ├── HydraS1Verifier.json
│ ├── Pythia1SimpleAttester.json
│ ├── Pythia1SimpleAttesterImplem.json
│ ├── Pythia1SimpleAttesterImplemV2.json
│ ├── Pythia1SimpleAttesterProxy.json
│ ├── Pythia1Verifier.json
│ ├── ZKBadgeboundERC721.json
│ ├── ZikiPass.json
│ ├── ZikiPassImplem.json
│ ├── ZikiPassProxy.json
│ └── solcInputs
│ │ ├── 24c70469fd559e01f6ff2a10472da9a6.json
│ │ ├── 3c35a0b3eece336a6bec6b7e7cad1298.json
│ │ ├── 61c38ae61d36c4e0fe74ede913f00b14.json
│ │ ├── 62cbcc15387d7a9f73c9f91e370ed0e0.json
│ │ ├── 6a43a49cef4871e7629c3936a225083d.json
│ │ ├── 6edb98fea2bf424a369954d0e80655f6.json
│ │ ├── 70d5ec851bd4311fac67c09b114b9c0c.json
│ │ ├── 7e84cd39af8dda1388150d22fc6a7983.json
│ │ ├── 8cd3fe249ae2a6d76ecd75bde0d70b64.json
│ │ ├── 9638c30436d05a5fd0170ba05ff60057.json
│ │ ├── 99f49ed252adf262e947b5c642bd53f3.json
│ │ ├── c7c67c4a1ddf53de4ef76f8a114dfc39.json
│ │ └── ca3a3d06406f39be0521e9dff90ae191.json
├── goerliTestnet
│ ├── .chainId
│ ├── AddressesProvider.json
│ ├── AddressesProviderImplem.json
│ ├── AddressesProviderProxy.json
│ ├── AttestationsRegistry.json
│ ├── AttestationsRegistryImplem.json
│ ├── AttestationsRegistryProxy.json
│ ├── AvailableRootsRegistry.json
│ ├── AvailableRootsRegistryImplem.json
│ ├── AvailableRootsRegistryProxy.json
│ ├── Badges.json
│ ├── BadgesImplem.json
│ ├── BadgesProxy.json
│ ├── CommitmentMapperRegistry.json
│ ├── CommitmentMapperRegistryImplem.json
│ ├── CommitmentMapperRegistryProxy.json
│ ├── Front.json
│ ├── FrontImplem.json
│ ├── FrontProxy.json
│ ├── FrontendLib.json
│ ├── HydraS1AccountboundAttester.json
│ ├── HydraS1AccountboundAttesterImplem.json
│ ├── HydraS1AccountboundAttesterProxy.json
│ ├── HydraS1Verifier.json
│ ├── Pythia1SimpleAttester.json
│ ├── Pythia1SimpleAttesterImplem.json
│ ├── Pythia1SimpleAttesterProxy.json
│ ├── Pythia1Verifier.json
│ ├── ZikiPass.json
│ ├── ZikiPassImplem.json
│ ├── ZikiPassProxy.json
│ └── solcInputs
│ │ ├── 61c38ae61d36c4e0fe74ede913f00b14.json
│ │ └── 6a43a49cef4871e7629c3936a225083d.json
├── local
│ ├── .chainId
│ ├── AttestationsRegistry.json
│ ├── AttestationsRegistryImplem.json
│ ├── AttestationsRegistryProxy.json
│ ├── AvailableRootsRegistry.json
│ ├── AvailableRootsRegistryImplem.json
│ ├── AvailableRootsRegistryProxy.json
│ ├── Badges.json
│ ├── BadgesImplem.json
│ ├── BadgesProxy.json
│ ├── CommitmentMapperRegistry.json
│ ├── CommitmentMapperRegistryImplem.json
│ ├── CommitmentMapperRegistryProxy.json
│ ├── Front.json
│ ├── FrontImplem.json
│ ├── FrontProxy.json
│ ├── HydraS1SimpleAttester.json
│ ├── HydraS1SimpleAttesterImplem.json
│ ├── HydraS1SimpleAttesterProxy.json
│ └── HydraS1Verifier.json
├── mainnet
│ ├── .chainId
│ ├── AddressesProvider.json
│ ├── AddressesProviderImplem.json
│ ├── AddressesProviderProxy.json
│ ├── AttestationsRegistry.json
│ ├── AttestationsRegistryImplem.json
│ ├── AttestationsRegistryProxy.json
│ ├── AvailableRootsRegistry.json
│ ├── AvailableRootsRegistryImplem.json
│ ├── AvailableRootsRegistryProxy.json
│ ├── Badges.json
│ ├── BadgesImplem.json
│ ├── BadgesProxy.json
│ ├── CommitmentMapperRegistry.json
│ ├── CommitmentMapperRegistryImplem.json
│ ├── CommitmentMapperRegistryProxy.json
│ ├── Front.json
│ ├── FrontImplem.json
│ ├── FrontProxy.json
│ ├── HydraS1AccountboundAttester.json
│ ├── HydraS1AccountboundAttesterImplem.json
│ ├── HydraS1AccountboundAttesterProxy.json
│ ├── HydraS1Verifier.json
│ ├── MergooorPass.json
│ ├── MergooorPassImplem.json
│ ├── MergooorPassProxy.json
│ ├── Pythia1SimpleAttester.json
│ ├── Pythia1SimpleAttesterImplem.json
│ ├── Pythia1SimpleAttesterProxy.json
│ ├── Pythia1Verifier.json
│ └── solcInputs
│ │ ├── 17323799ce052e363180ed575741910c.json
│ │ └── f1771477a6a95f548250af6302581d47.json
├── mumbaiStaging
│ ├── .chainId
│ ├── AttestationsRegistry.json
│ ├── AttestationsRegistryImplem.json
│ ├── AttestationsRegistryProxy.json
│ ├── AvailableRootsRegistry.json
│ ├── AvailableRootsRegistryImplem.json
│ ├── AvailableRootsRegistryProxy.json
│ ├── Badges.json
│ ├── BadgesImplem.json
│ ├── BadgesProxy.json
│ ├── CommitmentMapperRegistry.json
│ ├── CommitmentMapperRegistryImplem.json
│ ├── CommitmentMapperRegistryProxy.json
│ ├── Front.json
│ ├── FrontImplem.json
│ ├── FrontProxy.json
│ ├── FrontendLib.json
│ ├── HydraS1AccountboundAttester.json
│ ├── HydraS1AccountboundAttesterImplem.json
│ ├── HydraS1SoulboundAttester.json
│ ├── HydraS1SoulboundAttesterImplem.json
│ ├── HydraS1SoulboundAttesterProxy.json
│ ├── HydraS1Verifier.json
│ ├── Pythia1SimpleAttester.json
│ ├── Pythia1SimpleAttesterImplem.json
│ ├── Pythia1SimpleAttesterProxy.json
│ ├── Pythia1Verifier.json
│ └── solcInputs
│ │ ├── 24c70469fd559e01f6ff2a10472da9a6.json
│ │ ├── 61c38ae61d36c4e0fe74ede913f00b14.json
│ │ ├── 6edb98fea2bf424a369954d0e80655f6.json
│ │ ├── 70d5ec851bd4311fac67c09b114b9c0c.json
│ │ ├── 8cd3fe249ae2a6d76ecd75bde0d70b64.json
│ │ └── c7c67c4a1ddf53de4ef76f8a114dfc39.json
├── mumbaiTestnet
│ ├── .chainId
│ ├── AttestationsRegistry.json
│ ├── AttestationsRegistryImplem.json
│ ├── AttestationsRegistryProxy.json
│ ├── AvailableRootsRegistry.json
│ ├── AvailableRootsRegistryImplem.json
│ ├── AvailableRootsRegistryProxy.json
│ ├── Badges.json
│ ├── BadgesImplem.json
│ ├── BadgesProxy.json
│ ├── CommitmentMapperRegistry.json
│ ├── CommitmentMapperRegistryImplem.json
│ ├── CommitmentMapperRegistryProxy.json
│ ├── Front.json
│ ├── FrontImplem.json
│ ├── FrontProxy.json
│ ├── FrontendLib.json
│ ├── HydraS1AccountboundAttester.json
│ ├── HydraS1AccountboundAttesterImplem.json
│ ├── HydraS1AccountboundAttesterProxy.json
│ ├── HydraS1Verifier.json
│ ├── Pythia1SimpleAttester.json
│ ├── Pythia1SimpleAttesterImplem.json
│ ├── Pythia1SimpleAttesterProxy.json
│ ├── Pythia1Verifier.json
│ └── solcInputs
│ │ ├── 61c38ae61d36c4e0fe74ede913f00b14.json
│ │ └── 6a43a49cef4871e7629c3936a225083d.json
├── polygon
│ ├── .chainId
│ ├── AttestationsRegistry.json
│ ├── AttestationsRegistryImplem.json
│ ├── AttestationsRegistryProxy.json
│ ├── AvailableRootsRegistry.json
│ ├── AvailableRootsRegistryImplem.json
│ ├── AvailableRootsRegistryProxy.json
│ ├── Badges.json
│ ├── BadgesImplem.json
│ ├── BadgesProxy.json
│ ├── CommitmentMapperRegistry.json
│ ├── CommitmentMapperRegistryImplem.json
│ ├── CommitmentMapperRegistryProxy.json
│ ├── Front.json
│ ├── FrontImplem.json
│ ├── FrontProxy.json
│ ├── FrontendLib.json
│ ├── HydraS1AccountboundAttester.json
│ ├── HydraS1AccountboundAttesterImplem.json
│ ├── HydraS1SimpleAttester.json
│ ├── HydraS1SimpleAttesterImplem.json
│ ├── HydraS1SimpleAttesterProxy.json
│ ├── HydraS1SoulboundAttester.json
│ ├── HydraS1SoulboundAttesterImplem.json
│ ├── HydraS1SoulboundAttesterProxy.json
│ ├── HydraS1Verifier.json
│ ├── Pythia1SimpleAttester.json
│ ├── Pythia1SimpleAttesterImplem.json
│ ├── Pythia1SimpleAttesterProxy.json
│ ├── Pythia1Verifier.json
│ └── solcInputs
│ │ ├── 61c38ae61d36c4e0fe74ede913f00b14.json
│ │ ├── 70d5ec851bd4311fac67c09b114b9c0c.json
│ │ ├── c7c67c4a1ddf53de4ef76f8a114dfc39.json
│ │ └── c872f238f220b3571ef309821a459203.json
├── polygonPlayground
│ ├── .chainId
│ ├── AttestationsRegistry.json
│ ├── AttestationsRegistryImplem.json
│ ├── AttestationsRegistryProxy.json
│ ├── AvailableRootsRegistry.json
│ ├── AvailableRootsRegistryImplem.json
│ ├── AvailableRootsRegistryProxy.json
│ ├── Badges.json
│ ├── BadgesImplem.json
│ ├── BadgesProxy.json
│ ├── CommitmentMapperRegistry.json
│ ├── CommitmentMapperRegistryImplem.json
│ ├── CommitmentMapperRegistryProxy.json
│ ├── Front.json
│ ├── FrontImplem.json
│ ├── FrontProxy.json
│ ├── HydraS1AccountboundAttester.json
│ ├── HydraS1AccountboundAttesterImplem.json
│ ├── HydraS1SimpleAttester.json
│ ├── HydraS1SimpleAttesterImplem.json
│ ├── HydraS1SimpleAttesterProxy.json
│ ├── HydraS1SoulboundAttester.json
│ ├── HydraS1SoulboundAttesterImplem.json
│ ├── HydraS1SoulboundAttesterProxy.json
│ ├── HydraS1Verifier.json
│ ├── Pythia1SimpleAttester.json
│ ├── Pythia1SimpleAttesterImplem.json
│ ├── Pythia1SimpleAttesterProxy.json
│ ├── Pythia1Verifier.json
│ └── solcInputs
│ │ ├── 6edb98fea2bf424a369954d0e80655f6.json
│ │ ├── 70d5ec851bd4311fac67c09b114b9c0c.json
│ │ ├── c7c67c4a1ddf53de4ef76f8a114dfc39.json
│ │ └── c872f238f220b3571ef309821a459203.json
└── rinkeby
│ ├── .chainId
│ ├── AttestationsRegistry.json
│ ├── AttestationsRegistryImplem.json
│ ├── AttestationsRegistryProxy.json
│ ├── AvailableRootsRegistry.json
│ ├── AvailableRootsRegistryImplem.json
│ ├── AvailableRootsRegistryProxy.json
│ ├── Badges.json
│ ├── BadgesImplem.json
│ ├── BadgesProxy.json
│ ├── CommitmentMapperRegistry.json
│ ├── CommitmentMapperRegistryImplem.json
│ ├── CommitmentMapperRegistryProxy.json
│ ├── Front.json
│ ├── FrontImplem.json
│ ├── FrontProxy.json
│ ├── HydraS1SimpleAttester.json
│ ├── HydraS1SimpleAttesterImplem.json
│ ├── HydraS1SimpleAttesterProxy.json
│ ├── HydraS1SoulboundAttester.json
│ ├── HydraS1SoulboundAttesterImplem.json
│ ├── HydraS1SoulboundAttesterProxy.json
│ ├── HydraS1Verifier.json
│ ├── Pythia1SimpleAttester.json
│ ├── Pythia1SimpleAttesterImplem.json
│ ├── Pythia1SimpleAttesterProxy.json
│ ├── Pythia1Verifier.json
│ └── solcInputs
│ ├── 70d5ec851bd4311fac67c09b114b9c0c.json
│ └── c872f238f220b3571ef309821a459203.json
├── docs
├── schema1.png
└── top.png
├── hardhat.config.ts
├── helper-hardhat-config.ts
├── package.json
├── scripts
└── wait-for-local-chain.sh
├── tasks
├── addresses-provider
│ └── set-batch.task.ts
├── available-roots-registry
│ ├── register-for-attester.task.ts
│ └── unregister-for-attester.task.ts
├── deploy-tasks
│ ├── batch
│ │ └── deploy-core.task.ts
│ ├── deployments-config.ts
│ ├── full
│ │ ├── 0-deploy-core-and-hydra-s1-simple-and-accountbound-and-pythia1.task.ts
│ │ ├── 1-deploy-pythia-1-simple.task.ts
│ │ ├── 2-upgrade-proxies.task.ts
│ │ ├── 2-upgrade-proxies.test-fork.ts
│ │ ├── 3-new-hydra-s1-verifier-and-upgrade-hydra-s1-simple-proxy.task.ts
│ │ ├── 3-new-hydra-s1-verifier-and-upgrade-hydra-s1-simple-proxy.test-fork.ts
│ │ ├── 4-upgrade-attestations-registry-proxy-and-badges-proxy.task.ts
│ │ ├── 4-upgrade-attestations-registry-proxy-and-badges-proxy.test-fork.ts
│ │ ├── 5-upgrade-proxies-with-reinitializer.task.ts
│ │ ├── 5-upgrade-proxies-with-reinitializer
│ │ │ ├── 5-upgrade-proxies-with-reinitializer-available-roots-registry.test-fork.ts
│ │ │ ├── 5-upgrade-proxies-with-reinitializer-commitment-mapper-registry.test-fork.ts
│ │ │ └── 5-upgrade-proxies-with-reinitializer-pythia1.test-fork.ts
│ │ ├── 6-7-8-fork-test
│ │ │ └── 6-7-8.test-fork.ts
│ │ ├── 6-deploy-sismo-addresses-provider.task.ts
│ │ ├── 7-upgrade-hydra-s1-accountbound-and-pythia-1-proxies.task.ts
│ │ ├── 9-fork-test
│ │ │ └── 9-upgrade-addresses-provider-on-testnets.test-fork.ts
│ │ ├── 9-upgrade-addresses-provider-on-testnets.task.ts
│ │ ├── local
│ │ │ └── deploy-full-local.task.ts
│ │ └── staging
│ │ │ └── deploy-sismo-addresses-provider-staging.task.ts
│ ├── tests
│ │ ├── deploy-mock-attestations-registry.task.ts
│ │ ├── deploy-mock-attester-and-core.task.ts
│ │ ├── deploy-mock-attester.task.ts
│ │ ├── deploy-mock-contract-using-sismo-lib.task.ts
│ │ └── deploy-zk-badgebound-erc721.task.ts
│ ├── unit
│ │ ├── attesters
│ │ │ ├── hydra-s1
│ │ │ │ ├── deploy-hydra-s1-accountbound-attester.task.ts
│ │ │ │ ├── deploy-hydra-s1-simple-attester.task.ts
│ │ │ │ └── deploy-hydra-s1-verifier.task.ts
│ │ │ └── pythia-1
│ │ │ │ ├── deploy-pythia-1-simple-attester.task.ts
│ │ │ │ └── deploy-pythia-1-verifier.task.ts
│ │ ├── core
│ │ │ ├── deploy-attestations-registry.task.ts
│ │ │ ├── deploy-badges.task.ts
│ │ │ ├── deploy-front.task.ts
│ │ │ └── deploy-sismo-addresses-provider.task.ts
│ │ └── periphery
│ │ │ ├── deploy-available-roots-registry.task.ts
│ │ │ ├── deploy-commitment-mapper-registry.task.ts
│ │ │ └── deploy-frontend-lib.task.ts
│ ├── utils
│ │ ├── deployment.ts
│ │ ├── deployments-config-types.ts
│ │ └── index.ts
│ └── zkdrop
│ │ ├── deploy-mergooor-pass.task.ts
│ │ ├── deploy-ziki-pass-staging.task.ts
│ │ └── deploy-ziki-pass-testnet.task.ts
├── helpers
│ ├── authorizations
│ │ ├── access-control-grant-role.task.ts
│ │ ├── access-control-revoke-role.task.ts
│ │ ├── attestations-registry-authorize-range.task.ts
│ │ ├── attestations-registry-transfer-ownership.task.ts
│ │ ├── change-proxy-admin.task.ts
│ │ └── ownable-transfer-ownership.task.ts
│ ├── forge-create2-transaction.task.ts
│ ├── print-accounts.task.ts
│ ├── print-storage-layout.task.ts
│ ├── proxy
│ │ └── upgrade-proxy.task.ts
│ └── verify-contract.task.ts
└── utils
│ ├── common-options.ts
│ ├── confirm.ts
│ ├── index.ts
│ ├── relayer.ts
│ └── types.ts
├── test
├── e2e
│ └── e2e.test.ts
├── unit
│ ├── attesters
│ │ ├── hydra-s1
│ │ │ ├── hydra-s1-accountbound-attester.test.ts
│ │ │ └── hydra-s1-simple-attester.test.ts
│ │ └── pythia-1
│ │ │ └── pythia-1-simple-attester.test.ts
│ ├── core
│ │ ├── attestations-registry
│ │ │ ├── attestations-registry-config-logic.test.ts
│ │ │ └── attestations-registry.test.ts
│ │ ├── badges.test.ts
│ │ ├── front.test.ts
│ │ └── utils
│ │ │ └── sismo-addresses-provider.test.ts
│ ├── libs
│ │ └── using-sismo
│ │ │ └── using-sismo.test.ts
│ ├── periphery
│ │ └── utils
│ │ │ ├── available-roots-registry.test.ts
│ │ │ ├── commitment-mapper-registry.test.ts
│ │ │ └── frontend-lib.test.ts
│ └── zkdrop
│ │ └── zk-badgebound-erc721.test.ts
└── utils
│ ├── attestation-logic.ts
│ ├── evm.ts
│ ├── expectEvent.ts
│ ├── hydra-s1-accountbound.ts
│ ├── hydra-s1.ts
│ ├── index.ts
│ ├── pythia-1.ts
│ ├── setup.ts
│ └── test-helpers.ts
├── tsconfig.json
├── utils
├── constants.ts
├── index.ts
├── proxy.ts
└── singletonFactory.ts
└── yarn.lock
/.github/workflows/publish.yaml:
--------------------------------------------------------------------------------
1 | name: Publish Docker image
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*'
7 |
8 | jobs:
9 | push_to_registry:
10 | name: Push Docker image to Docker Hub
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Check out the repo
14 | uses: actions/checkout@v3
15 |
16 | - name: Set up QEMU
17 | uses: docker/setup-qemu-action@v2
18 |
19 | - name: Set up Docker Buildx
20 | uses: docker/setup-buildx-action@v2
21 |
22 | - name: Log in to Docker Hub
23 | uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
24 | with:
25 | username: ${{ secrets.DOCKER_USERNAME }}
26 | password: ${{ secrets.DOCKER_PASSWORD }}
27 |
28 | - name: Extract metadata (tags, labels) for Docker
29 | id: meta
30 | uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
31 | with:
32 | images: sismo/sismo-protocol
33 |
34 | - name: Build and push Docker image
35 | uses: docker/build-push-action@v3
36 | with:
37 | context: .
38 | push: true
39 | platforms: linux/amd64,linux/arm64/v8
40 | tags: ${{ steps.meta.outputs.tags }}
41 | labels: ${{ steps.meta.outputs.labels }}
42 |
43 |
--------------------------------------------------------------------------------
/.github/workflows/push.yaml:
--------------------------------------------------------------------------------
1 | name: On Push checks
2 | on:
3 | push:
4 | jobs:
5 | test:
6 | runs-on: ubuntu-latest
7 | name: Compile, test and test deploy
8 | steps:
9 | - uses: actions/checkout@v2
10 | - name: Setup node
11 | uses: actions/setup-node@v2
12 | with:
13 | node-version: '16.x'
14 | cache: yarn
15 | - run: yarn install --frozen-lockfile
16 | - run: yarn compile
17 | - name: test
18 | run: yarn test
19 | - name: deploy local script
20 | run: npx concurrently --kill-others -s command-1 "npx hardhat node" "sleep 2 & npx yarn deploy:local"
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | deployments
3 | cache
4 | artifacts
5 | typechain-types
6 | types/**
7 | .vscode
8 | deployments/local
9 | save
10 | .env
11 |
12 |
--------------------------------------------------------------------------------
/.mocharc.json:
--------------------------------------------------------------------------------
1 | {
2 | "require": "ts-node/register/files",
3 | "timeout": 20000
4 | }
5 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "trailingComma": "es5",
4 | "semi": true,
5 | "singleQuote": true,
6 | "tabWidth": 2,
7 | "overrides": [
8 | {
9 | "files": "*.sol",
10 | "options": {
11 | "semi": true,
12 | "printWidth": 100
13 | }
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:16 AS build
2 |
3 | WORKDIR /usr/src/build
4 | # Install dependencies
5 | COPY package.json yarn.lock ./
6 |
7 | RUN yarn install --frozen-lockfile
8 | COPY . .
9 | RUN yarn compile
10 |
11 | FROM node:16-slim AS run
12 | RUN apt-get -y update && apt-get -y install netcat
13 | WORKDIR /usr/src/app
14 | COPY --from=build /usr/src/build/ .
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Sismo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 | This repository contains the smart contracts of the Sismo Protocol.
27 |
28 | There are three core contracts:
29 |
30 | - `core/AttestationsRegistry.sol`: The registry stores all attestations. It is owned by the governance that authorizes/unauthorize issuers to record in it
31 | - `core/Attester.sol` The standard abstract contract must be inherited by attesters. Attesters are issuers of attestations. They verify user requests and build attestations that will be recorded in the registry
32 | - `core/Badges.sol` Reads the registry. Stateless Non Transferable Token view of attestations (ERC1155)
33 |
34 | It also contains implementations of attester in `attesters/`:
35 | - `HydraS1SimpleAttester.sol`: ZK Attester using the [Hydra S1 Proving Scheme](https://hydra-s1.docs.sismo.io) and the notion of nullifiers. Users must provide a ZK Proof along with their request to generate attestations
36 | - `HydraS1AccountboundAttester.sol`: Accountbound version of the Simple Hydra S1 Simple Attester. (Users can update at will where the attestation is stored)
37 |
38 |
39 |
40 |
41 | ## Sismo protocol
42 |
43 | A complete overview of the protocol is available in our [documentation](https://protocol.docs.sismo.io)
44 |
45 |
46 | ## Deployed contracts
47 |
48 | Deployed contracts can be found [here](https://docs.sismo.io/sismo-docs/deployed-contract-addresses)
49 |
50 |
51 | ## Usage
52 | ### Installation
53 | ```
54 | yarn
55 | ```
56 |
57 | ### Compile contracts
58 | Compile contracts using hardhat
59 | ```
60 | yarn compile
61 | ```
62 |
63 | ### Test
64 | Launch all tests
65 |
66 | ```
67 | yarn test
68 | ```
69 |
70 | ### Print storage layout
71 | ```
72 | yarn storage-layout
73 | ```
74 |
75 | ### Deploy on local chain
76 |
77 | Terminal tab 1
78 | ```
79 | yarn chain
80 | ```
81 |
82 | Terminal tab 2
83 | ```
84 | yarn deploy:local
85 | ```
86 |
87 |
88 | ## Create a new Attester
89 |
90 | To develop a new attester, you must inherit the `core/Attester.sol` abstract contract and implement the following functions:
91 |
92 | - `_verifyRequest(request, proofData)`: You must implement the user request verification against the proof provided by the user
93 | - `buildAttestations(request, proofData)`: You must build the attestations that will be recorded from a verified user request
94 |
95 | Other optional hook functions that can be implemented:
96 |
97 | - `_beforeRecordAttestations(request, proofData)`
98 | - `_afterRecordAttestations(request, proofData)`
99 |
100 | The `/attesters/hydra-s1/HydraS1SimpleAttester.sol` is a good example of an attester implementing those functions.
101 |
102 | A [guide](https://attesters.docs.sismo.io) is offered in our documentation.
103 |
104 | Feel free open a PR with your new attester in `/attester`!
105 |
106 | ## License
107 |
108 | Distributed under the MIT License.
109 |
110 | ## Contribute
111 |
112 | Please, feel free to open issues, PRs or simply provide feedback!
113 |
114 | ## Contact
115 |
116 | Prefer [Discord](https://discord.gg/sismo) or [Twitter](https://twitter.com/sismo_eth)
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/contracts/attesters/hydra-s1/base/IHydraS1Base.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.8.14;
4 | pragma experimental ABIEncoderV2;
5 |
6 | import {IAttester} from '../../../core/interfaces/IAttester.sol';
7 | import {HydraS1Verifier, HydraS1Lib, HydraS1ProofData} from '../libs/HydraS1Lib.sol';
8 | import {ICommitmentMapperRegistry} from '../../../periphery/utils/CommitmentMapperRegistry.sol';
9 | import {IAvailableRootsRegistry} from '../../../periphery/utils/AvailableRootsRegistry.sol';
10 |
11 | /**
12 | * @title Hydra-S1 Base Interface
13 | * @author Sismo
14 | * @notice Interface that facilitates the use of the Hydra-S1 ZK Proving Scheme.
15 | * Hydra-S1 is single source, single group: it allows users to verify they are part of one and only one group at a time
16 | * It is inherited by the family of Hydra-S1 attesters.
17 | * It contains the errors and method specific of the Hydra-S1 attesters family and the Hydra-S1 ZK Proving Scheme
18 | * We invite readers to refer to the following:
19 | * - https://hydra-s1.docs.sismo.io for a full guide through the Hydra-S1 ZK Attestations
20 | * - https://hydra-s1-circuits.docs.sismo.io for circuits, prover and verifiers of Hydra-S1
21 | **/
22 | interface IHydraS1Base is IAttester {
23 | error ClaimsLengthDifferentThanOne(uint256 claimLength);
24 | error RegistryRootMismatch(uint256 inputRoot);
25 | error DestinationMismatch(address expectedDestination, address inputDestination);
26 | error CommitmentMapperPubKeyMismatch(
27 | uint256 expectedX,
28 | uint256 expectedY,
29 | uint256 inputX,
30 | uint256 inputY
31 | );
32 | error ExternalNullifierMismatch(uint256 expectedExternalNullifier, uint256 externalNullifier);
33 | error IsStrictMismatch(bool expectedStrictness, bool strictNess);
34 | error ChainIdMismatch(uint256 expectedChainId, uint256 chainId);
35 | error ValueMismatch(uint256 expectedValue, uint256 inputValue);
36 | error AccountsTreeValueMismatch(
37 | uint256 expectedAccountsTreeValue,
38 | uint256 inputAccountsTreeValue
39 | );
40 | error InvalidGroth16Proof(string reason);
41 |
42 | function getNullifierFromExtraData(bytes memory extraData) external view returns (uint256);
43 |
44 | /**
45 | * @dev Getter of Hydra-S1 Verifier contract
46 | */
47 | function getVerifier() external view returns (HydraS1Verifier);
48 |
49 | /**
50 | * @dev Getter of Commitment Mapper Registry contract
51 | */
52 | function getCommitmentMapperRegistry() external view returns (ICommitmentMapperRegistry);
53 |
54 | /**
55 | * @dev Getter of Roots Registry Contract
56 | */
57 | function getAvailableRootsRegistry() external view returns (IAvailableRootsRegistry);
58 | }
59 |
--------------------------------------------------------------------------------
/contracts/attesters/hydra-s1/interfaces/IHydraS1AccountboundAttester.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.8.14;
4 | pragma experimental ABIEncoderV2;
5 |
6 | import {IHydraS1SimpleAttester} from '././IHydraS1SimpleAttester.sol';
7 |
8 | /**
9 | * @title Hydra-S1 Accountbound Interface
10 | * @author Sismo
11 | * @notice Interface of the HydraS1AccountboundAttester contract which inherits from the errors, events and methods specific to the HydraS1SimpleAttester interface.
12 | **/
13 | interface IHydraS1AccountboundAttester is IHydraS1SimpleAttester {
14 | /**
15 | * @dev Event emitted when the duration of the cooldown duration for a group index (internal collection id) has been set
16 | * @param groupIndex internal collection id
17 | * @param cooldownDuration the duration of the cooldown period
18 | **/
19 | event CooldownDurationSetForGroupIndex(uint256 indexed groupIndex, uint32 cooldownDuration);
20 |
21 | /**
22 | * @dev Event emitted when the nullifier has been set on cooldown. This happens when the
23 | * attestation destination of a nullifier has been changed
24 | * @param nullifier user nullifier
25 | * @param burnCount the number of times the attestation destination of a nullifier has been changed
26 | **/
27 | event NullifierSetOnCooldown(uint256 indexed nullifier, uint16 burnCount);
28 |
29 | /**
30 | * @dev Error when the nullifier is on cooldown. The user have to wait the cooldownDuration
31 | * before being able to change again the destination address.
32 | **/
33 | error NullifierOnCooldown(
34 | uint256 nullifier,
35 | address destination,
36 | uint16 burnCount,
37 | uint32 cooldownStart
38 | );
39 |
40 | /**
41 | * @dev Error when the cooldown duration for a given groupIndex is equal to zero.
42 | * The HydraS1AccountboundAttester behaves like the HydraS1SimpleAttester.
43 | **/
44 | error CooldownDurationNotSetForGroupIndex(uint256 groupIndex);
45 |
46 | /**
47 | * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
48 | * @param owner Owner of the contract, can update public key and address
49 | */
50 | function initialize(address owner) external;
51 |
52 | /**
53 | * @dev returns the nullifier for a given extraData
54 | * @param extraData bytes where the nullifier is encoded
55 | */
56 | function getNullifierFromExtraData(bytes memory extraData) external pure returns (uint256);
57 |
58 | /**
59 | * @dev Returns the burn count for a given extraData
60 | * @param extraData bytes where the burnCount is encoded
61 | */
62 | function getBurnCountFromExtraData(bytes memory extraData) external pure returns (uint16);
63 |
64 | /**
65 | * @dev Getter, returns the cooldown start of a nullifier
66 | * @param nullifier nullifier used
67 | **/
68 | function getNullifierCooldownStart(uint256 nullifier) external view returns (uint32);
69 |
70 | /**
71 | * @dev Getter, returns the burnCount of a nullifier
72 | * @param nullifier nullifier used
73 | **/
74 | function getNullifierBurnCount(uint256 nullifier) external view returns (uint16);
75 |
76 | /**
77 | * @dev Setter, sets the cooldown duration of a groupIndex
78 | * @param groupIndex internal collection id
79 | * @param cooldownDuration cooldown duration we want to set for the groupIndex
80 | **/
81 | function setCooldownDurationForGroupIndex(uint256 groupIndex, uint32 cooldownDuration) external;
82 |
83 | /*/**
84 | * @dev Getter, get the cooldown duration of a groupIndex
85 | * @notice returns 0 when the accountbound feature is deactivated for this group
86 | * @param groupIndex internal collection id
87 | **/
88 | function getCooldownDurationForGroupIndex(uint256 groupIndex) external view returns (uint32);
89 | }
90 |
--------------------------------------------------------------------------------
/contracts/attesters/hydra-s1/interfaces/IHydraS1SimpleAttester.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.8.14;
4 | pragma experimental ABIEncoderV2;
5 |
6 | import {Attestation} from '../../../core/libs/Structs.sol';
7 | import {CommitmentMapperRegistry} from '../../../periphery/utils/CommitmentMapperRegistry.sol';
8 | import {AvailableRootsRegistry} from '../../../periphery/utils/AvailableRootsRegistry.sol';
9 | import {HydraS1Lib, HydraS1ProofData, HydraS1ProofInput} from './../libs/HydraS1Lib.sol';
10 | import {IHydraS1Base} from './../base/IHydraS1Base.sol';
11 |
12 | /**
13 | * @title Hydra-S1 Accountbound Interface
14 | * @author Sismo
15 | * @notice Interface with errors, events and methods specific to the HydraS1SimpleAttester.
16 | **/
17 | interface IHydraS1SimpleAttester is IHydraS1Base {
18 | /**
19 | * @dev Error when the nullifier is already used for a destination address
20 | **/
21 | error NullifierUsed(uint256 nullifier);
22 |
23 | /**
24 | * @dev Error when the collectionId of an attestation overflow the AUTHORIZED_COLLECTION_ID_LAST
25 | **/
26 | error CollectionIdOutOfBound(uint256 collectionId);
27 |
28 | /**
29 | * @dev Event emitted when the nullifier is associated to a destination address.
30 | **/
31 | event NullifierDestinationUpdated(uint256 nullifier, address newOwner);
32 |
33 | /**
34 | * @dev Getter, returns the last attestation destination of a nullifier
35 | * @param nullifier nullifier used
36 | **/
37 | function getDestinationOfNullifier(uint256 nullifier) external view returns (address);
38 |
39 | /**
40 | * @dev Getter
41 | * returns of the first collection in which the attester is supposed to record
42 | **/
43 | function AUTHORIZED_COLLECTION_ID_FIRST() external view returns (uint256);
44 |
45 | /**
46 | * @dev Getter
47 | * returns of the last collection in which the attester is supposed to record
48 | **/
49 | function AUTHORIZED_COLLECTION_ID_LAST() external view returns (uint256);
50 | }
51 |
--------------------------------------------------------------------------------
/contracts/attesters/hydra-s1/libs/HydraS1AccountboundLib.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | import {Claim, Request} from '../../../core/libs/Structs.sol';
5 | import {HydraS1Lib, HydraS1Claim, HydraS1GroupProperties} from './HydraS1Lib.sol';
6 |
7 | // user Hydra-S1 claim retrieved form his request
8 | struct HydraS1AccountboundClaim {
9 | uint256 groupId; // user claims to have an account in this group
10 | uint256 claimedValue; // user claims this value for its account in the group
11 | address destination; // user claims to own this destination[]
12 | HydraS1AccountboundGroupProperties groupProperties; // user claims the group has the following properties
13 | }
14 |
15 | struct HydraS1AccountboundGroupProperties {
16 | uint128 groupIndex;
17 | uint32 generationTimestamp;
18 | uint32 cooldownDuration;
19 | bool isScore;
20 | }
21 |
22 | library HydraS1AccountboundLib {
23 | error GroupIdAndPropertiesMismatch(uint256 expectedGroupId, uint256 groupId);
24 |
25 | function _hydraS1claim(Request memory self) internal pure returns (HydraS1Claim memory) {
26 | Claim memory claim = self.claims[0];
27 | _validateClaim(claim);
28 |
29 | HydraS1AccountboundGroupProperties memory groupProperties = abi.decode(
30 | claim.extraData,
31 | (HydraS1AccountboundGroupProperties)
32 | );
33 |
34 | HydraS1GroupProperties memory hydraS1GroupProperties = HydraS1GroupProperties(
35 | groupProperties.groupIndex,
36 | groupProperties.generationTimestamp,
37 | groupProperties.isScore
38 | );
39 |
40 | return (
41 | HydraS1Claim(claim.groupId, claim.claimedValue, self.destination, hydraS1GroupProperties)
42 | );
43 | }
44 |
45 | function _hydraS1Accountboundclaim(
46 | Request memory self
47 | ) internal pure returns (HydraS1AccountboundClaim memory) {
48 | Claim memory claim = self.claims[0];
49 | _validateClaim(claim);
50 |
51 | HydraS1AccountboundGroupProperties memory hydraS1AccountboundGroupProperties = abi.decode(
52 | claim.extraData,
53 | (HydraS1AccountboundGroupProperties)
54 | );
55 |
56 | return (
57 | HydraS1AccountboundClaim(
58 | claim.groupId,
59 | claim.claimedValue,
60 | self.destination,
61 | hydraS1AccountboundGroupProperties
62 | )
63 | );
64 | }
65 |
66 | function _generateGroupIdFromEncodedProperties(
67 | bytes memory encodedProperties
68 | ) internal pure returns (uint256) {
69 | return uint256(keccak256(encodedProperties)) % HydraS1Lib.SNARK_FIELD;
70 | }
71 |
72 | function _validateClaim(Claim memory claim) internal pure {
73 | uint256 expectedGroupId = _generateGroupIdFromEncodedProperties(claim.extraData);
74 | if (claim.groupId != expectedGroupId)
75 | revert GroupIdAndPropertiesMismatch(expectedGroupId, claim.groupId);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/contracts/attesters/pythia-1/base/IPythia1Base.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.8.14;
4 | pragma experimental ABIEncoderV2;
5 |
6 | import {Pythia1Verifier, Pythia1Lib, Pythia1ProofData} from '../libs/Pythia1Lib.sol';
7 |
8 | interface IPythia1Base {
9 | error DestinationMismatch(address expectedDestination, address inputDestination);
10 | error UserShouldOwnItsDestination(address sender, address inputdestination);
11 | error CommitmentSignerPubKeyMismatch(
12 | uint256 expectedX,
13 | uint256 expectedY,
14 | uint256 inputX,
15 | uint256 inputY
16 | );
17 | error TicketIdentifierMismatch(uint256 expectedTicketIdentifier, uint256 ticketIdentifier);
18 | error IsStrictMismatch(bool expectedStrictness, bool strictNess);
19 | error ChainIdMismatch(uint256 expectedChainId, uint256 chainId);
20 | error ValueMismatch(uint256 expectedValue, uint256 inputValue);
21 | error GroupIdMismatch(uint256 expectedAccountsTreeValue, uint256 inputAccountsTreeValue);
22 | error InvalidGroth16Proof(string reason);
23 |
24 | /**
25 | * @dev Getter of Pythia-1 Verifier contract
26 | */
27 | function getVerifier() external view returns (Pythia1Verifier);
28 |
29 | /**
30 | * @dev Getter of the Commitment Signer EdDSA Public Key
31 | */
32 | function getCommitmentSignerPubKey() external view returns (uint256[2] memory);
33 | }
34 |
--------------------------------------------------------------------------------
/contracts/attesters/pythia-1/interfaces/IPythia1SimpleAttester.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.8.14;
4 | pragma experimental ABIEncoderV2;
5 |
6 | import {Attestation} from '../../../core/libs/Structs.sol';
7 | import {IAttester} from '../../../core/interfaces/IAttester.sol';
8 | import {Pythia1Lib, Pythia1ProofData, Pythia1ProofInput} from './../libs/Pythia1Lib.sol';
9 | import {IPythia1Base} from './../base/IPythia1Base.sol';
10 |
11 | interface IPythia1SimpleAttester is IPythia1Base, IAttester {
12 | error TicketUsed(uint256 userTicket);
13 | error CollectionIdOutOfBound(uint256 collectionId);
14 |
15 | event TicketDestinationUpdated(uint256 ticket, address newOwner);
16 | event CommitmentSignerPubKeyUpdated(uint256[2] newCommitmentSignerPubKey);
17 |
18 | /**
19 | * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
20 | * @param commitmentSignerPubKey EdDSA public key of the commitment signer
21 | * @param owner Owner of the contract, can update public key and address
22 | * @notice The reinitializer modifier is needed to configure modules that are added through upgrades and that require initialization.
23 | */
24 | function initialize(uint256[2] memory commitmentSignerPubKey, address owner) external;
25 |
26 | /**
27 | * @dev Getter, returns the last attestation destination of a ticket
28 | * @param userTicket ticket used
29 | **/
30 | function getDestinationOfTicket(uint256 userTicket) external view returns (address);
31 |
32 | /**
33 | * @dev Getter
34 | * returns of the first collection in which the attester is supposed to record
35 | **/
36 | function AUTHORIZED_COLLECTION_ID_FIRST() external view returns (uint256);
37 |
38 | /**
39 | * @dev Getter
40 | * returns of the last collection in which the attester is supposed to record
41 | **/
42 | function AUTHORIZED_COLLECTION_ID_LAST() external view returns (uint256);
43 | }
44 |
--------------------------------------------------------------------------------
/contracts/core/interfaces/IAttestationsRegistry.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | import {Attestation, AttestationData} from '../libs/Structs.sol';
5 | import {IAttestationsRegistryConfigLogic} from './IAttestationsRegistryConfigLogic.sol';
6 |
7 | /**
8 | * @title IAttestationsRegistry
9 | * @author Sismo
10 | * @notice This is the interface of the AttestationRegistry
11 | */
12 | interface IAttestationsRegistry is IAttestationsRegistryConfigLogic {
13 | error IssuerNotAuthorized(address issuer, uint256 collectionId);
14 | error OwnersAndCollectionIdsLengthMismatch(address[] owners, uint256[] collectionIds);
15 | event AttestationRecorded(Attestation attestation);
16 | event AttestationDeleted(Attestation attestation);
17 |
18 | /**
19 | * @dev Main function to be called by authorized issuers
20 | * @param attestations Attestations to be recorded (creates a new one or overrides an existing one)
21 | */
22 | function recordAttestations(Attestation[] calldata attestations) external;
23 |
24 | /**
25 | * @dev Delete function to be called by authorized issuers
26 | * @param owners The owners of the attestations to be deleted
27 | * @param collectionIds The collection ids of the attestations to be deleted
28 | */
29 | function deleteAttestations(address[] calldata owners, uint256[] calldata collectionIds) external;
30 |
31 | /**
32 | * @dev Returns whether a user has an attestation from a collection
33 | * @param collectionId Collection identifier of the targeted attestation
34 | * @param owner Owner of the targeted attestation
35 | */
36 | function hasAttestation(uint256 collectionId, address owner) external returns (bool);
37 |
38 | /**
39 | * @dev Getter of the data of a specific attestation
40 | * @param collectionId Collection identifier of the targeted attestation
41 | * @param owner Owner of the targeted attestation
42 | */
43 | function getAttestationData(
44 | uint256 collectionId,
45 | address owner
46 | ) external view returns (AttestationData memory);
47 |
48 | /**
49 | * @dev Getter of the value of a specific attestation
50 | * @param collectionId Collection identifier of the targeted attestation
51 | * @param owner Owner of the targeted attestation
52 | */
53 | function getAttestationValue(uint256 collectionId, address owner) external view returns (uint256);
54 |
55 | /**
56 | * @dev Getter of the data of a specific attestation as tuple
57 | * @param collectionId Collection identifier of the targeted attestation
58 | * @param owner Owner of the targeted attestation
59 | */
60 | function getAttestationDataTuple(
61 | uint256 collectionId,
62 | address owner
63 | ) external view returns (address, uint256, uint32, bytes memory);
64 |
65 | /**
66 | * @dev Getter of the extraData of a specific attestation
67 | * @param collectionId Collection identifier of the targeted attestation
68 | * @param owner Owner of the targeted attestation
69 | */
70 | function getAttestationExtraData(
71 | uint256 collectionId,
72 | address owner
73 | ) external view returns (bytes memory);
74 |
75 | /**
76 | * @dev Getter of the issuer of a specific attestation
77 | * @param collectionId Collection identifier of the targeted attestation
78 | * @param owner Owner of the targeted attestation
79 | */
80 | function getAttestationIssuer(
81 | uint256 collectionId,
82 | address owner
83 | ) external view returns (address);
84 |
85 | /**
86 | * @dev Getter of the timestamp of a specific attestation
87 | * @param collectionId Collection identifier of the targeted attestation
88 | * @param owner Owner of the targeted attestation
89 | */
90 | function getAttestationTimestamp(
91 | uint256 collectionId,
92 | address owner
93 | ) external view returns (uint32);
94 |
95 | /**
96 | * @dev Getter of the data of specific attestations
97 | * @param collectionIds Collection identifiers of the targeted attestations
98 | * @param owners Owners of the targeted attestations
99 | */
100 | function getAttestationDataBatch(
101 | uint256[] memory collectionIds,
102 | address[] memory owners
103 | ) external view returns (AttestationData[] memory);
104 |
105 | /**
106 | * @dev Getter of the values of specific attestations
107 | * @param collectionIds Collection identifiers of the targeted attestations
108 | * @param owners Owners of the targeted attestations
109 | */
110 | function getAttestationValueBatch(
111 | uint256[] memory collectionIds,
112 | address[] memory owners
113 | ) external view returns (uint256[] memory);
114 | }
115 |
--------------------------------------------------------------------------------
/contracts/core/interfaces/IAttester.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | import {Request, Attestation} from '../libs/Structs.sol';
5 | import {IAttestationsRegistry} from '../interfaces/IAttestationsRegistry.sol';
6 |
7 | /**
8 | * @title IAttester
9 | * @author Sismo
10 | * @notice This is the interface for the attesters in Sismo Protocol
11 | */
12 | interface IAttester {
13 | event AttestationGenerated(Attestation attestation);
14 |
15 | event AttestationDeleted(Attestation attestation);
16 |
17 | error AttestationDeletionNotImplemented();
18 |
19 | /**
20 | * @dev Main external function. Allows to generate attestations by making a request and submitting proof
21 | * @param request User request
22 | * @param proofData Data sent along the request to prove its validity
23 | * @return attestations Attestations that has been recorded
24 | */
25 | function generateAttestations(
26 | Request calldata request,
27 | bytes calldata proofData
28 | ) external returns (Attestation[] memory);
29 |
30 | /**
31 | * @dev High level function to generate attestations by making a request and submitting proof
32 | * @param request User request
33 | * @param proofData Data sent along the request to prove its validity
34 | * @return badges owner, badges tokenIds and badges values
35 | */
36 | function mintBadges(
37 | Request calldata request,
38 | bytes calldata proofData
39 | ) external returns (address, uint256[] memory, uint256[] memory);
40 |
41 | /**
42 | * @dev External facing function. Allows to delete an attestation by submitting proof
43 | * @param collectionIds Collection identifier of attestations to delete
44 | * @param attestationsOwner Owner of attestations to delete
45 | * @param proofData Data sent along the deletion request to prove its validity
46 | * @return attestations Attestations that was deleted
47 | */
48 | function deleteAttestations(
49 | uint256[] calldata collectionIds,
50 | address attestationsOwner,
51 | bytes calldata proofData
52 | ) external returns (Attestation[] memory);
53 |
54 | /**
55 | * @dev MANDATORY: must be implemented in attesters
56 | * It should build attestations from the user request and the proof
57 | * @param request User request
58 | * @param proofData Data sent along the request to prove its validity
59 | * @return attestations Attestations that will be recorded
60 | */
61 | function buildAttestations(
62 | Request calldata request,
63 | bytes calldata proofData
64 | ) external view returns (Attestation[] memory);
65 |
66 | /**
67 | * @dev Attestation registry address getter
68 | * @return attestationRegistry Address of the registry
69 | */
70 | function getAttestationRegistry() external view returns (IAttestationsRegistry);
71 | }
72 |
--------------------------------------------------------------------------------
/contracts/core/interfaces/IBadges.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | /**
5 | * @title Interface for Badges contract
6 | * @author Sismo
7 | * @notice Stateless ERC1155 contract. Reads balance from the values of attestations
8 | * The associated attestations registry triggers TransferSingle events from this contract
9 | * It allows badge "shadow mints and burns" to be caught by off-chain platforms
10 | */
11 | interface IBadges {
12 | error BadgesNonTransferrable();
13 |
14 | /**
15 | * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
16 | * @param uri Uri for the metadata of badges
17 | * @param owner Owner of the contract, super admin, can setup roles and update the attestation registry
18 | * @notice The reinitializer modifier is needed to configure modules that are added through upgrades and that require initialization.
19 | */
20 | function initialize(string memory uri, address owner) external;
21 |
22 | /**
23 | * @dev Main function of the ERC1155 badge
24 | * The balance of a user is equal to the value of the underlying attestation.
25 | * attestationCollectionId == badgeId
26 | * @param account Address to check badge balance (= value of attestation)
27 | * @param id Badge Id to check (= attestationCollectionId)
28 | */
29 | function balanceOf(address account, uint256 id) external view returns (uint256);
30 |
31 | /**
32 | * @dev Emits a TransferSingle event, so subgraphs and other off-chain apps relying on events can see badge minting/burning
33 | * can only be called by address having the EVENT_TRIGGERER_ROLE (attestations registry address)
34 | * @param operator who is calling the TransferEvent
35 | * @param from address(0) if minting, address of the badge holder if burning
36 | * @param to address of the badge holder is minting, address(0) if burning
37 | * @param id badgeId for which to trigger the event
38 | * @param value minted/burned balance
39 | */
40 | function triggerTransferEvent(
41 | address operator,
42 | address from,
43 | address to,
44 | uint256 id,
45 | uint256 value
46 | ) external;
47 |
48 | /**
49 | * @dev Set the attestations registry address. Can only be called by owner (default admin)
50 | * @param attestationsRegistry new attestations registry address
51 | */
52 | function setAttestationsRegistry(address attestationsRegistry) external;
53 |
54 | /**
55 | * @dev Set the URI. Can only be called by owner (default admin)
56 | * @param uri new attestations registry address
57 | */
58 | function setUri(string memory uri) external;
59 |
60 | /**
61 | * @dev Getter of the attestations registry
62 | */
63 | function getAttestationsRegistry() external view returns (address);
64 |
65 | /**
66 | * @dev Getter of the badge issuer
67 | * @param account Address that holds the badge
68 | * @param id Badge Id to check (= attestationCollectionId)
69 | */
70 | function getBadgeIssuer(address account, uint256 id) external view returns (address);
71 |
72 | /**
73 | * @dev Getter of the badge timestamp
74 | * @param account Address that holds the badge
75 | * @param id Badge Id to check (= attestationCollectionId)
76 | */
77 | function getBadgeTimestamp(address account, uint256 id) external view returns (uint32);
78 |
79 | /**
80 | * @dev Getter of the badge extra data (it can store nullifier and burnCount)
81 | * @param account Address that holds the badge
82 | * @param id Badge Id to check (= attestationCollectionId)
83 | */
84 | function getBadgeExtraData(address account, uint256 id) external view returns (bytes memory);
85 |
86 | /**
87 | * @dev Getter of the value of a specific badge attribute
88 | * @param id Badge Id to check (= attestationCollectionId)
89 | * @param index Index of the attribute
90 | */
91 | function getAttributeValueForBadge(uint256 id, uint8 index) external view returns (uint8);
92 |
93 | /**
94 | * @dev Getter of all badge attributes and their values for a specific badge
95 | * @param id Badge Id to check (= attestationCollectionId)
96 | */
97 | function getAttributesNamesAndValuesForBadge(
98 | uint256 id
99 | ) external view returns (bytes32[] memory, uint8[] memory);
100 | }
101 |
--------------------------------------------------------------------------------
/contracts/core/interfaces/IFront.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | import {Request, Attestation} from '../libs/Structs.sol';
5 |
6 | /**
7 | * @title IFront
8 | * @author Sismo
9 | * @notice This is the interface of the Front Contract
10 | */
11 | interface IFront {
12 | error DifferentRequestsDestinations();
13 | event EarlyUserAttestationGenerated(address destination);
14 |
15 | /**
16 | * @dev Forward a request to an attester and generates an early user attestation
17 | * @param attester Attester targeted by the request
18 | * @param request Request sent to the attester
19 | * @param proofData Data provided to the attester to back the request
20 | */
21 | function generateAttestations(
22 | address attester,
23 | Request calldata request,
24 | bytes calldata proofData
25 | ) external returns (Attestation[] memory);
26 |
27 | /**
28 | * @dev generate multiple attestations at once, to the same destination
29 | * @param attesters Attesters targeted by the attesters
30 | * @param requests Requests sent to attester
31 | * @param proofDataArray Data sent with each request
32 | */
33 | function batchGenerateAttestations(
34 | address[] calldata attesters,
35 | Request[] calldata requests,
36 | bytes[] calldata proofDataArray
37 | ) external returns (Attestation[][] memory);
38 |
39 | /**
40 | * @dev build the attestations from a user request targeting a specific attester.
41 | * Forwards to the build function of targeted attester
42 | * @param attester Targeted attester
43 | * @param request User request
44 | * @param proofData Data sent along the request to prove its validity
45 | * @return attestations Attestations that will be recorded
46 | */
47 | function buildAttestations(
48 | address attester,
49 | Request calldata request,
50 | bytes calldata proofData
51 | ) external view returns (Attestation[] memory);
52 |
53 | /**
54 | * @dev build the attestations from multiple user requests.
55 | * Forwards to the build function(s) of targeted attester(s)
56 | * @param attesters Targeted attesters
57 | * @param requests User requests
58 | * @param proofDataArray Data sent along the request to prove its validity
59 | * @return attestations Attestations that will be recorded
60 | */
61 | function batchBuildAttestations(
62 | address[] calldata attesters,
63 | Request[] calldata requests,
64 | bytes[] calldata proofDataArray
65 | ) external view returns (Attestation[][] memory);
66 | }
67 |
--------------------------------------------------------------------------------
/contracts/core/libs/Structs.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | /**
5 | * @title Attestations Registry State
6 | * @author Sismo
7 | * @notice This contract holds all of the storage variables and data
8 | * structures used by the AttestationsRegistry and parent
9 | * contracts.
10 | */
11 |
12 | // User Attestation Request, can be made by any user
13 | // The context of an Attestation Request is a specific attester contract
14 | // Each attester has groups of accounts in its available data
15 | // eg: for a specific attester:
16 | // group 1 <=> accounts that sent txs on mainnet
17 | // group 2 <=> accounts that sent txs on polygon
18 | // eg: for another attester:
19 | // group 1 <=> accounts that sent eth txs in 2022
20 | // group 2 <=> accounts sent eth txs in 2021
21 | struct Request {
22 | // implicit address attester;
23 | // implicit uint256 chainId;
24 | Claim[] claims;
25 | address destination; // destination that will receive the end attestation
26 | }
27 |
28 | struct Claim {
29 | uint256 groupId; // user claims to have an account in this group
30 | uint256 claimedValue; // user claims this value for its account in the group
31 | bytes extraData; // arbitrary data, may be required by the attester to verify claims or generate a specific attestation
32 | }
33 |
34 | /**
35 | * @dev Attestation Struct. This is the struct receive as argument by the Attestation Registry.
36 | * @param collectionId Attestation collection
37 | * @param owner Attestation collection
38 | * @param issuer Attestation collection
39 | * @param value Attestation collection
40 | * @param timestamp Attestation collection
41 | * @param extraData Attestation collection
42 | */
43 | struct Attestation {
44 | // implicit uint256 chainId;
45 | uint256 collectionId; // Id of the attestation collection (in the registry)
46 | address owner; // Owner of the attestation
47 | address issuer; // Contract that created or last updated the record.
48 | uint256 value; // Value of the attestation
49 | uint32 timestamp; // Timestamp chosen by the attester, should correspond to the effective date of the attestation
50 | // it is different from the recording timestamp (date when the attestation was recorded)
51 | // e.g a proof of NFT ownership may have be recorded today which is 2 month old data.
52 | bytes extraData; // arbitrary data that can be added by the attester
53 | }
54 |
55 | // Attestation Data, stored in the registry
56 | // The context is a specific owner of a specific collection
57 | struct AttestationData {
58 | // implicit uint256 chainId
59 | // implicit uint256 collectionId - from context
60 | // implicit owner
61 | address issuer; // Address of the contract that recorded the attestation
62 | uint256 value; // Value of the attestation
63 | uint32 timestamp; // Effective date of issuance of the attestation. (can be different from the recording timestamp)
64 | bytes extraData; // arbitrary data that can be added by the attester
65 | }
66 |
--------------------------------------------------------------------------------
/contracts/core/libs/attestations-registry/AttestationsRegistryState.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | import {Range} from '../utils/RangeLib.sol';
5 | import {Attestation, AttestationData} from '../Structs.sol';
6 |
7 | contract AttestationsRegistryState {
8 | /*******************************************************
9 | Storage layout:
10 | 19 slots for config
11 | 4 currently used for _initialized, _initializing, _paused, _owner
12 | 15 place holders
13 | 16 slots for logic
14 | 3 currently used for _authorizedRanges, _attestationsCollectionAttributesValuesBitmap, _attributesNames
15 | 13 place holders
16 | 1 slot for _attestationsData
17 | *******************************************************/
18 |
19 | // main config
20 | // changed `_initialized` from bool to uint8
21 | // as we were using OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
22 | // and changed to OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)
23 | // PR: https://github.com/sismo-core/sismo-protocol/pull/41
24 | uint8 internal _initialized;
25 | bool internal _initializing;
26 | bool internal _paused;
27 | address internal _owner;
28 | // keeping some space for future
29 | uint256[15] private _placeHoldersAdmin;
30 |
31 | // storing the authorized ranges for each attesters
32 | mapping(address => Range[]) internal _authorizedRanges;
33 | // Storing the attributes values used for each attestations collection
34 | // Each attribute value is an hexadecimal
35 | mapping(uint256 => uint256) internal _attestationsCollectionAttributesValuesBitmap;
36 | // Storing the attribute name for each attributes index
37 | mapping(uint8 => bytes32) internal _attributesNames;
38 | // keeping some space for future
39 | uint256[13] private _placeHoldersConfig;
40 | // storing the data of attestations
41 | // =collectionId=> =owner=> attestationData
42 | mapping(uint256 => mapping(address => AttestationData)) internal _attestationsData;
43 | }
44 |
--------------------------------------------------------------------------------
/contracts/core/libs/attestations-registry/OwnableLogic.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // Forked from, removed storage, OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
3 | // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
4 |
5 | pragma solidity ^0.8.14;
6 |
7 | import '../utils/Context.sol';
8 | import './AttestationsRegistryState.sol';
9 |
10 | /**
11 | * @dev Contract module which provides a basic access control mechanism, where
12 | * there is an account (an owner) that can be granted exclusive access to
13 | * specific functions.
14 | *
15 | * By default, the owner account will be the one that deploys the contract. This
16 | * can later be changed with {transferOwnership}.
17 | *
18 | * This module is used through inheritance. It will make available the modifier
19 | * `onlyOwner`, which can be applied to your functions to restrict their use to
20 | * the owner.
21 | */
22 | abstract contract OwnableLogic is Context, AttestationsRegistryState {
23 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
24 |
25 | // This is the only diff with OZ contract
26 | // address private _owner;
27 |
28 | /**
29 | * @dev Initializes the contract setting the deployer as the initial owner.
30 | */
31 | constructor() {
32 | _transferOwnership(_msgSender());
33 | }
34 |
35 | /**
36 | * @dev Returns the address of the current owner.
37 | */
38 | function owner() public view virtual returns (address) {
39 | return _owner;
40 | }
41 |
42 | /**
43 | * @dev Throws if called by any account other than the owner.
44 | */
45 | modifier onlyOwner() {
46 | require(owner() == _msgSender(), 'Ownable: caller is not the owner');
47 | _;
48 | }
49 |
50 | /**
51 | * @dev Leaves the contract without owner. It will not be possible to call
52 | * `onlyOwner` functions anymore. Can only be called by the current owner.
53 | *
54 | * NOTE: Renouncing ownership will leave the contract without an owner,
55 | * thereby removing any functionality that is only available to the owner.
56 | */
57 | function renounceOwnership() public virtual onlyOwner {
58 | _transferOwnership(address(0));
59 | }
60 |
61 | /**
62 | * @dev Transfers ownership of the contract to a new account (`newOwner`).
63 | * Can only be called by the current owner.
64 | */
65 | function transferOwnership(address newOwner) public virtual onlyOwner {
66 | require(newOwner != address(0), 'Ownable: new owner is the zero address');
67 | _transferOwnership(newOwner);
68 | }
69 |
70 | /**
71 | * @dev Transfers ownership of the contract to a new account (`newOwner`).
72 | * Internal function without access restriction.
73 | */
74 | function _transferOwnership(address newOwner) internal virtual {
75 | address oldOwner = _owner;
76 | _owner = newOwner;
77 | emit OwnershipTransferred(oldOwner, newOwner);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/contracts/core/libs/attestations-registry/PausableLogic.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // Forked from, removed storage, OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
3 | // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)
4 |
5 | pragma solidity ^0.8.14;
6 |
7 | import '../utils/Context.sol';
8 | import './AttestationsRegistryState.sol';
9 |
10 | /**
11 | * @dev Contract module which allows children to implement an emergency stop
12 | * mechanism that can be triggered by an authorized account.
13 | *
14 | * This module is used through inheritance. It will make available the
15 | * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
16 | * the functions of your contract. Note that they will not be pausable by
17 | * simply including this module, only once the modifiers are put in place.
18 | */
19 | abstract contract PausableLogic is Context, AttestationsRegistryState {
20 | /**
21 | * @dev Emitted when the pause is triggered by `account`.
22 | */
23 | event Paused(address account);
24 |
25 | /**
26 | * @dev Emitted when the pause is lifted by `account`.
27 | */
28 | event Unpaused(address account);
29 |
30 | // this is the only diff with OZ contract
31 | // bool private _paused;
32 |
33 | /**
34 | * @dev Initializes the contract in unpaused state.
35 | */
36 | constructor() {
37 | _paused = false;
38 | }
39 |
40 | /**
41 | * @dev Returns true if the contract is paused, and false otherwise.
42 | */
43 | function paused() public view virtual returns (bool) {
44 | return _paused;
45 | }
46 |
47 | /**
48 | * @dev Modifier to make a function callable only when the contract is not paused.
49 | *
50 | * Requirements:
51 | *
52 | * - The contract must not be paused.
53 | */
54 | modifier whenNotPaused() {
55 | require(!paused(), 'Pausable: paused');
56 | _;
57 | }
58 |
59 | /**
60 | * @dev Modifier to make a function callable only when the contract is paused.
61 | *
62 | * Requirements:
63 | *
64 | * - The contract must be paused.
65 | */
66 | modifier whenPaused() {
67 | require(paused(), 'Pausable: not paused');
68 | _;
69 | }
70 |
71 | /**
72 | * @dev Triggers stopped state.
73 | *
74 | * Requirements:
75 | *
76 | * - The contract must not be paused.
77 | */
78 | function _pause() internal virtual whenNotPaused {
79 | _paused = true;
80 | emit Paused(_msgSender());
81 | }
82 |
83 | /**
84 | * @dev Returns to normal state.
85 | *
86 | * Requirements:
87 | *
88 | * - The contract must be paused.
89 | */
90 | function _unpause() internal virtual whenPaused {
91 | _paused = false;
92 | emit Unpaused(_msgSender());
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/contracts/core/libs/utils/Bitmap256Bit.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | /*
5 | * The 256-bit bitmap is structured in 64 chuncks of 4 bits each.
6 | * The 4 bits can encode any value from 0 to 15.
7 |
8 | chunck63 chunck2 chunck1 chunck0
9 | bits bits bits bits
10 | ┌────────────┐ ┌────────────┬────────────┬────────────┐
11 | │ 1 1 1 1 │ .... │ 1 0 1 1 │ 0 0 0 0 │ 0 0 0 1 │
12 | └────────────┘ └────────────┴────────────┴────────────┘
13 | value 15 value 11 value 0 value 1
14 |
15 | * A chunck index must be between 0 and 63.
16 | * A value must be between 0 and 15.
17 | **/
18 |
19 | library Bitmap256Bit {
20 | uint256 constant MAX_INT = 2 ** 256 - 1;
21 |
22 | error IndexOutOfBounds(uint8 index);
23 | error ValueOutOfBounds(uint8 value);
24 |
25 | /**
26 | * @dev Return the value at a given index of a 256-bit bitmap
27 | * @param index index where the value can be found. Can be between 0 and 63
28 | */
29 | function _get(uint256 self, uint8 index) internal pure returns (uint8) {
30 | uint256 currentValues = self;
31 | // Get the encoded 4-bit value by right shifting to the `index` position
32 | uint256 shifted = currentValues >> (4 * index);
33 | // Get the value by only masking the last 4 bits with an AND operator
34 | return uint8(shifted & (2 ** 4 - 1));
35 | }
36 |
37 | /**
38 | * @dev Set a value at a chosen index in a 256-bit bitmap
39 | * @param index index where the value will be stored. Can be between 0 and 63
40 | * @param value value to store. Can be between 0 and 15
41 | */
42 | function _set(uint256 self, uint8 index, uint8 value) internal pure returns (uint256) {
43 | _checkIndexIsValid(index);
44 | _checkValueIsValid(value);
45 |
46 | uint256 currentValues = self;
47 | // 1. first we need to remove the current value for the inputed `index`
48 | // Left Shift 4 bits mask (1111 mask) to the `index` position
49 | uint256 mask = (2 ** 4 - 1) << (4 * index);
50 | // Apply a XOR operation to obtain a mask with all bits set to 1 except the 4 bits that we want to remove
51 | uint256 negativeMask = MAX_INT ^ mask;
52 | // Apply a AND operation between the current values and the negative mask to remove the wanted bits
53 | uint256 newValues = currentValues & negativeMask;
54 |
55 | // 2. We set the new value wanted at the `index` position
56 | // Create the 4 bits encoding the new value and left shift them to the `index` position
57 | uint256 newValueMask = uint256(value) << (4 * index);
58 | // Apply an OR operation between the current values and the newValueMask to reference new value
59 | return newValues | newValueMask;
60 | }
61 |
62 | /**
63 | * @dev Get all the non-zero values in a 256-bit bitmap
64 | * @param self a 256-bit bitmap
65 | */
66 | function _getAllNonZeroValues(
67 | uint256 self
68 | ) internal pure returns (uint8[] memory, uint8[] memory, uint8) {
69 | uint8[] memory indices = new uint8[](64);
70 | uint8[] memory values = new uint8[](64);
71 | uint8 nbOfNonZeroValues = 0;
72 | for (uint8 i = 0; i < 63; i++) {
73 | uint8 value = _get(self, i);
74 | if (value > 0) {
75 | indices[nbOfNonZeroValues] = i;
76 | values[nbOfNonZeroValues] = value;
77 | nbOfNonZeroValues++;
78 | }
79 | }
80 | return (indices, values, nbOfNonZeroValues);
81 | }
82 |
83 | /**
84 | * @dev Check if the index is valid (is between 0 and 63)
85 | * @param index index of a chunck
86 | */
87 | function _checkIndexIsValid(uint8 index) internal pure {
88 | if (index > 63) {
89 | revert IndexOutOfBounds(index);
90 | }
91 | }
92 |
93 | /**
94 | * @dev Check if the value is valid (is between 0 and 15)
95 | * @param value value to encode in a chunck
96 | */
97 | function _checkValueIsValid(uint8 value) internal pure {
98 | if (value > 15) {
99 | revert ValueOutOfBounds(value);
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/contracts/core/libs/utils/Context.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
3 |
4 | pragma solidity ^0.8.14;
5 |
6 | /**
7 | * @dev Provides information about the current execution context, including the
8 | * sender of the transaction and its data. While these are generally available
9 | * via msg.sender and msg.data, they should not be accessed in such a direct
10 | * manner, since when dealing with meta-transactions the account sending and
11 | * paying for execution may not be the actual sender (as far as an application
12 | * is concerned).
13 | *
14 | * This contract is only required for intermediate, library-like contracts.
15 | */
16 | abstract contract Context {
17 | function _msgSender() internal view virtual returns (address) {
18 | return msg.sender;
19 | }
20 |
21 | function _msgData() internal view virtual returns (bytes calldata) {
22 | return msg.data;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/contracts/core/libs/utils/RangeLib.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | struct Range {
5 | uint256 min;
6 | uint256 max;
7 | }
8 |
9 | // Range [0;3] includees 0 and 3
10 | library RangeUtils {
11 | function _includes(Range[] storage ranges, uint256 collectionId) internal view returns (bool) {
12 | for (uint256 i = 0; i < ranges.length; i++) {
13 | if (collectionId >= ranges[i].min && collectionId <= ranges[i].max) {
14 | return true;
15 | }
16 | }
17 | return false;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/contracts/core/utils/interfaces/IAddressesProvider.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | interface IAddressesProvider {
5 | /**
6 | * @dev Sets the address of a contract.
7 | * @param contractAddress Address of the contract.
8 | * @param contractName Name of the contract.
9 | */
10 | function set(address contractAddress, string memory contractName) external;
11 |
12 | /**
13 | * @dev Sets the address of multiple contracts.
14 | * @param contractAddresses Addresses of the contracts.
15 | * @param contractNames Names of the contracts.
16 | */
17 | function setBatch(address[] calldata contractAddresses, string[] calldata contractNames) external;
18 |
19 | /**
20 | * @dev Returns the address of a contract.
21 | * @param contractName Name of the contract (string).
22 | * @return Address of the contract.
23 | */
24 | function get(string memory contractName) external view returns (address);
25 |
26 | /**
27 | * @dev Returns the address of a contract.
28 | * @param contractNameHash Hash of the name of the contract (bytes32).
29 | * @return Address of the contract.
30 | */
31 | function get(bytes32 contractNameHash) external view returns (address);
32 |
33 | /**
34 | * @dev Returns the addresses of all contracts inputed.
35 | * @param contractNames Names of the contracts as strings.
36 | */
37 | function getBatch(string[] calldata contractNames) external view returns (address[] memory);
38 |
39 | /**
40 | * @dev Returns the addresses of all contracts inputed.
41 | * @param contractNamesHash Names of the contracts as strings.
42 | */
43 | function getBatch(bytes32[] calldata contractNamesHash) external view returns (address[] memory);
44 |
45 | /**
46 | * @dev Returns the addresses of all contracts in `_contractNames`
47 | * @return Names, Hashed Names and Addresses of all contracts.
48 | */
49 | function getAll() external view returns (string[] memory, bytes32[] memory, address[] memory);
50 | }
51 |
--------------------------------------------------------------------------------
/contracts/libs/SismoLib.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | /**
5 | * @title SismoLib
6 | * @author Sismo
7 | * @notice This is the Sismo Library of the Sismo protocol
8 | * It is designed to be the only contract that needs to be imported to integrate Sismo in a smart contract.
9 | * Its aim is to provide a set of sub-libraries with high-level functions to interact with the Sismo protocol easily.
10 | */
11 |
12 | import './using-sismo/UsingSismo.sol';
13 |
--------------------------------------------------------------------------------
/contracts/periphery/utils/AvailableRootsRegistry.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
5 | import {IAvailableRootsRegistry} from './interfaces/IAvailableRootsRegistry.sol';
6 | import {Initializable} from '@openzeppelin/contracts/proxy/utils/Initializable.sol';
7 |
8 | /**
9 | * @title Attesters Groups Registry
10 | * @author Sismo
11 | * @notice This contract stores that data required by attesters to be available so they can verify user claims
12 | * This contract is deployed behind a proxy and this implementation is focused on storing merkle roots
13 | * For more information: https://available-roots-registry.docs.sismo.io
14 | *
15 | **/
16 | contract AvailableRootsRegistry is IAvailableRootsRegistry, Initializable, Ownable {
17 | uint8 public constant IMPLEMENTATION_VERSION = 2;
18 |
19 | mapping(address => mapping(uint256 => bool)) public _roots;
20 |
21 | /**
22 | * @dev Constructor
23 | * @param owner Owner of the contract, can register/ unregister roots
24 | */
25 | constructor(address owner) {
26 | initialize(owner);
27 | }
28 |
29 | /**
30 | * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
31 | * @param ownerAddress Owner of the contract, can update public key and address
32 | * @notice The reinitializer modifier is needed to configure modules that are added through upgrades and that require initialization.
33 | */
34 | function initialize(address ownerAddress) public reinitializer(IMPLEMENTATION_VERSION) {
35 | // if proxy did not setup owner yet or if called by constructor (for implem setup)
36 | if (owner() == address(0) || address(this).code.length == 0) {
37 | _transferOwnership(ownerAddress);
38 | }
39 | }
40 |
41 | /**
42 | * @dev Register a root available for an attester
43 | * @param attester Attester which will have the root available
44 | * @param root Root to register
45 | */
46 | function registerRootForAttester(address attester, uint256 root) external onlyOwner {
47 | if (attester == address(0)) revert CannotRegisterForZeroAddress();
48 | _registerRootForAttester(attester, root);
49 | }
50 |
51 | /**
52 | * @dev Unregister a root for an attester
53 | * @param attester Attester which will no longer have the root available
54 | * @param root Root to unregister
55 | */
56 | function unregisterRootForAttester(address attester, uint256 root) external onlyOwner {
57 | if (attester == address(0)) revert CannotUnregisterForZeroAddress();
58 | _unregisterRootForAttester(attester, root);
59 | }
60 |
61 | /**
62 | * @dev Registers a root, available for all contracts
63 | * @param root Root to register
64 | */
65 | function registerRootForAll(uint256 root) external onlyOwner {
66 | _registerRootForAttester(address(0), root);
67 | }
68 |
69 | /**
70 | * @dev Unregister a root, available for all contracts
71 | * @param root Root to unregister
72 | */
73 | function unregisterRootForAll(uint256 root) external onlyOwner {
74 | _unregisterRootForAttester(address(0), root);
75 | }
76 |
77 | /**
78 | * @dev returns whether a root is available for a caller (msg.sender)
79 | * @param root root to check whether it is registered for me or not
80 | */
81 | function isRootAvailableForMe(uint256 root) external view returns (bool) {
82 | return _roots[_msgSender()][root] || _roots[address(0)][root];
83 | }
84 |
85 | /**
86 | * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
87 | * @param attester Owner of the contract, can update public key and address
88 | * @param root Owner of the contract, can update public key and address
89 | */
90 | function isRootAvailableForAttester(address attester, uint256 root) external view returns (bool) {
91 | return _roots[attester][root] || _roots[address(0)][root];
92 | }
93 |
94 | function _registerRootForAttester(address attester, uint256 root) internal {
95 | _roots[attester][root] = true;
96 | if (attester == address(0)) {
97 | emit RegisteredRootForAll(root);
98 | } else {
99 | emit RegisteredRootForAttester(attester, root);
100 | }
101 | }
102 |
103 | function _unregisterRootForAttester(address attester, uint256 root) internal {
104 | _roots[attester][root] = false;
105 | if (attester == address(0)) {
106 | emit UnregisteredRootForAll(root);
107 | } else {
108 | emit UnregisteredRootForAttester(attester, root);
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/contracts/periphery/utils/CommitmentMapperRegistry.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
5 | import {Initializable} from '@openzeppelin/contracts/proxy/utils/Initializable.sol';
6 | import {ICommitmentMapperRegistry} from './interfaces/ICommitmentMapperRegistry.sol';
7 |
8 | /**
9 | * @title Commitment Mapper Registry Contract
10 | * @author Sismo
11 | * @notice This contract stores information about the commitment mapper.
12 | * Its ethereum address and its EdDSA public key
13 | * For more information: https://commitment-mapper.docs.sismo.io
14 | *
15 | **/
16 | contract CommitmentMapperRegistry is ICommitmentMapperRegistry, Initializable, Ownable {
17 | uint8 public constant IMPLEMENTATION_VERSION = 2;
18 |
19 | uint256[2] internal _commitmentMapperPubKey;
20 | address _commitmentMapperAddress;
21 |
22 | /**
23 | * @dev Constructor
24 | * @param owner Owner of the contract, can update public key and address
25 | * @param commitmentMapperEdDSAPubKey EdDSA public key of the commitment mapper
26 | * @param commitmentMapperAddress Address of the commitment mapper
27 | */
28 | constructor(
29 | address owner,
30 | uint256[2] memory commitmentMapperEdDSAPubKey,
31 | address commitmentMapperAddress
32 | ) {
33 | initialize(owner, commitmentMapperEdDSAPubKey, commitmentMapperAddress);
34 | }
35 |
36 | /**
37 | * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
38 | * @param ownerAddress Owner of the contract, can update public key and address
39 | * @param commitmentMapperEdDSAPubKey EdDSA public key of the commitment mapper
40 | * @param commitmentMapperAddress Address of the commitment mapper
41 | * @notice The reinitializer modifier is needed to configure modules that are added through upgrades and that require initialization.
42 | */
43 | function initialize(
44 | address ownerAddress,
45 | uint256[2] memory commitmentMapperEdDSAPubKey,
46 | address commitmentMapperAddress
47 | ) public reinitializer(IMPLEMENTATION_VERSION) {
48 | // if proxy did not setup owner yet or if called by constructor (for implem setup)
49 | if (owner() == address(0) || address(this).code.length == 0) {
50 | _transferOwnership(ownerAddress);
51 | _updateCommitmentMapperEdDSAPubKey(commitmentMapperEdDSAPubKey);
52 | _updateCommitmentMapperAddress(commitmentMapperAddress);
53 | }
54 | }
55 |
56 | /**
57 | * @dev Updates the EdDSA public key
58 | * @param newEdDSAPubKey new EdDSA pubic key
59 | */
60 | function updateCommitmentMapperEdDSAPubKey(uint256[2] memory newEdDSAPubKey) external onlyOwner {
61 | _updateCommitmentMapperEdDSAPubKey(newEdDSAPubKey);
62 | }
63 |
64 | /**
65 | * @dev Updates the address
66 | * @param newAddress new address
67 | */
68 | function updateCommitmentMapperAddress(address newAddress) external onlyOwner {
69 | _updateCommitmentMapperAddress(newAddress);
70 | }
71 |
72 | /**
73 | * @dev Getter of the EdDSA public key of the commitment mapper
74 | */
75 | function getEdDSAPubKey() external view override returns (uint256[2] memory) {
76 | return _commitmentMapperPubKey;
77 | }
78 |
79 | /**
80 | * @dev Getter of the address of the commitment mapper
81 | */
82 | function getAddress() external view override returns (address) {
83 | return _commitmentMapperAddress;
84 | }
85 |
86 | function _updateCommitmentMapperAddress(address newAddress) internal {
87 | _commitmentMapperAddress = newAddress;
88 | emit UpdatedCommitmentMapperAddress(newAddress);
89 | }
90 |
91 | function _updateCommitmentMapperEdDSAPubKey(uint256[2] memory pubKey) internal {
92 | _commitmentMapperPubKey = pubKey;
93 | emit UpdatedCommitmentMapperEdDSAPubKey(pubKey);
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/contracts/periphery/utils/FrontendLib.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
5 | import {HydraS1AccountboundAttester} from '../../attesters/hydra-s1/HydraS1AccountboundAttester.sol';
6 | import {Initializable} from '@openzeppelin/contracts/proxy/utils/Initializable.sol';
7 |
8 | contract FrontendLib {
9 | address private immutable _hydraS1AccountboundAttester;
10 |
11 | constructor(address hydraS1AccountboundAttester) {
12 | _hydraS1AccountboundAttester = hydraS1AccountboundAttester;
13 | }
14 |
15 | function getHydraS1AccountboundAttesterDestinationOfNullifierBatch(
16 | uint256[] calldata nullifiers
17 | ) external view returns (address[] memory) {
18 | address[] memory destinations = new address[](nullifiers.length);
19 |
20 | for (uint256 i = 0; i < nullifiers.length; i++) {
21 | destinations[i] = HydraS1AccountboundAttester(_hydraS1AccountboundAttester)
22 | .getDestinationOfNullifier(nullifiers[i]);
23 | }
24 |
25 | return destinations;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/contracts/periphery/utils/interfaces/IAvailableRootsRegistry.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.8.14;
4 |
5 | /**
6 | * @title IAvailableRootsRegistry
7 | * @author Sismo
8 | * @notice Interface for (Merkle) Roots Registry
9 | */
10 | interface IAvailableRootsRegistry {
11 | event RegisteredRootForAttester(address attester, uint256 root);
12 | event RegisteredRootForAll(uint256 root);
13 | event UnregisteredRootForAttester(address attester, uint256 root);
14 | event UnregisteredRootForAll(uint256 root);
15 |
16 | error CannotRegisterForZeroAddress();
17 | error CannotUnregisterForZeroAddress();
18 |
19 | /**
20 | * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
21 | * @param owner Owner of the contract, can update public key and address
22 | * @notice The reinitializer modifier is needed to configure modules that are added through upgrades and that require initialization.
23 | */
24 | function initialize(address owner) external;
25 |
26 | /**
27 | * @dev Register a root available for an attester
28 | * @param attester Attester which will have the root available
29 | * @param root Root to register
30 | */
31 | function registerRootForAttester(address attester, uint256 root) external;
32 |
33 | /**
34 | * @dev Unregister a root for an attester
35 | * @param attester Attester which will no longer have the root available
36 | * @param root Root to unregister
37 | */
38 | function unregisterRootForAttester(address attester, uint256 root) external;
39 |
40 | /**
41 | * @dev Registers a root, available for all contracts
42 | * @param root Root to register
43 | */
44 | function registerRootForAll(uint256 root) external;
45 |
46 | /**
47 | * @dev Unregister a root, available for all contracts
48 | * @param root Root to unregister
49 | */
50 | function unregisterRootForAll(uint256 root) external;
51 |
52 | /**
53 | * @dev returns whether a root is available for a caller (msg.sender)
54 | * @param root root to check whether it is registered for me or not
55 | */
56 | function isRootAvailableForMe(uint256 root) external view returns (bool);
57 |
58 | /**
59 | * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
60 | * @param attester Owner of the contract, can update public key and address
61 | * @param root Owner of the contract, can update public key and address
62 | */
63 | function isRootAvailableForAttester(address attester, uint256 root) external view returns (bool);
64 | }
65 |
--------------------------------------------------------------------------------
/contracts/periphery/utils/interfaces/ICommitmentMapperRegistry.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | interface ICommitmentMapperRegistry {
5 | event UpdatedCommitmentMapperEdDSAPubKey(uint256[2] newEdDSAPubKey);
6 | event UpdatedCommitmentMapperAddress(address newAddress);
7 | error PubKeyNotValid(uint256[2] pubKey);
8 |
9 | /**
10 | * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
11 | * @param owner Owner of the contract, can update public key and address
12 | * @param commitmentMapperEdDSAPubKey EdDSA public key of the commitment mapper
13 | * @param commitmentMapperAddress Address of the commitment mapper
14 | * @notice The reinitializer modifier is needed to configure modules that are added through upgrades and that require initialization.
15 | */
16 | function initialize(
17 | address owner,
18 | uint256[2] memory commitmentMapperEdDSAPubKey,
19 | address commitmentMapperAddress
20 | ) external;
21 |
22 | /**
23 | * @dev Updates the EdDSA public key
24 | * @param newEdDSAPubKey new EdDSA pubic key
25 | */
26 | function updateCommitmentMapperEdDSAPubKey(uint256[2] memory newEdDSAPubKey) external;
27 |
28 | /**
29 | * @dev Updates the address
30 | * @param newAddress new address
31 | */
32 | function updateCommitmentMapperAddress(address newAddress) external;
33 |
34 | /**
35 | * @dev Getter of the address of the commitment mapper
36 | */
37 | function getEdDSAPubKey() external view returns (uint256[2] memory);
38 |
39 | /**
40 | * @dev Getter of the address of the commitment mapper
41 | */
42 | function getAddress() external view returns (address);
43 | }
44 |
--------------------------------------------------------------------------------
/contracts/tests/MockHydraS1SimpleAttester.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.8.14;
4 |
5 | import {Attestation, Request} from '../core/libs/Structs.sol';
6 | import {Attester} from '../core/Attester.sol';
7 | import {IAttester} from '../core/interfaces/IAttester.sol';
8 | import {IHydraS1AccountboundAttester} from '../attesters/hydra-s1/interfaces/IHydraS1AccountboundAttester.sol';
9 |
10 | contract MockHydraS1SimpleAttester {
11 | mapping(uint256 => address) internal _nullifiersDestinations;
12 |
13 | function getDestinationOfNullifier(uint256 nullifier) external view returns (address) {
14 | return _nullifiersDestinations[nullifier];
15 | }
16 |
17 | function setDestinationOfNullifier(uint256 nullifier, address destination) external {
18 | _nullifiersDestinations[nullifier] = destination;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/contracts/tests/mocks/MockAttestationsRegistry.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 | import {IAttestationsRegistry} from '../../core/interfaces/IAttestationsRegistry.sol';
4 | import {AttestationsRegistryConfigLogic} from '../../core/libs/attestations-registry/AttestationsRegistryConfigLogic.sol';
5 | import {AttestationsRegistryState} from '../../core/libs/attestations-registry/AttestationsRegistryState.sol';
6 | import {IBadges} from '../../core/interfaces/IBadges.sol';
7 | import {Attestation, AttestationData} from '../../core/libs/Structs.sol';
8 |
9 | contract MockAttestationsRegistry {
10 | uint256 immutable ATTESTATION_VALUE;
11 |
12 | event AttestationRecorded(Attestation attestation);
13 |
14 | constructor(uint256 attestationValue) {
15 | ATTESTATION_VALUE = attestationValue;
16 | }
17 |
18 | function getAttestationValue(
19 | uint256 collectionId,
20 | address owner
21 | ) external view returns (uint256) {
22 | return ATTESTATION_VALUE;
23 | }
24 |
25 | function recordAttestations(Attestation[] calldata attestations) external {
26 | for (uint256 i = 0; i < attestations.length; i++) {
27 | emit AttestationRecorded(attestations[i]);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/contracts/tests/mocks/MockAttester.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.8.14;
4 |
5 | import {Attestation, Request} from '../../core/libs/Structs.sol';
6 | import {Attester} from '../../core/Attester.sol';
7 | import {IAttester} from '../../core/interfaces/IAttester.sol';
8 |
9 | contract MockAttester is IAttester, Attester {
10 | uint256 public immutable ATTESTATION_ID_MIN;
11 | uint256 public immutable ATTESTATION_ID_MAX;
12 |
13 | constructor(
14 | address ATTESTATION_REGISTRY_ADDRESS,
15 | uint256 collectionIdFirst,
16 | uint256 collectionIdLast
17 | ) Attester(ATTESTATION_REGISTRY_ADDRESS) {
18 | ATTESTATION_ID_MIN = collectionIdFirst;
19 | ATTESTATION_ID_MAX = collectionIdLast;
20 | }
21 |
22 | function _verifyRequest(
23 | Request calldata request,
24 | bytes calldata proofData
25 | ) internal virtual override {}
26 |
27 | function buildAttestations(
28 | Request calldata request,
29 | bytes calldata /*data*/
30 | ) public view virtual override(Attester, IAttester) returns (Attestation[] memory) {
31 | uint256 collectionId = ATTESTATION_ID_MIN + request.claims[0].groupId;
32 | Attestation[] memory attestations = new Attestation[](1);
33 | attestations[0] = Attestation(
34 | collectionId,
35 | request.destination,
36 | address(this),
37 | request.claims[0].claimedValue,
38 | abi.decode(request.claims[0].extraData, (uint32)),
39 | 'Mock Attester v0'
40 | );
41 | return (attestations);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/contracts/tests/mocks/mockContractUsingSismoLib.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.14;
3 |
4 | import {UsingSismo, Request} from '../../libs/SismoLib.sol';
5 |
6 | contract MockContractUsingSismoLib is UsingSismo {
7 | uint256 public constant FIRST_GATED_BADGE_ID = 200002;
8 | uint256 public constant SECOND_GATED_BADGE_ID = 200003;
9 |
10 | mapping(address => uint256) public balances;
11 |
12 | /*******************************************************
13 | 1. MINT BADGES from sismoProof received by "Prove With Sismo" off-chain flow
14 | *******************************************************/
15 |
16 | function testMintSismoBadgeWithAttester(
17 | Request memory request,
18 | bytes memory proofData,
19 | address attester
20 | ) external {
21 | _mintSismoBadge(request, proofData, attester);
22 | }
23 |
24 | function testMintSismoBadge(Request memory request, bytes memory proofData) external {
25 | _mintSismoBadge(request, proofData);
26 | }
27 |
28 | function testMintSismoBadgesWithAttester(
29 | Request memory request,
30 | bytes memory proofData,
31 | address attester
32 | ) external {
33 | _mintSismoBadges(request, proofData, attester);
34 | }
35 |
36 | function testMintSismoBadges(Request memory request, bytes memory proofData) external {
37 | _mintSismoBadges(request, proofData);
38 | }
39 |
40 | /*******************************************************
41 | 2. MODIFIERS
42 | *******************************************************/
43 |
44 | function testOnlyBadgeHoldersModifier() external onlyBadgeHolders(FIRST_GATED_BADGE_ID) {
45 | _inc(_msgSender());
46 | }
47 |
48 | function testOnlyBadgesHoldersWithAllBadgesRequiredModifier(
49 | uint256[] memory gatedBadge
50 | ) external onlyBadgesHolders(gatedBadge, true) {
51 | _inc(_msgSender());
52 | }
53 |
54 | function testOnlyBadgesHoldersWithOnlyOneBadgeRequiredModifier(
55 | uint256[] memory gatedBadge
56 | ) external onlyBadgesHolders(gatedBadge, false) {
57 | _inc(_msgSender());
58 | }
59 |
60 | function testOnlyBadgeHoldersWithGreaterBalanceModifier()
61 | external
62 | onlyBadgeHoldersWithGreaterBalance(FIRST_GATED_BADGE_ID, 2)
63 | {
64 | _inc(_msgSender());
65 | }
66 |
67 | function testOnlyBadgeHoldersWithLowerBalanceModifier()
68 | external
69 | onlyBadgeHoldersWithLowerBalance(FIRST_GATED_BADGE_ID, 2)
70 | {
71 | _inc(_msgSender());
72 | }
73 |
74 | function testOnlyBadgeHoldersWithExactBalanceModifier()
75 | external
76 | onlyBadgeHoldersWithExactBalance(FIRST_GATED_BADGE_ID, 1)
77 | {
78 | _inc(_msgSender());
79 | }
80 |
81 | function testOnlyBadgesHoldersWithGreaterBalanceAndAllBadgesRequiredModifier(
82 | uint256[] memory badgeTokenIds,
83 | uint256[] memory minBalances
84 | ) external onlyBadgesHoldersWithGreaterBalance(badgeTokenIds, minBalances, true) {
85 | _inc(_msgSender());
86 | }
87 |
88 | function testOnlyBadgesHoldersWithGreaterBalanceAndOnlyOneBadgeRequiredModifier(
89 | uint256[] memory badgeTokenIds,
90 | uint256[] memory minBalances
91 | ) external onlyBadgesHoldersWithGreaterBalance(badgeTokenIds, minBalances, false) {
92 | _inc(_msgSender());
93 | }
94 |
95 | function testOnlyBadgesHoldersWithLowerBalanceAndAllBadgesRequiredModifier(
96 | uint256[] memory badgeTokenIds,
97 | uint256[] memory maxBalances
98 | ) external onlyBadgesHoldersWithLowerBalance(badgeTokenIds, maxBalances, true) {
99 | _inc(_msgSender());
100 | }
101 |
102 | function testOnlyBadgesHoldersWithLowerBalanceAndOnlyOneBadgeRequiredModifier(
103 | uint256[] memory badgeTokenIds,
104 | uint256[] memory maxBalances
105 | ) external onlyBadgesHoldersWithLowerBalance(badgeTokenIds, maxBalances, false) {
106 | _inc(_msgSender());
107 | }
108 |
109 | function testOnlyBadgesHoldersWithExactBalanceAndAllBadgesRequiredModifier(
110 | uint256[] memory badgeTokenIds,
111 | uint256[] memory exactBalances
112 | ) external onlyBadgesHoldersWithExactBalance(badgeTokenIds, exactBalances, true) {
113 | _inc(_msgSender());
114 | }
115 |
116 | function testOnlyBadgesHoldersWithExactBalanceAndOnlyOneBadgeRequiredModifier(
117 | uint256[] memory badgeTokenIds,
118 | uint256[] memory exactBalances
119 | ) external onlyBadgesHoldersWithExactBalance(badgeTokenIds, exactBalances, false) {
120 | _inc(_msgSender());
121 | }
122 |
123 | function _inc(address account) internal {
124 | balances[account]++;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/deployments/gnosis/.chainId:
--------------------------------------------------------------------------------
1 | 100
--------------------------------------------------------------------------------
/deployments/goerliStaging/.chainId:
--------------------------------------------------------------------------------
1 | 5
--------------------------------------------------------------------------------
/deployments/goerliTestnet/.chainId:
--------------------------------------------------------------------------------
1 | 5
--------------------------------------------------------------------------------
/deployments/local/.chainId:
--------------------------------------------------------------------------------
1 | 31337
--------------------------------------------------------------------------------
/deployments/mainnet/.chainId:
--------------------------------------------------------------------------------
1 | 1
--------------------------------------------------------------------------------
/deployments/mumbaiStaging/.chainId:
--------------------------------------------------------------------------------
1 | 80001
--------------------------------------------------------------------------------
/deployments/mumbaiTestnet/.chainId:
--------------------------------------------------------------------------------
1 | 80001
--------------------------------------------------------------------------------
/deployments/polygon/.chainId:
--------------------------------------------------------------------------------
1 | 137
--------------------------------------------------------------------------------
/deployments/polygonPlayground/.chainId:
--------------------------------------------------------------------------------
1 | 137
--------------------------------------------------------------------------------
/deployments/rinkeby/.chainId:
--------------------------------------------------------------------------------
1 | 4
--------------------------------------------------------------------------------
/docs/schema1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismo-core/sismo-badges/09206e396ca2342a88f7eaa897d55783f019f759/docs/schema1.png
--------------------------------------------------------------------------------
/docs/top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sismo-core/sismo-badges/09206e396ca2342a88f7eaa897d55783f019f759/docs/top.png
--------------------------------------------------------------------------------
/helper-hardhat-config.ts:
--------------------------------------------------------------------------------
1 | import dotenv from 'dotenv';
2 | dotenv.config({});
3 |
4 | export type Network = EthereumNetwork | PolygonNetwork | GnosisNetwork;
5 |
6 | export enum EthereumNetwork {
7 | kovan = 'kovan',
8 | goerli = 'goerli',
9 | rinkeby = 'rinkeby',
10 | mainnet = 'mainnet',
11 | hardhat = 'hardhat',
12 | tenderlyMain = 'tenderlyMain',
13 | harhatevm = 'harhatevm',
14 | }
15 |
16 | export enum PolygonNetwork {
17 | main = 'polygon-mainnet',
18 | mumbai = 'mumbai',
19 | }
20 |
21 | export enum GnosisNetwork {
22 | gnosis = 'gnosis',
23 | }
24 |
25 | export type ParamsPerNetwork =
26 | | EthereumParamsPerNetwork
27 | | PolygonParamsPerNetwork
28 | | XDaiParamsPerNetwork;
29 |
30 | export interface EthereumParamsPerNetwork {
31 | [EthereumNetwork.harhatevm]: Network;
32 | [EthereumNetwork.rinkeby]: Network;
33 | [EthereumNetwork.mainnet]: Network;
34 | [EthereumNetwork.hardhat]: Network;
35 | [EthereumNetwork.tenderlyMain]: Network;
36 | [EthereumNetwork.goerli]: Network;
37 | }
38 |
39 | export interface PolygonParamsPerNetwork {
40 | [PolygonNetwork.main]: T;
41 | [PolygonNetwork.mumbai]: T;
42 | }
43 |
44 | export interface XDaiParamsPerNetwork {
45 | [GnosisNetwork.gnosis]: T;
46 | }
47 |
48 | export interface ObjectString {
49 | [key: string]: string;
50 | }
51 | export const alchemyUrlOrEnvVar = (defaultAlchemyUrl: string, rpcUrl?: string): string => {
52 | const defaultUrl = `${defaultAlchemyUrl}/${process.env.ALCHEMY_KEY}`;
53 | return rpcUrl ? rpcUrl : defaultUrl;
54 | };
55 |
56 | export const NETWORKS_RPC_URL: ParamsPerNetwork = {
57 | [EthereumNetwork.rinkeby]: alchemyUrlOrEnvVar(
58 | 'https://eth-rinkeby.alchemyapi.io/v2',
59 | process.env.RINKEBY_RPC_URL
60 | ),
61 | [EthereumNetwork.mainnet]: alchemyUrlOrEnvVar(
62 | 'https://eth-mainnet.alchemyapi.io/v2',
63 | process.env.MAINNET_RPC_URL
64 | ),
65 | [EthereumNetwork.goerli]: alchemyUrlOrEnvVar(
66 | 'https://eth-goerli.g.alchemy.com/v2',
67 | process.env.MAINNET_RPC_URL
68 | ),
69 | [EthereumNetwork.hardhat]: 'http://localhost:8545',
70 | [PolygonNetwork.mumbai]: alchemyUrlOrEnvVar(
71 | 'https://polygon-mumbai.g.alchemy.com/v2',
72 | process.env.MUMBAI_RPC_URL
73 | ),
74 | [PolygonNetwork.main]: alchemyUrlOrEnvVar(
75 | 'https://polygon-mainnet.g.alchemy.com/v2',
76 | process.env.POLYGON_RPC_URL
77 | ),
78 | [GnosisNetwork.gnosis]: 'https://rpc.gnosischain.com',
79 | };
80 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sismo-protocol",
3 | "version": "1.0.0",
4 | "description": "Sismo attestations repo",
5 | "main": "index.js",
6 | "repository": "git@github.com:sismo-core/sismo-protocol.git",
7 | "author": "leosayous21.sismo.eth ",
8 | "license": "MIT",
9 | "scripts": {
10 | "compile": "SKIP_LOAD=true hardhat compile",
11 | "test": "hardhat test",
12 | "prettier": "prettier --write 'contracts/**/*.sol'",
13 | "chain": "hardhat node",
14 | "storage-layout": "hardhat print-storage-layout",
15 | "deploy:local": "rm -rf deployments/local && hardhat deploy-full-local --network local"
16 | },
17 | "devDependencies": {
18 | "@nomiclabs/hardhat-etherscan": "^3.0.1",
19 | "@nomiclabs/hardhat-waffle": "^2.0.2",
20 | "@typechain/hardhat": "^4.0.0",
21 | "@types/chai": "^4.3.0",
22 | "@types/jest": "^27.4.0",
23 | "@types/mocha": "^9.1.0",
24 | "chai": "^4.3.6",
25 | "concurrently": "^7.2.0",
26 | "dotenv": "^16.0.0",
27 | "prettier": "^2.5.1",
28 | "prettier-plugin-solidity": "^1.0.0-beta.19",
29 | "solhint": "^3.3.7",
30 | "solidity-coverage": "^0.7.19",
31 | "tslib": "^2.4.0"
32 | },
33 | "husky": {
34 | "hooks": {
35 | "pre-commit": "pretty-quick --staged --pattern 'test/**/*.ts' --pattern 'tasks/**/*.ts' --pattern 'contracts/**/*.sol'"
36 | }
37 | },
38 | "dependencies": {
39 | "@metamask/eth-sig-util": "^4.0.0",
40 | "@nomiclabs/hardhat-ethers": "^2.2.1",
41 | "@openzeppelin/contracts": "^4.5.0",
42 | "@openzeppelin/contracts-upgradeable": "^4.8.0",
43 | "@sismo-core/commitment-mapper-tester-js": "^1.0.11",
44 | "@sismo-core/hydra-s1": "^1.0.6",
45 | "@sismo-core/pythia-1": "^1.0.6",
46 | "@trufflesuite/eth-sig-util": "^1.4.2",
47 | "@typechain/ethers-v5": "^9.0.0",
48 | "@typescript-eslint/eslint-plugin": "^5.22.0",
49 | "@typescript-eslint/parser": "^5.22.0",
50 | "defender-relay-client": "^1.21.3",
51 | "eslint": "^8.14.0",
52 | "ethereum-waffle": "^3.4.0",
53 | "ethers": "^5.6.8",
54 | "fast-glob": "^3.2.11",
55 | "hardhat": "^2.9.7",
56 | "hardhat-deploy": "^0.11.22",
57 | "hardhat-gas-reporter": "^1.0.7",
58 | "hardhat-storage-layout": "^0.1.6",
59 | "husky": "4.2.5",
60 | "hydra-s1-previous": "npm:@sismo-core/hydra-s1@v1.0.5",
61 | "js-sha3": "^0.8.0",
62 | "mocha": "^10.0.0",
63 | "pretty-quick": "^3.1.3",
64 | "ts-node": "^10.5.0",
65 | "typechain": "^7.0.0",
66 | "typescript": "^4.5.5",
67 | "web3": "^1.7.1"
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/scripts/wait-for-local-chain.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | HOSTNAME=${LOCAL_HOSTNAME:-'localhost'}
5 | PORT=${LOCAL_PORT:-8545}
6 | while ! nc -z $HOSTNAME $PORT; do
7 | echo "Waiting for chain to be up ..."
8 | sleep 2
9 | done
10 |
11 | >&2 echo "Chain is up - executing command"
12 | exec "$@"
13 |
--------------------------------------------------------------------------------
/tasks/addresses-provider/set-batch.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { AddressesProvider__factory } from '../../types';
4 | import { CommonTaskOptions, wrapCommonOptions } from '../utils';
5 | import { confirm } from '../utils/confirm';
6 | import { deploymentsConfig } from '../../tasks/deploy-tasks/deployments-config';
7 |
8 | export type SetBatchArgs = {
9 | contractAddressesAsString: string;
10 | contractNamesAsString: string;
11 | options?: CommonTaskOptions;
12 | };
13 |
14 | async function action(
15 | { contractAddressesAsString, contractNamesAsString, options }: SetBatchArgs,
16 | hre: HardhatRuntimeEnvironment
17 | ): Promise {
18 | const [signer] = await hre.ethers.getSigners();
19 |
20 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
21 |
22 | const contractAddresses = contractAddressesAsString.split(',');
23 | const contractNames = contractNamesAsString.split(',');
24 |
25 | const sismoAddressesProvider = AddressesProvider__factory.connect(
26 | config.sismoAddressesProvider.address,
27 | signer
28 | );
29 |
30 | if (process.env.SET_BATCH_MANUAL_OPERATION === 'true') {
31 | console.log(`
32 | ************************************
33 | * SET BATCH *
34 | ************************************`);
35 |
36 | if (options?.manualConfirm) {
37 | await confirm();
38 | }
39 |
40 | // we can't connect as signer, we need manual operation
41 | const iface = new hre.ethers.utils.Interface(AddressesProvider__factory.abi);
42 | const data = iface.encodeFunctionData('setBatch', [contractAddresses, contractNames]);
43 |
44 | console.log({
45 | from: await sismoAddressesProvider.owner(),
46 | to: sismoAddressesProvider.address,
47 | data: data,
48 | });
49 |
50 | console.log('Send the transaction using etherscan !');
51 | } else {
52 | console.log(`
53 | Aborting setBatch...`);
54 | }
55 | }
56 |
57 | task('set-batch')
58 | .addParam('contractAddressesAsString', 'Addresses of the contracts we want to set')
59 | .addParam('contractNamesAsString', 'Names of the contracts we want to set')
60 | .setAction(wrapCommonOptions(action));
61 |
--------------------------------------------------------------------------------
/tasks/available-roots-registry/register-for-attester.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { getDeployer } from '../deploy-tasks/utils';
4 |
5 | import { AvailableRootsRegistry__factory } from '../../types';
6 | import { manualConfirmValidity } from '../utils/confirm';
7 | import { BigNumber, Signer } from 'ethers';
8 | import { CommonTaskOptions, wrapCommonOptions } from '../utils';
9 | import { getRelayerSigner } from '../utils/relayer';
10 |
11 | export type RegisterForAttesterArgs = {
12 | root: string;
13 | attester: string;
14 | availableRootsRegistryAddress?: string;
15 | relayed?: boolean;
16 | options?: CommonTaskOptions;
17 | };
18 |
19 | async function action(
20 | { root, attester, relayed, options, availableRootsRegistryAddress }: RegisterForAttesterArgs,
21 | hre: HardhatRuntimeEnvironment
22 | ): Promise {
23 | if (root === '0') {
24 | if (options?.log) {
25 | console.log(`
26 | root undefined for attester ${attester}. Not running the task.
27 | `);
28 | }
29 | return;
30 | }
31 |
32 | const signer = relayed ? await getRelayerSigner() : ((await getDeployer(hre)) as Signer);
33 |
34 | const availableRootsRegistry = AvailableRootsRegistry__factory.connect(
35 | availableRootsRegistryAddress || (await hre.deployments.get(`AvailableRootsRegistry`)).address,
36 | signer
37 | );
38 |
39 | const isRootAlreadyRegistered = await availableRootsRegistry.isRootAvailableForAttester(
40 | attester,
41 | BigNumber.from(root)
42 | );
43 | if (isRootAlreadyRegistered) {
44 | if (options?.log) {
45 | console.log(`
46 | Root: ${root} already registered for attester ${availableRootsRegistry.address}`);
47 | }
48 | return;
49 | }
50 |
51 | const actionRegisterRootForAttesterArgs = {
52 | availableRootsRegistry: availableRootsRegistry.address,
53 | root: root,
54 | attester,
55 | };
56 | await manualConfirmValidity(actionRegisterRootForAttesterArgs, options);
57 | const tx = await availableRootsRegistry.registerRootForAttester(
58 | actionRegisterRootForAttesterArgs.attester,
59 | BigNumber.from(actionRegisterRootForAttesterArgs.root)
60 | );
61 | await tx.wait();
62 | }
63 |
64 | task('register-for-attester')
65 | .addParam('root', 'Root to update')
66 | .addParam('attester', 'Register for this Attester')
67 | .addOptionalParam('availableRootsRegistryAddress', 'Root to update')
68 | .addFlag('relayed', 'to use with relayer')
69 | .setAction(wrapCommonOptions(action));
70 |
--------------------------------------------------------------------------------
/tasks/available-roots-registry/unregister-for-attester.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { getDeployer } from '../deploy-tasks/utils';
4 |
5 | import { AvailableRootsRegistry__factory } from '../../types';
6 | import { manualConfirmValidity } from '../utils/confirm';
7 | import { BigNumber, Signer } from 'ethers';
8 | import { CommonTaskOptions, wrapCommonOptions } from '../utils';
9 | import { getRelayerSigner } from '../utils/relayer';
10 |
11 | export type UnregisterForAttesterArgs = {
12 | root: string;
13 | attester: string;
14 | availableRootsRegistryAddress?: string;
15 | relayed?: boolean;
16 | options?: CommonTaskOptions;
17 | };
18 |
19 | async function action(
20 | { root, attester, relayed, options, availableRootsRegistryAddress }: UnregisterForAttesterArgs,
21 | hre: HardhatRuntimeEnvironment
22 | ): Promise {
23 | if (root === '0') {
24 | if (options?.log) {
25 | console.log(`
26 | root undefined for attester ${attester}. Not running the task.
27 | `);
28 | }
29 | return;
30 | }
31 |
32 | const signer = relayed ? await getRelayerSigner() : ((await getDeployer(hre)) as Signer);
33 |
34 | const availableRootsRegistry = AvailableRootsRegistry__factory.connect(
35 | availableRootsRegistryAddress || (await hre.deployments.get(`AvailableRootsRegistry`)).address,
36 | signer
37 | );
38 |
39 | const isRootAlreadyRegistered = await availableRootsRegistry.isRootAvailableForAttester(
40 | attester,
41 | BigNumber.from(root)
42 | );
43 | if (!isRootAlreadyRegistered) {
44 | if (options?.log) {
45 | console.log(`
46 | Root: ${root} already unregistered for attester ${availableRootsRegistry.address}`);
47 | }
48 | return;
49 | }
50 |
51 | const actionUnregisterRootForAttesterArgs = {
52 | availableRootsRegistry: availableRootsRegistry.address,
53 | root: root,
54 | attester,
55 | };
56 | await manualConfirmValidity(actionUnregisterRootForAttesterArgs, options);
57 | const tx = await availableRootsRegistry.unregisterRootForAttester(
58 | actionUnregisterRootForAttesterArgs.attester,
59 | BigNumber.from(actionUnregisterRootForAttesterArgs.root)
60 | );
61 | await tx.wait();
62 | }
63 |
64 | task('unregister-for-attester')
65 | .addParam('root', 'Root to update')
66 | .addParam('attester', 'Register for this Attester')
67 | .addOptionalParam('availableRootsRegistryAddress', 'Root to update')
68 | .addFlag('relayed', 'to use with relayer')
69 | .setAction(wrapCommonOptions(action));
70 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/batch/deploy-core.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { AttestationsRegistry, Badges, Front } from '../../../types';
4 | import {
5 | DeployedAttestationsRegistry,
6 | DeployAttestationsRegistryArgs,
7 | } from '../unit/core/deploy-attestations-registry.task';
8 | import { DeployBadgesArgs, DeployedBadges } from '../unit/core/deploy-badges.task';
9 | import { DeployOptions, wrapCommonDeployOptions } from '../utils';
10 | import { DeployedFront, DeployFrontArgs } from '../unit/core/deploy-front.task';
11 | import { AuthorizeRangeArgs } from 'tasks/helpers/authorizations/attestations-registry-authorize-range.task';
12 | import { AccessControlGrantRoleArgs } from 'tasks/helpers/authorizations/access-control-grant-role.task';
13 |
14 | export interface DeployedCore {
15 | attestationsRegistry: AttestationsRegistry;
16 | badges: Badges;
17 | front: Front;
18 | }
19 |
20 | export interface DeployCoreArgs {
21 | uri?: string;
22 | registryOwner?: string;
23 | badgeOwner?: string;
24 | frontFirstCollectionId: string;
25 | frontLastCollectionId: string;
26 | options?: DeployOptions;
27 | }
28 |
29 | async function deploymentAction(
30 | {
31 | uri,
32 | registryOwner,
33 | badgeOwner,
34 | frontFirstCollectionId,
35 | frontLastCollectionId,
36 | options,
37 | }: DeployCoreArgs,
38 | hre: HardhatRuntimeEnvironment
39 | ): Promise {
40 | if (options?.log) console.log('Deploying Core Contracts');
41 |
42 | // Deployed ERC1155 Default Badge
43 | const { badges } = (await hre.run('deploy-badges', {
44 | uri,
45 | owner: badgeOwner,
46 | options,
47 | } as DeployBadgesArgs)) as DeployedBadges;
48 |
49 | // Deploy main contract Attestation Registry
50 | const { attestationsRegistry } = (await hre.run('deploy-attestations-registry', {
51 | owner: registryOwner,
52 | badges: badges.address,
53 | options,
54 | } as DeployAttestationsRegistryArgs)) as DeployedAttestationsRegistry;
55 |
56 | const registeredAttestationsRegistryInBadges = await badges.getAttestationsRegistry();
57 | if (registeredAttestationsRegistryInBadges != attestationsRegistry.address) {
58 | await (await badges.setAttestationsRegistry(attestationsRegistry.address)).wait();
59 | }
60 |
61 | const { front } = (await hre.run('deploy-front', {
62 | attestationsRegistryAddress: attestationsRegistry.address,
63 | badges: badges.address,
64 | options,
65 | } as DeployFrontArgs)) as DeployedFront;
66 |
67 | await hre.run('attestations-registry-authorize-range', {
68 | attestationsRegistryAddress: attestationsRegistry.address,
69 | attesterAddress: front.address,
70 | collectionIdFirst: frontFirstCollectionId,
71 | collectionIdLast: frontLastCollectionId,
72 | options,
73 | } as AuthorizeRangeArgs);
74 |
75 | await hre.run('access-control-grant-role', {
76 | contractAddress: badges.address,
77 | role: await badges.EVENT_TRIGGERER_ROLE(),
78 | accountAddress: attestationsRegistry.address,
79 | options,
80 | } as AccessControlGrantRoleArgs);
81 |
82 | if (options?.log) {
83 | console.log(`
84 | Deployed core contracts of the sismo protocol:
85 | attestationsRegistry: ${attestationsRegistry.address}
86 | badges: ${badges.address}
87 | front: ${front.address}
88 | `);
89 | }
90 | return { attestationsRegistry, badges, front };
91 | }
92 |
93 | task('deploy-core')
94 | .addOptionalParam('uri', 'uri for the badges')
95 | .addOptionalParam('registryOwner', 'owner of the contracts')
96 | .addOptionalParam('badgeOwner', 'owner of the contracts')
97 | .addOptionalParam('frontFirstCollectionId', 'owner of the contracts')
98 | .addOptionalParam('frontLastCollectionId', 'owner of the contracts')
99 | .setAction(wrapCommonDeployOptions(deploymentAction));
100 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/full/1-deploy-pythia-1-simple.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { DeployOptions, getDeployer } from '../utils';
4 | import { deploymentsConfig } from '../deployments-config';
5 | import { getCommonOptions } from '../../utils/common-options';
6 | import { AuthorizeRangeArgs } from '../../helpers/authorizations/attestations-registry-authorize-range.task';
7 | import { Pythia1SimpleAttester } from 'types';
8 | import {
9 | DeployedPythia1SimpleAttester,
10 | DeployPythia1SimpleAttesterArgs,
11 | } from 'tasks/deploy-tasks/unit/attesters/pythia-1/deploy-pythia-1-simple-attester.task';
12 | import { Pythia1Verifier } from '@sismo-core/pythia-1';
13 |
14 | export interface Deployed1 {
15 | pythia1SimpleAttester: Pythia1SimpleAttester;
16 | pythia1Verifier: Pythia1Verifier;
17 | }
18 |
19 | async function deploymentAction(
20 | { options }: { options: DeployOptions },
21 | hre: HardhatRuntimeEnvironment
22 | ): Promise {
23 | const deployer = await getDeployer(hre);
24 | const config = deploymentsConfig[hre.network.name];
25 | options = { ...config.deployOptions, ...options };
26 | if (options.manualConfirm || options.log) {
27 | console.log('1-deploy-pythia-1-simple: ', hre.network.name);
28 | }
29 |
30 | const attestationsRegistry = await hre.deployments.get('AttestationsRegistry');
31 | // Only deploy contracts without giving final ownership.
32 | // Owners of the different contract are the deployer
33 | const pythia1SimpleAttesterArgs: DeployPythia1SimpleAttesterArgs = {
34 | collectionIdFirst: config.synapsPythia1SimpleAttester.collectionIdFirst,
35 | collectionIdLast: config.synapsPythia1SimpleAttester.collectionIdLast,
36 | attestationsRegistryAddress: attestationsRegistry.address,
37 | commitmentSignerPubKeyX: config.synapsPythia1SimpleAttester.commitmentSignerPubKeyX,
38 | commitmentSignerPubKeyY: config.synapsPythia1SimpleAttester.commitmentSignerPubKeyY,
39 | owner: config.synapsPythia1SimpleAttester.owner,
40 | options,
41 | };
42 |
43 | const { pythia1SimpleAttester, pythia1Verifier } = (await hre.run(
44 | 'deploy-pythia-1-simple-attester',
45 | pythia1SimpleAttesterArgs
46 | )) as DeployedPythia1SimpleAttester;
47 |
48 | // Give to the attester the authorization to write on the attestations Registry
49 | if (options.manualConfirm || options.log) {
50 | console.log(`
51 | ----------------------------------------------------------------
52 | * Authorize Pythia1SimpleAttester to record on the AttestationsRegistry`);
53 | }
54 | await hre.run('attestations-registry-authorize-range', {
55 | attestationsRegistryAddress: attestationsRegistry.address,
56 | attesterAddress: pythia1SimpleAttester.address,
57 | collectionIdFirst: config.synapsPythia1SimpleAttester.collectionIdFirst,
58 | collectionIdLast: config.synapsPythia1SimpleAttester.collectionIdLast,
59 | options: getCommonOptions(options),
60 | } as AuthorizeRangeArgs);
61 |
62 | if (options.manualConfirm || options.log) {
63 | console.log(`
64 | ************************************************************
65 | * RECAP *
66 | ************************************************************
67 |
68 | date: ${new Date().toISOString()}
69 |
70 | ** Common **
71 | proxyAdmin: ${config.deployOptions.proxyAdmin}
72 |
73 | * Pythia1SimpleAttester:
74 | -> proxy: ${(await hre.deployments.all()).Pythia1SimpleAttester.address}
75 | -> implem: ${(await hre.deployments.all()).Pythia1SimpleAttesterImplem.address}
76 | collectionIdFirst: ${config.synapsPythia1SimpleAttester.collectionIdFirst}
77 | collectionIdLast: ${config.synapsPythia1SimpleAttester.collectionIdLast}
78 | commitmentSignerPubKeyX: ${config.synapsPythia1SimpleAttester.commitmentSignerPubKeyX}
79 | commitmentSignerPubKeyY: ${config.synapsPythia1SimpleAttester.commitmentSignerPubKeyY}
80 |
81 | * Pythia1Verifier:
82 | -> address: ${(await hre.deployments.all()).Pythia1Verifier.address}
83 | `);
84 | }
85 |
86 | return {
87 | pythia1SimpleAttester,
88 | pythia1Verifier,
89 | };
90 | }
91 |
92 | task('1-deploy-pythia-1-simple').setAction(deploymentAction);
93 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/full/3-new-hydra-s1-verifier-and-upgrade-hydra-s1-simple-proxy.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { DeployOptions, getDeployer } from '../utils';
4 | import { HydraS1AccountboundAttester, HydraS1Verifier } from 'types';
5 | import { DeployedHydraS1AccountboundAttester } from 'tasks/deploy-tasks/unit/attesters/hydra-s1/deploy-hydra-s1-accountbound-attester.task';
6 | import { deploymentsConfig } from '../deployments-config';
7 |
8 | export interface Deployed3 {
9 | hydraS1Verifier: HydraS1Verifier;
10 | hydraS1AccountboundAttester: HydraS1AccountboundAttester;
11 | }
12 |
13 | async function deploymentAction(
14 | { options }: { options: DeployOptions },
15 | hre: HardhatRuntimeEnvironment
16 | ): Promise {
17 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
18 | options = { ...config.deployOptions, ...options };
19 |
20 | if (options.manualConfirm || options.log) {
21 | console.log('3-new-hydra-s1-verifier-and-upgrade-accountbound-proxy: ', hre.network.name);
22 | }
23 |
24 | // The following proxies will be updated:
25 | // - HydraS1Verifier => rename ticket in nullifier
26 | // - HydraS1SimpleAttester implementation will be replaced by the HydraS1AccountboundAttester implementation => cooldown duration removed from groupProperties + inherits from HydraS1SimpleAttester
27 | // => + reinitializer modifier added and version as constant
28 |
29 | // Upgrade HydraS1Verifier
30 | const { hydraS1Verifier: newHydraS1Verifier } = await hre.run('deploy-hydra-s1-verifier', {
31 | options,
32 | });
33 |
34 | // Upgrade proxy implementation from HydraS1SimpleAttester to HydraS1AccountboundAttester
35 | const { hydraS1AccountboundAttester: newHydraS1AccountboundAttester } = (await hre.run(
36 | 'deploy-hydra-s1-accountbound-attester',
37 | {
38 | // the collectionIds referenced are the ones used by the previous HydraS1SimpleAttester
39 | collectionIdFirst: config.hydraS1AccountboundAttester.collectionIdFirst,
40 | collectionIdLast: config.hydraS1AccountboundAttester.collectionIdLast,
41 | commitmentMapperRegistryAddress: config.commitmentMapper.address,
42 | availableRootsRegistryAddress: config.availableRootsRegistry.address,
43 | attestationsRegistryAddress: config.attestationsRegistry.address,
44 | hydraS1VerifierAddress: newHydraS1Verifier.address, // reference the new hydraS1Verifier address
45 | owner: config.hydraS1AccountboundAttester.owner, // set the owner referenced in the config
46 | options: {
47 | ...options,
48 | isImplementationUpgrade: true,
49 | proxyAddress: config.hydraS1AccountboundAttester.address, // the address referenced here is the old address of the hydraS1SimpleAttester
50 | },
51 | }
52 | )) as DeployedHydraS1AccountboundAttester;
53 |
54 | return {
55 | hydraS1Verifier: newHydraS1Verifier,
56 | hydraS1AccountboundAttester: newHydraS1AccountboundAttester,
57 | };
58 | }
59 |
60 | task('3-new-hydra-s1-verifier-and-upgrade-hydra-s1-simple-proxy').setAction(deploymentAction);
61 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/full/4-upgrade-attestations-registry-proxy-and-badges-proxy.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { DeployOptions, getDeployer } from '../utils';
4 | import { AttestationsRegistry, Badges } from 'types';
5 | import { DeployedAttestationsRegistry } from 'tasks/deploy-tasks/unit/core/deploy-attestations-registry.task';
6 | import { deploymentsConfig } from '../deployments-config';
7 | import { DeployedBadges } from 'tasks/deploy-tasks/unit/core/deploy-badges.task';
8 |
9 | export interface Deployed4 {
10 | attestationsRegistry: AttestationsRegistry;
11 | badges: Badges;
12 | }
13 |
14 | async function deploymentAction(
15 | { options }: { options: DeployOptions },
16 | hre: HardhatRuntimeEnvironment
17 | ): Promise {
18 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
19 | options = { ...config.deployOptions, ...options };
20 |
21 | if (options.manualConfirm || options.log) {
22 | console.log('4-upgrade-attestations-registry-proxy: ', hre.network.name);
23 | }
24 |
25 | // The following proxy will be updated:
26 | // - AttestationRegistry => introduce attributes names and values for attestationsCollection
27 | // values go from 0 to 15, if the value is 0 the attribute is disabled, else it is enabled with the value set
28 | // + reinitializer modifier added and version as constant
29 | // - Badges => add getters for attestations issuer, timestamp and extradata
30 | // => add getters for attribute values and names
31 | // => + reinitializer modifier added and version as constant
32 |
33 | // Upgrade attestations registry
34 | const { attestationsRegistry: newAttestationsRegistry } = (await hre.run(
35 | 'deploy-attestations-registry',
36 | {
37 | badges: config.badges.address,
38 | owner: config.attestationsRegistry.owner,
39 | options: {
40 | ...options,
41 | isImplementationUpgrade: true, // implementation version has been bumped from v2 to v3
42 | proxyAddress: config.attestationsRegistry.address,
43 | },
44 | }
45 | )) as DeployedAttestationsRegistry;
46 |
47 | // Upgrade Badges
48 | const { badges: newBadges } = (await hre.run('deploy-badges', {
49 | uri: config.badges.uri,
50 | owner: config.badges.owner,
51 | options: {
52 | ...options,
53 | isImplementationUpgrade: true, // implementation version has been bumped from v2 to v3
54 | proxyAddress: config.badges.address,
55 | },
56 | })) as DeployedBadges;
57 |
58 | return {
59 | attestationsRegistry: newAttestationsRegistry,
60 | badges: newBadges,
61 | };
62 | }
63 |
64 | task('4-upgrade-attestations-registry-proxy-and-badges-proxy').setAction(deploymentAction);
65 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/full/5-upgrade-proxies-with-reinitializer.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { DeployOptions, getDeployer } from '../utils';
4 | import {
5 | AvailableRootsRegistry,
6 | Badges,
7 | CommitmentMapperRegistry,
8 | Pythia1SimpleAttester,
9 | } from 'types';
10 | import { deploymentsConfig } from '../deployments-config';
11 | import { DeployedPythia1SimpleAttester } from 'tasks/deploy-tasks/unit/attesters/pythia-1/deploy-pythia-1-simple-attester.task';
12 | import { DeployedAvailableRootsRegistry } from 'tasks/deploy-tasks/unit/periphery/deploy-available-roots-registry.task';
13 | import { DeployedCommitmentMapper } from 'tasks/deploy-tasks/unit/periphery/deploy-commitment-mapper-registry.task';
14 |
15 | export interface Deployed5 {
16 | pythia1SimpleAttester: Pythia1SimpleAttester;
17 | availableRootsRegistry: AvailableRootsRegistry;
18 | commitmentMapperRegistry: CommitmentMapperRegistry;
19 | }
20 |
21 | async function deploymentAction(
22 | { options }: { options: DeployOptions },
23 | hre: HardhatRuntimeEnvironment
24 | ): Promise {
25 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
26 | options = { ...config.deployOptions, ...options };
27 |
28 | if (options.manualConfirm || options.log) {
29 | console.log('4-upgrade-attestations-registry-proxy: ', hre.network.name);
30 | }
31 |
32 | // The following proxies will be updated:
33 | // - Pythia1SimpleAttester => reinitializer modifier added and version as constant
34 | // - AvailableRootsRegistry => reinitializer modifier added and version as constant
35 | // - CommitmentMapperRegistry => reinitializer modifier added and version as constant
36 |
37 | // Upgrade pythia1SimpleAttester
38 | const { pythia1SimpleAttester: newPythia1SimpleAttester } = (await hre.run(
39 | 'deploy-pythia-1-simple-attester',
40 | {
41 | collectionIdFirst: config.synapsPythia1SimpleAttester.collectionIdFirst,
42 | collectionIdLast: config.synapsPythia1SimpleAttester.collectionIdLast,
43 | attestationsRegistryAddress: config.attestationsRegistry.address,
44 | commitmentSignerPubKeyX: config.synapsPythia1SimpleAttester.commitmentSignerPubKeyX,
45 | commitmentSignerPubKeyY: config.synapsPythia1SimpleAttester.commitmentSignerPubKeyY,
46 | owner: config.synapsPythia1SimpleAttester.owner,
47 | options: {
48 | ...options,
49 | isImplementationUpgrade: true, // implementation version has been bumped from v2 to v3
50 | proxyAddress: config.synapsPythia1SimpleAttester.address,
51 | },
52 | }
53 | )) as DeployedPythia1SimpleAttester;
54 |
55 | // Upgrade AvailableRootsRegistry
56 | const { availableRootsRegistry: newAvailableRootsRegistry } = (await hre.run(
57 | 'deploy-available-roots-registry',
58 | {
59 | owner: config.availableRootsRegistry.owner,
60 | options: {
61 | ...options,
62 | isImplementationUpgrade: true, // implementation version has been bumped from v1 to v2
63 | proxyAddress: config.availableRootsRegistry.address,
64 | },
65 | }
66 | )) as DeployedAvailableRootsRegistry;
67 |
68 | // Upgrade CommitmentMapperRegistry
69 | const { commitmentMapperRegistry: newCommitmentMapperRegistry } = (await hre.run(
70 | 'deploy-commitment-mapper-registry',
71 | {
72 | commitmentMapperPubKeyX: config.commitmentMapper.EdDSAPubKeyX,
73 | commitmentMapperPubKeyY: config.commitmentMapper.EdDSAPubKeyY,
74 | owner: config.commitmentMapper.owner,
75 | options: {
76 | ...options,
77 | isImplementationUpgrade: true, // implementation version has been bumped from v1 to v2
78 | proxyAddress: config.commitmentMapper.address,
79 | },
80 | }
81 | )) as DeployedCommitmentMapper;
82 |
83 | return {
84 | pythia1SimpleAttester: newPythia1SimpleAttester,
85 | availableRootsRegistry: newAvailableRootsRegistry,
86 | commitmentMapperRegistry: newCommitmentMapperRegistry,
87 | };
88 | }
89 |
90 | task('5-upgrade-proxies-with-reinitializer').setAction(deploymentAction);
91 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/full/6-deploy-sismo-addresses-provider.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { DeployOptions } from '../utils';
4 | import { deploymentsConfig } from '../deployments-config';
5 | import { DeployedSismoAddressesProvider } from 'tasks/deploy-tasks/unit/core/deploy-sismo-addresses-provider.task';
6 | import { AddressesProvider } from 'types';
7 |
8 | export interface Deployed6 {
9 | sismoAddressesProvider: AddressesProvider;
10 | }
11 |
12 | async function deploymentAction(
13 | { options }: { options: DeployOptions },
14 | hre: HardhatRuntimeEnvironment
15 | ): Promise {
16 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
17 | options = { ...config.deployOptions, ...options };
18 |
19 | if (options.manualConfirm || options.log) {
20 | console.log('6-deploy-sismo-addresses-provider: ', hre.network.name);
21 | }
22 |
23 | // Deploy SismoAddressesProvider
24 | const { sismoAddressesProvider } = (await hre.run('deploy-sismo-addresses-provider', {
25 | owner: config.sismoAddressesProvider.owner,
26 | badges: config.badges.address,
27 | attestationsRegistry: config.attestationsRegistry.address,
28 | front: config.front.address,
29 | hydraS1AccountboundAttester: config.hydraS1AccountboundAttester.address,
30 | commitmentMapperRegistry: config.commitmentMapper.address,
31 | availableRootsRegistry: config.availableRootsRegistry.address,
32 | hydraS1Verifier: config.hydraS1Verifier.address,
33 | options: { ...options, proxyAdmin: config.deployOptions.proxyAdmin },
34 | })) as DeployedSismoAddressesProvider;
35 |
36 | return {
37 | sismoAddressesProvider,
38 | };
39 | }
40 |
41 | task('6-deploy-sismo-addresses-provider').setAction(deploymentAction);
42 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/full/7-upgrade-hydra-s1-accountbound-and-pythia-1-proxies.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { DeployOptions } from '../utils';
4 | import { deploymentsConfig } from '../deployments-config';
5 | import { DeployedHydraS1AccountboundAttester } from 'tasks/deploy-tasks/unit/attesters/hydra-s1/deploy-hydra-s1-accountbound-attester.task';
6 | import { DeployedPythia1SimpleAttester } from 'tasks/deploy-tasks/unit/attesters/pythia-1/deploy-pythia-1-simple-attester.task';
7 | import { HydraS1AccountboundAttester, Pythia1SimpleAttester } from 'types';
8 |
9 | export interface Deployed7 {
10 | hydraS1AccountboundAttester: HydraS1AccountboundAttester;
11 | pythia1SimpleAttester: Pythia1SimpleAttester;
12 | }
13 |
14 | async function deploymentAction(
15 | { options }: { options: DeployOptions },
16 | hre: HardhatRuntimeEnvironment
17 | ): Promise {
18 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
19 | options = { ...config.deployOptions, ...options };
20 |
21 | if (options.manualConfirm || options.log) {
22 | console.log('7-upgrade-hydra-s1-accountbound-and-pythia-1-proxies: ', hre.network.name);
23 | }
24 |
25 | // Upgrade HydraS1AccountboundAttester
26 | const { hydraS1AccountboundAttester: newHydraS1AccountboundAttester } = (await hre.run(
27 | 'deploy-hydra-s1-accountbound-attester',
28 | {
29 | // the collectionIds referenced are the ones used by the previous HydraS1SimpleAttester
30 | collectionIdFirst: config.hydraS1AccountboundAttester.collectionIdFirst,
31 | collectionIdLast: config.hydraS1AccountboundAttester.collectionIdLast,
32 | commitmentMapperRegistryAddress: config.commitmentMapper.address,
33 | availableRootsRegistryAddress: config.availableRootsRegistry.address,
34 | attestationsRegistryAddress: config.attestationsRegistry.address,
35 | hydraS1VerifierAddress: config.hydraS1Verifier.address,
36 | owner: config.hydraS1AccountboundAttester.owner,
37 | options: {
38 | ...options,
39 | isImplementationUpgrade: true,
40 | proxyAddress: config.hydraS1AccountboundAttester.address,
41 | },
42 | }
43 | )) as DeployedHydraS1AccountboundAttester;
44 |
45 | // Upgrade Pythia1SimpleAttester
46 | const { pythia1SimpleAttester: newPythia1SimpleAttester } = (await hre.run(
47 | 'deploy-pythia-1-simple-attester',
48 | {
49 | collectionIdFirst: config.synapsPythia1SimpleAttester.collectionIdFirst,
50 | collectionIdLast: config.synapsPythia1SimpleAttester.collectionIdLast,
51 | attestationsRegistryAddress: config.attestationsRegistry.address,
52 | commitmentSignerPubKeyX: config.synapsPythia1SimpleAttester.commitmentSignerPubKeyX,
53 | commitmentSignerPubKeyY: config.synapsPythia1SimpleAttester.commitmentSignerPubKeyY,
54 | pythia1VerifierAddress: config.pythia1Verifier.address,
55 | owner: config.synapsPythia1SimpleAttester.owner,
56 | options: {
57 | ...options,
58 | isImplementationUpgrade: true,
59 | proxyAddress: config.synapsPythia1SimpleAttester.address,
60 | },
61 | }
62 | )) as DeployedPythia1SimpleAttester;
63 |
64 | return {
65 | hydraS1AccountboundAttester: newHydraS1AccountboundAttester,
66 | pythia1SimpleAttester: newPythia1SimpleAttester,
67 | };
68 | }
69 |
70 | task('7-upgrade-hydra-s1-accountbound-and-pythia-1-proxies').setAction(deploymentAction);
71 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/full/9-upgrade-addresses-provider-on-testnets.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | afterDeployment,
5 | beforeDeployment,
6 | buildDeploymentName,
7 | customDeployContract,
8 | DeployOptions,
9 | getDeployer,
10 | } from '../utils';
11 | import { deploymentsConfig } from '../deployments-config';
12 | import {
13 | AddressesProvider,
14 | AddressesProvider__factory,
15 | TransparentUpgradeableProxy__factory,
16 | } from '../../../types';
17 | import { confirm } from '../../../tasks/utils';
18 |
19 | export interface Deployed9 {
20 | sismoAddressesProvider: AddressesProvider;
21 | }
22 |
23 | async function deploymentAction(
24 | { options }: { options: DeployOptions },
25 | hre: HardhatRuntimeEnvironment
26 | ): Promise {
27 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
28 |
29 | // we need to use the proxyAdmins of staging since we deployed addressesProvider create2 on staging
30 | let badNetwork: string;
31 | let deploymentNetwork = process.env.FORK_NETWORK ?? hre.network.name;
32 | if (deploymentNetwork === 'goerliTestnet') {
33 | badNetwork = 'goerliStaging';
34 | } else if (deploymentNetwork === 'mumbaiTestnet') {
35 | badNetwork = 'mumbaiStaging';
36 | } else {
37 | throw new Error('Invalid network');
38 | }
39 |
40 | options = {
41 | isImplementationUpgrade: true,
42 | proxyAddress: config.sismoAddressesProvider.address,
43 | ...config.deployOptions,
44 | ...options,
45 | };
46 |
47 | if (options.manualConfirm || options.log) {
48 | console.log('9-upgrade-addresses-provider-on-testnets: ', hre.network.name);
49 | }
50 | const CONTRACT_NAME = 'AddressesProvider';
51 |
52 | // Deploy SismoAddressesProvider
53 | const deployer = await getDeployer(hre);
54 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
55 |
56 | const proxyAdmin = deploymentsConfig[badNetwork].deployOptions.proxyAdmin; // we need to use the proxyAdmins of staging since we deployed addressesProvider create2 on staging
57 |
58 | const deploymentArgs = [
59 | config.badges.address,
60 | config.attestationsRegistry.address,
61 | config.front.address,
62 | config.hydraS1AccountboundAttester.address,
63 | config.availableRootsRegistry.address,
64 | config.commitmentMapper.address,
65 | config.hydraS1Verifier.address,
66 | config.sismoAddressesProvider.owner,
67 | ];
68 |
69 | const initData = new AddressesProvider__factory().interface.encodeFunctionData('initialize', [
70 | config.sismoAddressesProvider.owner,
71 | ]);
72 |
73 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
74 | const deployed = await customDeployContract(
75 | hre,
76 | deployer,
77 | deploymentName,
78 | CONTRACT_NAME,
79 | deploymentArgs,
80 | {
81 | ...options,
82 | proxyData: initData,
83 | isImplementationUpgrade: true, // implementation version has been bumped from v1 to v2
84 | proxyAddress: config.sismoAddressesProvider.address,
85 | proxyAdmin,
86 | }
87 | );
88 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
89 |
90 | const sismoAddressesProvider = AddressesProvider__factory.connect(
91 | deployed.address,
92 | await hre.ethers.getSigner(deploymentsConfig[badNetwork].sismoAddressesProvider.owner as string)
93 | );
94 |
95 | return {
96 | sismoAddressesProvider,
97 | };
98 | }
99 |
100 | task('9-upgrade-addresses-provider-on-testnets').setAction(deploymentAction);
101 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/full/staging/deploy-sismo-addresses-provider-staging.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | afterDeployment,
5 | beforeDeployment,
6 | buildDeploymentName,
7 | customDeployContract,
8 | DeployOptions,
9 | getDeployer,
10 | } from '../../utils';
11 | import { deploymentsConfig } from '../../deployments-config';
12 | import { AddressesProvider__factory } from '../../../../types';
13 |
14 | const CONTRACT_NAME = 'AddressesProvider';
15 |
16 | async function deploymentAction(
17 | { options }: { options: DeployOptions },
18 | hre: HardhatRuntimeEnvironment
19 | ) {
20 | const config = deploymentsConfig[hre.network.name];
21 | options = { ...config.deployOptions, ...options };
22 |
23 | const deployer = await getDeployer(hre);
24 | const deploymentName = 'AddressesProviderStaging';
25 |
26 | // always start by giving the ownership of the deployer
27 | const deploymentArgs = [
28 | config.badges.address, // badges,
29 | config.attestationsRegistry.address, // attestationsRegistry,
30 | config.front.address, // front,
31 | config.hydraS1AccountboundAttester.address, // hydraS1AccountboundAttester,
32 | config.availableRootsRegistry.address, // availableRootsRegistry,
33 | config.commitmentMapper.address, // commitmentMapperRegistry,
34 | config.hydraS1Verifier.address, // hydraS1Verifier,
35 | config.sismoAddressesProvider.owner, // deployer.address,
36 | ];
37 |
38 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
39 |
40 | const initData = new AddressesProvider__factory().interface.encodeFunctionData('initialize', [
41 | config.sismoAddressesProvider.owner,
42 | ]);
43 |
44 | const deployed = await customDeployContract(
45 | hre,
46 | deployer,
47 | deploymentName,
48 | CONTRACT_NAME,
49 | deploymentArgs,
50 | {
51 | ...options,
52 | proxyData: initData,
53 | }
54 | );
55 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
56 |
57 | if (options.manualConfirm || options.log) {
58 | console.log(`
59 | ************************************************************
60 | * RECAP *
61 | ************************************************************
62 |
63 | date: ${new Date().toISOString()}
64 |
65 | ** Common **
66 | proxyAdmin: ${config.deployOptions.proxyAdmin}
67 |
68 | * AddressesProviderStaging:
69 | -> address: ${(await hre.deployments.all()).AddressesProviderStaging.address}
70 | `);
71 | }
72 | }
73 |
74 | task('deploy-sismo-addresses-provider-staging').setAction(deploymentAction);
75 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/tests/deploy-mock-attestations-registry.task.ts:
--------------------------------------------------------------------------------
1 | import { BigNumberish } from 'ethers';
2 | import { task } from 'hardhat/config';
3 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
4 | import { MockAttestationsRegistry, MockAttestationsRegistry__factory } from '../../../types';
5 | import {
6 | afterDeployment,
7 | beforeDeployment,
8 | buildDeploymentName,
9 | customDeployContract,
10 | DeployOptions,
11 | getDeployer,
12 | wrapCommonDeployOptions,
13 | } from '../utils';
14 |
15 | export interface DeployMockAttestationsRegistryArgs {
16 | attestationValue: BigNumberish;
17 | options?: DeployOptions;
18 | }
19 |
20 | export interface DeployedMockAttestationsRegistry {
21 | mockAttestationsRegistry: MockAttestationsRegistry;
22 | }
23 |
24 | const CONTRACT_NAME = 'MockAttestationsRegistry';
25 |
26 | async function deploymentAction(
27 | { attestationValue, options }: DeployMockAttestationsRegistryArgs,
28 | hre: HardhatRuntimeEnvironment
29 | ) {
30 | const deployer = await getDeployer(hre);
31 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
32 | const deploymentArgs = [attestationValue || 0];
33 |
34 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
35 |
36 | const deployed = await customDeployContract(
37 | hre,
38 | deployer,
39 | deploymentName,
40 | CONTRACT_NAME,
41 | deploymentArgs,
42 | options
43 | );
44 |
45 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
46 | const mockAttestationsRegistry = MockAttestationsRegistry__factory.connect(
47 | deployed.address,
48 | deployer
49 | );
50 | return { mockAttestationsRegistry };
51 | }
52 |
53 | task('deploy-mock-attestations-registry').setAction(wrapCommonDeployOptions(deploymentAction));
54 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/tests/deploy-mock-attester-and-core.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | DeployOptions,
5 | getDeployer,
6 | wrapCommonDeployOptions,
7 | } from '../../../tasks/deploy-tasks/utils';
8 | import { DeployCoreArgs, DeployedCore } from '../batch/deploy-core.task';
9 | import { DeployedMockAttester, DeployMockAttesterArgs } from './deploy-mock-attester.task';
10 |
11 | export type DeployMockAttesterAndCoreArgs = Omit<
12 | DeployMockAttesterArgs & DeployCoreArgs & DeployOptions,
13 | 'attestationsRegistryAddress' | ''
14 | >;
15 |
16 | export interface DeployedMockAttesterAndCore extends DeployedMockAttester, DeployedCore {}
17 |
18 | async function deploymentAction(
19 | options: DeployMockAttesterAndCoreArgs,
20 | hre: HardhatRuntimeEnvironment
21 | ): Promise {
22 | if (options?.log) {
23 | console.log('Deploying ALL on network: ', hre.network.name);
24 | }
25 |
26 | const deployer = await getDeployer(hre);
27 |
28 | const deployedCore = (await hre.run('deploy-core', {
29 | uri: options.uri,
30 | badgeOwner: options.badgeOwner,
31 | registryOwner: options.registryOwner,
32 | frontFirstCollectionId: options.frontLastCollectionId,
33 | frontLastCollectionId: options.frontLastCollectionId,
34 | options: options.options,
35 | } as DeployCoreArgs)) as DeployedCore;
36 |
37 | const deployedMockAttester = (await hre.run('deploy-mock-attester', {
38 | attestationsRegistryAddress: deployedCore.attestationsRegistry.address,
39 | collectionIdFirst: options.collectionIdFirst,
40 | collectionIdLast: options.collectionIdLast,
41 | options: options.options,
42 | } as DeployMockAttesterArgs)) as DeployedMockAttester;
43 |
44 | // Authorize Mock attester to record attestation on the attestationsRegistry
45 | // for its corresponding min and max
46 | if (options?.log) {
47 | console.log('Authorize Mock on the attestationsRegistry');
48 | }
49 |
50 | await deployedCore.attestationsRegistry
51 | .connect(deployer)
52 | .authorizeRange(
53 | deployedCore.front.address,
54 | await deployedCore.front.EARLY_USER_COLLECTION(),
55 | await deployedCore.front.EARLY_USER_COLLECTION()
56 | );
57 |
58 | await deployedCore.attestationsRegistry
59 | .connect(deployer)
60 | .authorizeRange(
61 | deployedMockAttester.mockAttester.address,
62 | await deployedMockAttester.mockAttester.ATTESTATION_ID_MIN(),
63 | await deployedMockAttester.mockAttester.ATTESTATION_ID_MAX()
64 | );
65 |
66 | return { ...deployedCore, ...deployedMockAttester };
67 | }
68 |
69 | task('deploy-mock-attester-and-core').setAction(wrapCommonDeployOptions(deploymentAction));
70 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/tests/deploy-mock-attester.task.ts:
--------------------------------------------------------------------------------
1 | import { BigNumber, BigNumberish } from 'ethers';
2 | import { task } from 'hardhat/config';
3 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
4 | import {
5 | afterDeployment,
6 | beforeDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | DeployOptions,
10 | getDeployer,
11 | wrapCommonDeployOptions,
12 | } from '../../../tasks/deploy-tasks/utils';
13 | import { MockAttester, MockAttester__factory } from '../../../types';
14 |
15 | export interface DeployMockAttesterArgs {
16 | // address of the attestations Registry contract
17 | attestationsRegistryAddress: string;
18 | collectionIdFirst: BigNumberish;
19 | collectionIdLast: BigNumberish;
20 | options?: DeployOptions;
21 | }
22 |
23 | export interface DeployedMockAttester {
24 | mockAttester: MockAttester;
25 | }
26 |
27 | const CONTRACT_NAME = 'MockAttester';
28 |
29 | async function deploymentAction(
30 | {
31 | attestationsRegistryAddress,
32 | collectionIdFirst,
33 | collectionIdLast,
34 | options,
35 | }: DeployMockAttesterArgs,
36 | hre: HardhatRuntimeEnvironment
37 | ): Promise {
38 | const deployer = await getDeployer(hre);
39 |
40 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
41 |
42 | const deploymentArgs = [
43 | attestationsRegistryAddress,
44 | BigNumber.from(collectionIdFirst),
45 | BigNumber.from(collectionIdLast),
46 | ];
47 |
48 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
49 |
50 | const deployed = await customDeployContract(
51 | hre,
52 | deployer,
53 | deploymentName,
54 | CONTRACT_NAME,
55 | deploymentArgs,
56 | options
57 | );
58 |
59 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
60 | const mockAttester = MockAttester__factory.connect(deployed.address, deployer);
61 | return { mockAttester };
62 | }
63 |
64 | task('deploy-mock-attester')
65 | .addParam('attestationsRegistryAddress', 'Address of the attestations contract')
66 | .addOptionalParam('collectionIdFirst', '')
67 | .addOptionalParam('collectionIdLast', '')
68 | .setAction(wrapCommonDeployOptions(deploymentAction));
69 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/tests/deploy-mock-contract-using-sismo-lib.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | afterDeployment,
5 | beforeDeployment,
6 | buildDeploymentName,
7 | customDeployContract,
8 | DeployOptions,
9 | getDeployer,
10 | wrapCommonDeployOptions,
11 | } from '../../../tasks/deploy-tasks/utils';
12 | import { MockContractUsingSismoLib, MockContractUsingSismoLib__factory } from '../../../types';
13 |
14 | export interface DeployMockContractUsingSismoLibArgs {
15 | options?: DeployOptions;
16 | }
17 |
18 | export interface DeployedMockContractUsingSismoLib {
19 | mockContractUsingSismoLib: MockContractUsingSismoLib;
20 | }
21 |
22 | const CONTRACT_NAME = 'MockContractUsingSismoLib';
23 |
24 | async function deploymentAction(
25 | { options }: DeployMockContractUsingSismoLibArgs,
26 | hre: HardhatRuntimeEnvironment
27 | ): Promise {
28 | const deployer = await getDeployer(hre);
29 |
30 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
31 |
32 | const deploymentArgs = [];
33 |
34 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
35 |
36 | const deployed = await customDeployContract(
37 | hre,
38 | deployer,
39 | deploymentName,
40 | CONTRACT_NAME,
41 | deploymentArgs,
42 | options
43 | );
44 |
45 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
46 | const mockContractUsingSismoLib = MockContractUsingSismoLib__factory.connect(
47 | deployed.address,
48 | deployer
49 | );
50 |
51 | return { mockContractUsingSismoLib };
52 | }
53 |
54 | task('deploy-mock-contract-using-sismo-lib').setAction(wrapCommonDeployOptions(deploymentAction));
55 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/tests/deploy-zk-badgebound-erc721.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { getImplementation } from './../../../utils';
4 | import { ZKBadgeboundERC721, ZKBadgeboundERC721__factory } from '../../../types';
5 | import {
6 | afterDeployment,
7 | beforeDeployment,
8 | customDeployContract,
9 | DeployOptions,
10 | getDeployer,
11 | wrapCommonDeployOptions,
12 | } from '../utils';
13 |
14 | export interface DeployZKBadgeboundERC721Args {
15 | deploymentName?: string;
16 | name: string;
17 | symbol: string;
18 | tokenURI: string;
19 | gatingBadgeTokenId: number;
20 | admin: string;
21 | options?: DeployOptions;
22 | }
23 |
24 | export interface DeployedZkBadgeboundERC721 {
25 | zkBadgeboundERC721: ZKBadgeboundERC721;
26 | }
27 |
28 | const CONTRACT_NAME = 'ZKBadgeboundERC721';
29 |
30 | async function deploymentAction(
31 | {
32 | deploymentName,
33 | name,
34 | symbol,
35 | tokenURI,
36 | gatingBadgeTokenId,
37 | admin,
38 | options,
39 | }: DeployZKBadgeboundERC721Args,
40 | hre: HardhatRuntimeEnvironment
41 | ) {
42 | const deployer = await getDeployer(hre);
43 | const deploymentArgs = [name, symbol, tokenURI, gatingBadgeTokenId, admin];
44 |
45 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
46 |
47 | const initData = new ZKBadgeboundERC721__factory().interface.encodeFunctionData('initialize', [
48 | name,
49 | symbol,
50 | tokenURI,
51 | admin,
52 | ]);
53 |
54 | const deployed = await customDeployContract(
55 | hre,
56 | deployer,
57 | deploymentName ? deploymentName : `${options?.deploymentNamePrefix}_${CONTRACT_NAME}`,
58 | CONTRACT_NAME,
59 | deploymentArgs,
60 | { ...options, proxyData: initData }
61 | );
62 |
63 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
64 | const zkBadgeboundERC721 = ZKBadgeboundERC721__factory.connect(deployed.address, deployer);
65 |
66 | if (options?.manualConfirm || options?.log) {
67 | console.log(`
68 | ************************************************************
69 | * RECAP *
70 | ************************************************************
71 |
72 | date: ${new Date().toISOString()}
73 |
74 | * ZKBadgeboundERC721:
75 | -> proxy: ${zkBadgeboundERC721.address}
76 | -> implem: ${await getImplementation(zkBadgeboundERC721)}
77 | `);
78 | }
79 |
80 | return { zkBadgeboundERC721 };
81 | }
82 |
83 | task('deploy-zk-badgebound-erc721')
84 | .addOptionalParam('deploymentName', 'Name of the deployment')
85 | .addParam('name', 'Name of the token')
86 | .addParam('symbol', 'Symbol of the token')
87 | .addParam('tokenURI', 'Token URI')
88 | .addParam('gatingBadgeTokenId', 'gatingBadgeTokenId')
89 | .setAction(wrapCommonDeployOptions(deploymentAction));
90 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/attesters/hydra-s1/deploy-hydra-s1-accountbound-attester.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | getDeployer,
5 | beforeDeployment,
6 | afterDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | wrapCommonDeployOptions,
10 | DeployOptions,
11 | } from '../../../utils';
12 | import {
13 | HydraS1AccountboundAttester,
14 | HydraS1AccountboundAttester__factory,
15 | HydraS1Verifier,
16 | HydraS1Verifier__factory,
17 | } from '../../../../../types';
18 | import { BigNumber, BigNumberish } from 'ethers';
19 |
20 | export interface DeployHydraS1AccountboundAttesterArgs {
21 | // address of the proving scheme verifier contract
22 | hydraS1VerifierAddress?: string;
23 | // address of the registry MerkleRoot contract
24 | availableRootsRegistryAddress: string;
25 | // address of the commitment mapper registry
26 | commitmentMapperRegistryAddress: string;
27 | // address of the attestations contract,
28 | // which is part of the SAS
29 | // Sismo Attestation State
30 | attestationsRegistryAddress: string;
31 | collectionIdFirst: BigNumberish;
32 | collectionIdLast: BigNumberish;
33 | owner: string;
34 | options?: DeployOptions;
35 | }
36 |
37 | export interface DeployedHydraS1AccountboundAttester {
38 | hydraS1AccountboundAttester: HydraS1AccountboundAttester;
39 | hydraS1Verifier: HydraS1Verifier;
40 | }
41 |
42 | const CONTRACT_NAME = 'HydraS1AccountboundAttester';
43 |
44 | async function deploymentAction(
45 | {
46 | hydraS1VerifierAddress,
47 | availableRootsRegistryAddress,
48 | commitmentMapperRegistryAddress,
49 | attestationsRegistryAddress,
50 | collectionIdFirst,
51 | collectionIdLast,
52 | owner,
53 | options,
54 | }: DeployHydraS1AccountboundAttesterArgs,
55 | hre: HardhatRuntimeEnvironment
56 | ): Promise {
57 | const deployer = await getDeployer(hre);
58 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
59 |
60 | let hydraS1Verifier: HydraS1Verifier;
61 |
62 | if (!hydraS1VerifierAddress) {
63 | ({ hydraS1Verifier } = await hre.run('deploy-hydra-s1-verifier', {
64 | options,
65 | }));
66 | hydraS1VerifierAddress = hydraS1Verifier.address;
67 | } else {
68 | hydraS1Verifier = HydraS1Verifier__factory.connect(hydraS1VerifierAddress, deployer);
69 | }
70 | const deploymentArgs = [
71 | attestationsRegistryAddress,
72 | hydraS1VerifierAddress,
73 | availableRootsRegistryAddress,
74 | commitmentMapperRegistryAddress,
75 | BigNumber.from(collectionIdFirst),
76 | BigNumber.from(collectionIdLast),
77 | owner || deployer.address,
78 | ];
79 |
80 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
81 |
82 | const initData = new HydraS1AccountboundAttester__factory().interface.encodeFunctionData(
83 | 'initialize',
84 | [owner || deployer.address]
85 | );
86 |
87 | const deployed = await customDeployContract(
88 | hre,
89 | deployer,
90 | deploymentName,
91 | CONTRACT_NAME,
92 | deploymentArgs,
93 | {
94 | ...options,
95 | proxyData: initData,
96 | }
97 | );
98 |
99 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
100 |
101 | const hydraS1AccountboundAttester = HydraS1AccountboundAttester__factory.connect(
102 | deployed.address,
103 | deployer
104 | );
105 |
106 | return { hydraS1AccountboundAttester, hydraS1Verifier };
107 | }
108 |
109 | task('deploy-hydra-s1-accountbound-attester')
110 | .addParam('collectionIdFirst', '')
111 | .addParam('collectionIdLast', '')
112 | .addOptionalParam(
113 | 'hydraS1VerifierAddress',
114 | 'address of the proving scheme verifier. Deploy verifier if not defined.'
115 | )
116 | .addParam('availableRootsRegistryAddress', 'address of the registryMerkleRoot contract')
117 | .addParam(
118 | 'commitmentMapperRegistryAddress',
119 | 'address of the commitmentMapperRegistryAddress contract'
120 | )
121 | .addParam('attestationsRegistryAddress', 'Address of the attestations contract')
122 | .setAction(wrapCommonDeployOptions(deploymentAction));
123 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/attesters/hydra-s1/deploy-hydra-s1-simple-attester.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | getDeployer,
5 | beforeDeployment,
6 | afterDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | wrapCommonDeployOptions,
10 | DeployOptions,
11 | } from '../../../../../tasks/deploy-tasks/utils';
12 |
13 | import {
14 | HydraS1SimpleAttester,
15 | HydraS1SimpleAttester__factory,
16 | HydraS1Verifier,
17 | HydraS1Verifier__factory,
18 | } from '../../../../../types';
19 | import { BigNumber, BigNumberish } from 'ethers';
20 |
21 | export interface DeployHydraS1SimpleAttesterArgs {
22 | // mandatory parameter that indicates if we want to deploy the hydra S1 simple attester
23 | enableDeployment: boolean;
24 | // address of the proving scheme verifier contract
25 | hydraS1VerifierAddress?: string;
26 | // address of the registryMerkleRoot contract
27 | availableRootsRegistryAddress: string;
28 | // address of the commitment mapper registry
29 | commitmentMapperRegistryAddress: string;
30 | // address of the attestations contract,
31 | // which is part of the SAS
32 | // Sismo Attestation State
33 | attestationsRegistryAddress: string;
34 | collectionIdFirst: BigNumberish;
35 | collectionIdLast: BigNumberish;
36 | options?: DeployOptions;
37 | }
38 |
39 | export interface DeployedHydraS1SimpleAttester {
40 | hydraS1SimpleAttester?: HydraS1SimpleAttester;
41 | hydraS1Verifier: HydraS1Verifier;
42 | }
43 |
44 | const CONTRACT_NAME = 'HydraS1SimpleAttester';
45 |
46 | async function deploymentAction(
47 | {
48 | enableDeployment,
49 | hydraS1VerifierAddress,
50 | availableRootsRegistryAddress,
51 | commitmentMapperRegistryAddress,
52 | attestationsRegistryAddress,
53 | collectionIdFirst = 100,
54 | collectionIdLast = 0,
55 | options,
56 | }: DeployHydraS1SimpleAttesterArgs,
57 | hre: HardhatRuntimeEnvironment
58 | ): Promise {
59 | const deployer = await getDeployer(hre);
60 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
61 |
62 | let hydraS1Verifier: HydraS1Verifier;
63 |
64 | if (!hydraS1VerifierAddress) {
65 | ({ hydraS1Verifier } = await hre.run('deploy-hydra-s1-verifier', {
66 | options,
67 | }));
68 | hydraS1VerifierAddress = hydraS1Verifier.address;
69 | } else {
70 | hydraS1Verifier = HydraS1Verifier__factory.connect(hydraS1VerifierAddress, deployer);
71 | }
72 |
73 | // if enableDeployment is false, we just return the verifier
74 | if (!enableDeployment) {
75 | return { hydraS1Verifier };
76 | }
77 |
78 | const deploymentArgs = [
79 | attestationsRegistryAddress,
80 | hydraS1VerifierAddress,
81 | availableRootsRegistryAddress,
82 | commitmentMapperRegistryAddress,
83 | BigNumber.from(collectionIdFirst),
84 | BigNumber.from(collectionIdLast),
85 | ];
86 |
87 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
88 |
89 | const initData = '0x';
90 |
91 | const deployed = await customDeployContract(
92 | hre,
93 | deployer,
94 | deploymentName,
95 | CONTRACT_NAME,
96 | deploymentArgs,
97 | {
98 | ...options,
99 | proxyData: initData,
100 | }
101 | );
102 |
103 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
104 |
105 | const hydraS1SimpleAttester = HydraS1SimpleAttester__factory.connect(deployed.address, deployer);
106 | return { hydraS1SimpleAttester, hydraS1Verifier };
107 | }
108 |
109 | task('deploy-hydra-s1-simple-attester')
110 | .addParam('collectionIdFirst', '')
111 | .addParam('collectionIdLast', '')
112 | .addOptionalParam(
113 | 'hydraS1VerifierAddress',
114 | 'address of the proving scheme verifier. Deploy verifier if not defined.'
115 | )
116 | .addParam('availableRootsRegistryAddress', 'address of the registryMerkleRoot contract')
117 | .addParam(
118 | 'commitmentMapperRegistryAddress',
119 | 'address of the commitmentMapperRegistryAddress contract'
120 | )
121 | .addParam('attestationsRegistryAddress', 'Address of the attestations contract')
122 | .setAction(wrapCommonDeployOptions(deploymentAction));
123 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/attesters/hydra-s1/deploy-hydra-s1-verifier.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | getDeployer,
5 | beforeDeployment,
6 | afterDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | wrapCommonDeployOptions,
10 | DeployOptions,
11 | } from '../../../../../tasks/deploy-tasks/utils';
12 | import { HydraS1Verifier, HydraS1Verifier__factory } from '../../../../../types';
13 |
14 | export interface DeployHydraS1Verifier {
15 | options?: DeployOptions;
16 | }
17 |
18 | export interface DeployedHydraS1Verifier {
19 | hydraS1Verifier: HydraS1Verifier;
20 | }
21 |
22 | const CONTRACT_NAME = 'HydraS1Verifier';
23 |
24 | async function deploymentAction(
25 | { options }: DeployHydraS1Verifier,
26 | hre: HardhatRuntimeEnvironment
27 | ): Promise {
28 | const deployer = await getDeployer(hre);
29 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
30 | const deploymentArgs = [];
31 |
32 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
33 |
34 | const deployed = await hre.deployments.deploy(deploymentName, {
35 | contract: CONTRACT_NAME,
36 | from: deployer.address,
37 | args: deploymentArgs,
38 | skipIfAlreadyDeployed: false,
39 | });
40 |
41 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
42 |
43 | const hydraS1Verifier = HydraS1Verifier__factory.connect(deployed.address, deployer);
44 | return { hydraS1Verifier };
45 | }
46 |
47 | task('deploy-hydra-s1-verifier').setAction(wrapCommonDeployOptions(deploymentAction));
48 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/attesters/pythia-1/deploy-pythia-1-simple-attester.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | getDeployer,
5 | beforeDeployment,
6 | afterDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | wrapCommonDeployOptions,
10 | DeployOptions,
11 | } from '../../../utils';
12 |
13 | import {
14 | Pythia1SimpleAttester,
15 | Pythia1SimpleAttester__factory,
16 | Pythia1Verifier,
17 | Pythia1Verifier__factory,
18 | } from '../../../../../types';
19 | import { BigNumber, BigNumberish } from 'ethers';
20 |
21 | export interface DeployPythia1SimpleAttesterArgs {
22 | // address of the proving scheme verifier contract
23 | pythia1VerifierAddress?: string;
24 | // Commitment Signer public key
25 | commitmentSignerPubKeyX?: string;
26 | commitmentSignerPubKeyY?: string;
27 | // address of the owner that can update the commitmentSignerPubKey
28 | owner?: string;
29 | // address of the attestations contract,
30 | // which is part of the Attestation Registry
31 | // Sismo Attestation State
32 | attestationsRegistryAddress: string;
33 | collectionIdFirst: BigNumberish;
34 | collectionIdLast: BigNumberish;
35 | options?: DeployOptions;
36 | }
37 |
38 | export interface DeployedPythia1SimpleAttester {
39 | pythia1SimpleAttester: Pythia1SimpleAttester;
40 | pythia1Verifier: Pythia1Verifier;
41 | }
42 |
43 | const CONTRACT_NAME = 'Pythia1SimpleAttester';
44 |
45 | async function deploymentAction(
46 | {
47 | pythia1VerifierAddress,
48 | attestationsRegistryAddress,
49 | commitmentSignerPubKeyX,
50 | commitmentSignerPubKeyY,
51 | collectionIdFirst = 100,
52 | collectionIdLast = 0,
53 | owner,
54 | options,
55 | }: DeployPythia1SimpleAttesterArgs,
56 | hre: HardhatRuntimeEnvironment
57 | ): Promise {
58 | const deployer = await getDeployer(hre);
59 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
60 |
61 | let pythia1Verifier: Pythia1Verifier;
62 |
63 | if (!pythia1VerifierAddress) {
64 | ({ pythia1Verifier } = await hre.run('deploy-pythia-1-verifier', {
65 | options,
66 | }));
67 | pythia1VerifierAddress = pythia1Verifier.address;
68 | } else {
69 | pythia1Verifier = Pythia1Verifier__factory.connect(pythia1VerifierAddress, deployer);
70 | }
71 |
72 | const deploymentArgs = [
73 | attestationsRegistryAddress,
74 | BigNumber.from(collectionIdFirst),
75 | BigNumber.from(collectionIdLast),
76 | pythia1VerifierAddress,
77 | [commitmentSignerPubKeyX, commitmentSignerPubKeyY],
78 | owner || deployer.address,
79 | ];
80 |
81 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
82 |
83 | const initData = new Pythia1SimpleAttester__factory().interface.encodeFunctionData('initialize', [
84 | [commitmentSignerPubKeyX, commitmentSignerPubKeyY],
85 | owner || deployer.address,
86 | ]);
87 |
88 | const deployed = await customDeployContract(
89 | hre,
90 | deployer,
91 | deploymentName,
92 | CONTRACT_NAME,
93 | deploymentArgs,
94 | {
95 | ...options,
96 | proxyData: initData,
97 | }
98 | );
99 |
100 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
101 |
102 | const pythia1SimpleAttester = Pythia1SimpleAttester__factory.connect(deployed.address, deployer);
103 | return { pythia1SimpleAttester, pythia1Verifier };
104 | }
105 |
106 | task('deploy-pythia-1-simple-attester')
107 | .addParam('collectionIdFirst', '')
108 | .addParam('collectionIdLast', '')
109 | .addOptionalParam(
110 | 'pythia1VerifierAddress',
111 | 'address of the proving scheme verifier. Deploy verifier if not defined.'
112 | )
113 | .addParam('attestationsRegistryAddress', 'Address of the attestations contract')
114 | .addParam('commitmentSignerPubKeyX', 'Eddsa public key coordinate X')
115 | .addParam('commitmentSignerPubKeyY', 'Eddsa public key coordinate Y')
116 | .addOptionalParam(
117 | 'owner',
118 | 'Owner of the contract that can change the commitment signer pubKey. Default to deployer'
119 | )
120 | .setAction(wrapCommonDeployOptions(deploymentAction));
121 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/attesters/pythia-1/deploy-pythia-1-verifier.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | getDeployer,
5 | beforeDeployment,
6 | afterDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | wrapCommonDeployOptions,
10 | DeployOptions,
11 | } from '../../../utils';
12 | import { Pythia1Verifier, Pythia1Verifier__factory } from '../../../../../types';
13 |
14 | export interface DeployPythia1Verifier {
15 | options?: DeployOptions;
16 | }
17 |
18 | export interface DeployedPythia1Verifier {
19 | pythia1Verifier: Pythia1Verifier;
20 | }
21 |
22 | const CONTRACT_NAME = 'Pythia1Verifier';
23 |
24 | async function deploymentAction(
25 | { options }: DeployPythia1Verifier,
26 | hre: HardhatRuntimeEnvironment
27 | ): Promise {
28 | const deployer = await getDeployer(hre);
29 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
30 | const deploymentArgs = [];
31 |
32 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
33 |
34 | const deployed = await hre.deployments.deploy(deploymentName, {
35 | contract: CONTRACT_NAME,
36 | from: deployer.address,
37 | args: deploymentArgs,
38 | skipIfAlreadyDeployed: false,
39 | });
40 |
41 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
42 |
43 | const pythia1Verifier = Pythia1Verifier__factory.connect(deployed.address, deployer);
44 | return { pythia1Verifier };
45 | }
46 |
47 | task('deploy-pythia-1-verifier').setAction(wrapCommonDeployOptions(deploymentAction));
48 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/core/deploy-attestations-registry.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | getDeployer,
5 | beforeDeployment,
6 | afterDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | wrapCommonDeployOptions,
10 | DeployOptions,
11 | } from '../../../../tasks/deploy-tasks/utils';
12 | import { AttestationsRegistry, AttestationsRegistry__factory } from '../../../../types';
13 |
14 | export interface DeployAttestationsRegistryArgs {
15 | // owner of the contract
16 | owner?: string;
17 | badges: string;
18 | // attester register role
19 | attesterRegister?: string;
20 | options?: DeployOptions;
21 | }
22 |
23 | export interface DeployedAttestationsRegistry {
24 | attestationsRegistry: AttestationsRegistry;
25 | }
26 |
27 | const CONTRACT_NAME = 'AttestationsRegistry';
28 |
29 | async function deploymentAction(
30 | { owner, badges, options }: DeployAttestationsRegistryArgs,
31 | hre: HardhatRuntimeEnvironment
32 | ): Promise {
33 | const deployer = await getDeployer(hre);
34 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
35 | const deploymentArgs = [owner || deployer.address, badges || deployer.address];
36 |
37 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
38 |
39 | const initData = new AttestationsRegistry__factory(deployer).interface.encodeFunctionData(
40 | 'initialize',
41 | [owner || deployer.address]
42 | );
43 |
44 | const deployed = await customDeployContract(
45 | hre,
46 | deployer,
47 | deploymentName,
48 | CONTRACT_NAME,
49 | deploymentArgs,
50 | { ...options, proxyData: initData }
51 | );
52 |
53 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
54 |
55 | const attestationsRegistry = AttestationsRegistry__factory.connect(deployed.address, deployer);
56 | return { attestationsRegistry };
57 | }
58 |
59 | task('deploy-attestations-registry')
60 | .addOptionalParam('owner', 'Admin of the attester register role. default to deployer')
61 | .addOptionalParam('badges', 'Address of the badges contract')
62 | .setAction(wrapCommonDeployOptions(deploymentAction));
63 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/core/deploy-badges.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | getDeployer,
5 | beforeDeployment,
6 | afterDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | wrapCommonDeployOptions,
10 | DeployOptions,
11 | } from '../../../../tasks/deploy-tasks/utils';
12 | import { Badges, Badges__factory } from '../../../../types';
13 |
14 | export interface DeployBadgesArgs {
15 | // owner of the contract
16 | uri?: string;
17 | owner?: string;
18 | // attester register role
19 | options?: DeployOptions;
20 | }
21 |
22 | export interface DeployedBadges {
23 | badges: Badges;
24 | }
25 |
26 | const CONTRACT_NAME = 'Badges';
27 |
28 | async function deploymentAction(
29 | { uri = '', owner, options }: DeployBadgesArgs,
30 | hre: HardhatRuntimeEnvironment
31 | ): Promise {
32 | const deployer = await getDeployer(hre);
33 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
34 | const deploymentArgs = [uri, owner || deployer.address];
35 |
36 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
37 |
38 | const initData = new Badges__factory(deployer).interface.encodeFunctionData('initialize', [
39 | uri,
40 | owner || deployer.address,
41 | ]);
42 |
43 | const deployed = await customDeployContract(
44 | hre,
45 | deployer,
46 | deploymentName,
47 | CONTRACT_NAME,
48 | deploymentArgs,
49 | {
50 | ...options,
51 | proxyData: initData,
52 | }
53 | );
54 |
55 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
56 |
57 | const badges = Badges__factory.connect(deployed.address, deployer);
58 | return { badges };
59 | }
60 |
61 | task('deploy-badges')
62 | .addOptionalParam('uri', 'uri')
63 | .addOptionalParam('owner', 'owner')
64 | .setAction(wrapCommonDeployOptions(deploymentAction));
65 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/core/deploy-front.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | getDeployer,
5 | beforeDeployment,
6 | afterDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | wrapCommonDeployOptions,
10 | DeployOptions,
11 | } from '../../../../tasks/deploy-tasks/utils';
12 |
13 | import { Front, Front__factory } from '../../../../types';
14 |
15 | export interface DeployFrontArgs {
16 | attestationsRegistryAddress: string;
17 | // owner of the contract
18 | // attester register role
19 | options: DeployOptions;
20 | }
21 |
22 | export interface DeployedFront {
23 | front: Front;
24 | }
25 |
26 | const CONTRACT_NAME = 'Front';
27 |
28 | async function deploymentAction(
29 | { attestationsRegistryAddress, options }: DeployFrontArgs,
30 | hre: HardhatRuntimeEnvironment
31 | ): Promise {
32 | const deployer = await getDeployer(hre);
33 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
34 | const deploymentArgs = [attestationsRegistryAddress];
35 |
36 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
37 |
38 | const initData = '0x';
39 |
40 | const deployed = await customDeployContract(
41 | hre,
42 | deployer,
43 | deploymentName,
44 | CONTRACT_NAME,
45 | deploymentArgs,
46 | {
47 | ...options,
48 | proxyData: initData,
49 | }
50 | );
51 |
52 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
53 |
54 | const front = Front__factory.connect(deployed.address, deployer);
55 | return { front };
56 | }
57 |
58 | task('deploy-front')
59 | .addParam('attestationsRegistryAddress', 'Attestation Registry on which to read')
60 | .setAction(wrapCommonDeployOptions(deploymentAction));
61 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/periphery/deploy-available-roots-registry.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | getDeployer,
5 | beforeDeployment,
6 | afterDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | wrapCommonDeployOptions,
10 | DeployOptions,
11 | } from '../../../../tasks/deploy-tasks/utils';
12 |
13 | import { AvailableRootsRegistry, AvailableRootsRegistry__factory } from '../../../../types';
14 |
15 | export interface DeployAvailableRootsRegistry {
16 | // owner of the contract
17 | owner?: string;
18 | options?: DeployOptions;
19 | }
20 |
21 | export interface DeployedAvailableRootsRegistry {
22 | availableRootsRegistry: AvailableRootsRegistry;
23 | }
24 |
25 | const CONTRACT_NAME = 'AvailableRootsRegistry';
26 |
27 | async function deploymentAction(
28 | { owner, options }: DeployAvailableRootsRegistry,
29 | hre: HardhatRuntimeEnvironment
30 | ): Promise {
31 | const deployer = await getDeployer(hre);
32 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
33 | const deploymentArgs = [owner || deployer.address];
34 |
35 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
36 |
37 | const initData = new AvailableRootsRegistry__factory().interface.encodeFunctionData(
38 | 'initialize',
39 | [owner || deployer.address]
40 | );
41 |
42 | const deployed = await customDeployContract(
43 | hre,
44 | deployer,
45 | deploymentName,
46 | CONTRACT_NAME,
47 | deploymentArgs,
48 | {
49 | ...options,
50 | proxyData: initData,
51 | }
52 | );
53 |
54 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
55 |
56 | const availableRootsRegistry = AvailableRootsRegistry__factory.connect(
57 | deployed.address,
58 | deployer
59 | );
60 | return { availableRootsRegistry };
61 | }
62 |
63 | task('deploy-available-roots-registry')
64 | .addOptionalParam('owner', 'Admin of the attester register role. default to deployer')
65 | .setAction(wrapCommonDeployOptions(deploymentAction));
66 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/periphery/deploy-commitment-mapper-registry.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import {
4 | getDeployer,
5 | beforeDeployment,
6 | afterDeployment,
7 | buildDeploymentName,
8 | customDeployContract,
9 | wrapCommonDeployOptions,
10 | DeployOptions,
11 | } from '../../../../tasks/deploy-tasks/utils';
12 |
13 | import { CommitmentMapperRegistry, CommitmentMapperRegistry__factory } from '../../../../types';
14 |
15 | export interface DeployCommitmentMapperArgs {
16 | // owner of the contract
17 | owner?: string;
18 | commitmentMapperPubKeyX?: string;
19 | commitmentMapperPubKeyY?: string;
20 | commitmentMapperAddress?: string;
21 | options?: DeployOptions;
22 | }
23 |
24 | export interface DeployedCommitmentMapper {
25 | commitmentMapperRegistry: CommitmentMapperRegistry;
26 | }
27 |
28 | const CONTRACT_NAME = 'CommitmentMapperRegistry';
29 |
30 | async function deploymentAction(
31 | {
32 | owner,
33 | commitmentMapperPubKeyX,
34 | commitmentMapperPubKeyY,
35 | commitmentMapperAddress,
36 | options,
37 | }: DeployCommitmentMapperArgs,
38 | hre: HardhatRuntimeEnvironment
39 | ): Promise {
40 | const deployer = await getDeployer(hre);
41 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
42 | const deploymentArgs = [
43 | owner || deployer.address,
44 | [commitmentMapperPubKeyX, commitmentMapperPubKeyY],
45 | commitmentMapperAddress || hre.ethers.constants.AddressZero,
46 | ];
47 |
48 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
49 |
50 | const initData = new CommitmentMapperRegistry__factory().interface.encodeFunctionData(
51 | 'initialize',
52 | [
53 | owner || deployer.address,
54 | [commitmentMapperPubKeyX, commitmentMapperPubKeyY],
55 | commitmentMapperAddress || hre.ethers.constants.AddressZero,
56 | ]
57 | );
58 |
59 | const deployed = await customDeployContract(
60 | hre,
61 | deployer,
62 | deploymentName,
63 | CONTRACT_NAME,
64 | deploymentArgs,
65 | {
66 | ...options,
67 | proxyData: initData,
68 | }
69 | );
70 |
71 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
72 |
73 | const commitmentMapperRegistry = CommitmentMapperRegistry__factory.connect(
74 | deployed.address,
75 | deployer
76 | );
77 | return { commitmentMapperRegistry };
78 | }
79 |
80 | task('deploy-commitment-mapper-registry')
81 | .addOptionalParam('commitmentMapperPubKeyX', 'Eddsa public key coordinate x')
82 | .addOptionalParam('commitmentMapperPubKeyY', 'Eddsa public key coordinate y')
83 | .addOptionalParam('commitmentMapperAddress', 'ethereum address of commitment mapper')
84 | .addOptionalParam('owner', 'Admin of the commitment mapper updater role. default to deployer')
85 | .setAction(wrapCommonDeployOptions(deploymentAction));
86 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/unit/periphery/deploy-frontend-lib.task.ts:
--------------------------------------------------------------------------------
1 | import { FrontendLib } from '../../../../types/FrontendLib';
2 | import { task } from 'hardhat/config';
3 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
4 | import {
5 | getDeployer,
6 | beforeDeployment,
7 | afterDeployment,
8 | buildDeploymentName,
9 | customDeployContract,
10 | wrapCommonDeployOptions,
11 | DeployOptions,
12 | } from '../../utils';
13 |
14 | import { FrontendLib__factory } from '../../../../types';
15 | import { deploymentsConfig } from '../../../../tasks/deploy-tasks/deployments-config';
16 |
17 | export interface DeployFrontendLib {
18 | hydraS1AccountboundAttester?: string;
19 | options?: DeployOptions;
20 | }
21 |
22 | export interface DeployedFrontendLib {
23 | frontendLib: FrontendLib;
24 | }
25 |
26 | const CONTRACT_NAME = 'FrontendLib';
27 |
28 | async function deploymentAction(
29 | { hydraS1AccountboundAttester, options }: DeployFrontendLib,
30 | hre: HardhatRuntimeEnvironment
31 | ): Promise {
32 | const deployer = await getDeployer(hre);
33 | const deploymentName = buildDeploymentName(CONTRACT_NAME, options?.deploymentNamePrefix);
34 | const config = deploymentsConfig[hre.network.name];
35 |
36 | const deploymentArgs = [
37 | hydraS1AccountboundAttester || config.hydraS1AccountboundAttester.address,
38 | ];
39 |
40 | await beforeDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, options);
41 |
42 | const deployed = await customDeployContract(
43 | hre,
44 | deployer,
45 | deploymentName,
46 | CONTRACT_NAME,
47 | deploymentArgs,
48 | {
49 | ...options,
50 | behindProxy: false,
51 | }
52 | );
53 |
54 | await afterDeployment(hre, deployer, CONTRACT_NAME, deploymentArgs, deployed, options);
55 |
56 | const frontLib = FrontendLib__factory.connect(deployed.address, deployer);
57 | return { frontendLib: frontLib };
58 | }
59 |
60 | task('deploy-frontend-lib')
61 | .addOptionalParam(
62 | 'hydraS1AccountboundAttester',
63 | 'address of the hydraS1AccountboundAttester contract'
64 | )
65 | .setAction(wrapCommonDeployOptions(deploymentAction));
66 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/utils/deployments-config-types.ts:
--------------------------------------------------------------------------------
1 | import { CommonTaskOptions } from '../../utils';
2 |
3 | export interface DeployOptions extends CommonTaskOptions {
4 | // prefix for the contract name
5 | deploymentNamePrefix?: string;
6 | // deploy with proxy?
7 | behindProxy?: boolean;
8 | // Proxy data is the encoded call of the initialize(params) function
9 | proxyData?: string;
10 | // admin of the proxy
11 | proxyAdmin?: string;
12 | // set to true if the deployment is an upgrade of an existing proxy
13 | isImplementationUpgrade?: boolean;
14 | // proxy address, required in case of implementation upgrade
15 | proxyAddress?: string;
16 | // deterministic deployment
17 | deterministicDeployment?: boolean;
18 | }
19 |
20 | export type DeploymentsConfigTypes = {
21 | [chain: string]: {
22 | // Conf related to the deployment (behind proxy, etc.)
23 | deployOptions: DeployOptions;
24 | // Conf related to the hydraS1AccountboundAttester
25 | hydraS1Verifier: {
26 | address: string;
27 | };
28 | hydraS1AccountboundAttester: {
29 | address: string;
30 | collectionIdFirst: string;
31 | collectionIdLast: string;
32 | initialRoot: string;
33 | owner: string;
34 | };
35 | hydraS1SimpleAttester: {
36 | enableDeployment: boolean;
37 | address: string;
38 | collectionIdFirst: string;
39 | collectionIdLast: string;
40 | initialRoot: string;
41 | };
42 | pythia1Verifier: {
43 | address: string;
44 | };
45 | synapsPythia1SimpleAttester: {
46 | address: string;
47 | collectionIdFirst: string;
48 | collectionIdLast: string;
49 | commitmentSignerPubKeyX: string;
50 | commitmentSignerPubKeyY: string;
51 | owner: string;
52 | };
53 | // Conf related to the commitment mapper
54 | // https://github.com/sismo-core/sismo-commitment-mapper
55 | commitmentMapper: {
56 | address: string;
57 | owner: string;
58 | EdDSAPubKeyX: string;
59 | EdDSAPubKeyY: string;
60 | };
61 | badges: {
62 | address: string;
63 | owner: string;
64 | uri: string;
65 | };
66 | // conf related to the roots Registry to store
67 | // all the merkleRoots
68 | availableRootsRegistry: {
69 | address: string;
70 | owner: string;
71 | };
72 | attestationsRegistry: {
73 | address: string;
74 | owner: string;
75 | };
76 | front: {
77 | address: string;
78 | collectionIdFirst: string;
79 | collectionIdLast: string;
80 | };
81 | sismoAddressesProvider: {
82 | address: string;
83 | owner: string;
84 | };
85 | };
86 | };
87 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './deployment';
2 | export * from './deployments-config-types';
3 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/zkdrop/deploy-mergooor-pass.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { DeployOptions } from '../utils';
4 | import { deploymentsConfig } from '../deployments-config';
5 | import { ZKBadgeboundERC721 } from 'types';
6 | import { DeployedZkBadgeboundERC721 } from 'tasks/deploy-tasks/tests/deploy-zk-badgebound-erc721.task';
7 |
8 | export interface DeployedMergooorPass {
9 | zkBadgeboundERC721: ZKBadgeboundERC721;
10 | }
11 |
12 | async function deploymentAction(
13 | { options }: { options: DeployOptions },
14 | hre: HardhatRuntimeEnvironment
15 | ): Promise {
16 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
17 | options = { ...config.deployOptions, ...options };
18 |
19 | if (options.manualConfirm || options.log) {
20 | console.log('deploy-mergooor-pass: ', hre.network.name);
21 | }
22 |
23 | // Deploy SismoAddressesProvider
24 | const { zkBadgeboundERC721 } = (await hre.run('deploy-zk-badgebound-erc721', {
25 | name: 'Mergooor Pass',
26 | symbol: 'MP',
27 | tokenURI: 'ipfs://QmPR9q3Q5fByxzfMfRp32azvH2UPXhPoDFhHWAsiGNHBwS/',
28 | gatingBadgeTokenId: '10000040',
29 | admin: '0xaee4acd5c4Bf516330ca8fe11B07206fC6709294', // Sismo owner
30 | deploymentName: 'MergooorPass',
31 | options,
32 | })) as DeployedZkBadgeboundERC721;
33 |
34 | return {
35 | zkBadgeboundERC721,
36 | };
37 | }
38 |
39 | task('deploy-mergooor-pass').setAction(deploymentAction);
40 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/zkdrop/deploy-ziki-pass-staging.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { DeployOptions } from '../utils';
4 | import { deploymentsConfig } from '../deployments-config';
5 | import { ZKBadgeboundERC721 } from 'types';
6 | import { DeployedZkBadgeboundERC721 } from 'tasks/deploy-tasks/tests/deploy-zk-badgebound-erc721.task';
7 |
8 | export interface DeployedZikiPass {
9 | zkBadgeboundERC721: ZKBadgeboundERC721;
10 | }
11 |
12 | async function deploymentAction(
13 | { options }: { options: DeployOptions },
14 | hre: HardhatRuntimeEnvironment
15 | ): Promise {
16 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
17 | options = { ...config.deployOptions, ...options };
18 |
19 | if (options.manualConfirm || options.log) {
20 | console.log('deploy-ziki-pass-staging: ', hre.network.name);
21 | }
22 |
23 | // Deploy SismoAddressesProvider
24 | const { zkBadgeboundERC721 } = (await hre.run('deploy-zk-badgebound-erc721', {
25 | name: 'Ziki Pass',
26 | symbol: 'ZKP',
27 | tokenURI: 'ipfs://Qme1WfqhZ4dUVSKHE9NqH1z7MXFtviPY6QEPwu8TcgAyjc/',
28 | gatingBadgeTokenId: '10000515',
29 | admin: '0xf61cabba1e6fc166a66bca0fcaa83762edb6d4bd', // leo21.eth
30 | deploymentName: 'ZikiPass',
31 | options,
32 | })) as DeployedZkBadgeboundERC721;
33 |
34 | return {
35 | zkBadgeboundERC721,
36 | };
37 | }
38 |
39 | task('deploy-ziki-pass-staging').setAction(deploymentAction);
40 |
--------------------------------------------------------------------------------
/tasks/deploy-tasks/zkdrop/deploy-ziki-pass-testnet.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { DeployOptions } from '../utils';
4 | import { deploymentsConfig } from '../deployments-config';
5 | import { ZKBadgeboundERC721 } from 'types';
6 | import { DeployedZkBadgeboundERC721 } from 'tasks/deploy-tasks/tests/deploy-zk-badgebound-erc721.task';
7 |
8 | export interface DeployedZikiPass {
9 | zkBadgeboundERC721: ZKBadgeboundERC721;
10 | }
11 |
12 | async function deploymentAction(
13 | { options }: { options: DeployOptions },
14 | hre: HardhatRuntimeEnvironment
15 | ): Promise {
16 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
17 | options = { ...config.deployOptions, ...options };
18 |
19 | if (options.manualConfirm || options.log) {
20 | console.log('deploy-ziki-pass-testnet: ', hre.network.name);
21 | }
22 |
23 | // Deploy SismoAddressesProvider
24 | const { zkBadgeboundERC721 } = (await hre.run('deploy-zk-badgebound-erc721', {
25 | name: 'Ziki Pass',
26 | symbol: 'ZKP',
27 | tokenURI: 'https://metadata-zikies.zkdrop.io/ziki-pass/',
28 | gatingBadgeTokenId: '10000515',
29 | admin: '0xf61cabba1e6fc166a66bca0fcaa83762edb6d4bd', // leo21.eth
30 | deploymentName: 'ZikiPass',
31 | options,
32 | })) as DeployedZkBadgeboundERC721;
33 |
34 | return {
35 | zkBadgeboundERC721,
36 | };
37 | }
38 |
39 | task('deploy-ziki-pass-testnet').setAction(deploymentAction);
40 |
--------------------------------------------------------------------------------
/tasks/helpers/authorizations/access-control-grant-role.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { AccessControl__factory } from '../../../types';
4 | import { CommonTaskOptions } from '../../utils';
5 | import { confirm } from '../../utils/confirm';
6 |
7 | export type AccessControlGrantRoleArgs = {
8 | contractAddress: string;
9 | role: string;
10 | accountAddress: string;
11 | options?: CommonTaskOptions;
12 | };
13 |
14 | async function grantRole(
15 | { contractAddress, role, accountAddress, options }: AccessControlGrantRoleArgs,
16 | hre: HardhatRuntimeEnvironment
17 | ): Promise {
18 | const [signer] = await hre.ethers.getSigners();
19 |
20 | if (options?.log || options?.manualConfirm) {
21 | console.log(`
22 | ************************************
23 | * GRANT ROLE *
24 | ************************************`);
25 | }
26 |
27 | const accessControlContract = AccessControl__factory.connect(contractAddress, signer);
28 |
29 | const accountAlreadyHaveRole = await accessControlContract.hasRole(role, accountAddress);
30 |
31 | // Verify if the account already have the good role
32 | if (accountAlreadyHaveRole) {
33 | if (options?.log || options?.manualConfirm) {
34 | console.log(`
35 | * ${accountAddress} already has role ${role} on contract ${contractAddress}
36 | `);
37 | }
38 | return;
39 | }
40 |
41 | // Verify signer can give the role
42 | const signerAddressIsAdminRole = await accessControlContract.hasRole(
43 | await accessControlContract.DEFAULT_ADMIN_ROLE(),
44 | signer.address
45 | );
46 |
47 | if (!signerAddressIsAdminRole) {
48 | throw new Error(
49 | `The current signer (${signer.address}) is not admin of the current contract ${contractAddress}. Can't grant role ${role}`
50 | );
51 | }
52 |
53 | const actionGrantRole = {
54 | role: role,
55 | toAccount: accountAddress,
56 | contract: contractAddress,
57 | };
58 | // Grant role section
59 | if (options?.log || options?.manualConfirm) {
60 | console.log(`
61 | ${Object.keys(actionGrantRole as Object).map(
62 | (key) => `
63 | ${key}: ${actionGrantRole?.[key]}`
64 | )}`);
65 | }
66 | if (options?.manualConfirm) {
67 | console.log();
68 | await confirm();
69 | }
70 | const tx = await accessControlContract.grantRole(actionGrantRole.role, actionGrantRole.toAccount);
71 | await tx.wait();
72 |
73 | if (options?.log || options?.manualConfirm) {
74 | console.log(`
75 | * Role Granted !
76 | `);
77 | }
78 | }
79 |
80 | task('access-control-grant-role')
81 | .addParam('contractAddress', 'Contract concerned by the grantRole call')
82 | .addParam('role', 'Role to grant')
83 | .addParam('accountAddress', 'Account to receive the role')
84 | .setAction(grantRole);
85 |
--------------------------------------------------------------------------------
/tasks/helpers/authorizations/access-control-revoke-role.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { AccessControl__factory } from '../../../types';
4 | import { CommonTaskOptions } from '../../utils';
5 | import { confirm } from '../../utils/confirm';
6 |
7 | export type AccessControlRevokeRoleArgs = {
8 | contractAddress: string;
9 | role: string;
10 | accountAddress: string;
11 | options?: CommonTaskOptions;
12 | };
13 |
14 | async function revokeRole(
15 | { contractAddress, role, accountAddress, options }: AccessControlRevokeRoleArgs,
16 | hre: HardhatRuntimeEnvironment
17 | ): Promise {
18 | const [signer] = await hre.ethers.getSigners();
19 |
20 | if (options?.log || options?.manualConfirm) {
21 | console.log(`
22 | ************************************
23 | * REVOKE ROLE *
24 | ************************************`);
25 | }
26 |
27 | const accessControlContract = AccessControl__factory.connect(contractAddress, signer);
28 |
29 | const accountAlreadyHaveRole = await accessControlContract.hasRole(role, accountAddress);
30 |
31 | // Verify if the account already have the good role
32 | if (!accountAlreadyHaveRole) {
33 | if (options?.log || options?.manualConfirm) {
34 | console.log(`
35 | * ${accountAddress} don't have role ${role} on contract ${contractAddress}. Exiting
36 | `);
37 | }
38 | return;
39 | }
40 |
41 | // Verify signer can revoke the role
42 | const signerAddressIsAdminRole = await accessControlContract.hasRole(
43 | await accessControlContract.DEFAULT_ADMIN_ROLE(),
44 | signer.address
45 | );
46 |
47 | if (!signerAddressIsAdminRole) {
48 | throw new Error(
49 | `The current signer (${signer.address}) is not admin of the current contract ${contractAddress}. Can't revoke role ${role}`
50 | );
51 | }
52 |
53 | const actionRevokeRole = {
54 | role: role,
55 | toAccount: accountAddress,
56 | contract: contractAddress,
57 | };
58 | // Revoke role section
59 | if (options?.log || options?.manualConfirm) {
60 | console.log(`
61 | ${Object.keys(actionRevokeRole as Object).map(
62 | (key) => `
63 | ${key}: ${actionRevokeRole?.[key]}`
64 | )}`);
65 | }
66 | if (options?.manualConfirm) {
67 | console.log();
68 | await confirm();
69 | }
70 | const tx = await accessControlContract.revokeRole(
71 | actionRevokeRole.role,
72 | actionRevokeRole.toAccount
73 | );
74 | await tx.wait();
75 |
76 | if (options?.log || options?.manualConfirm) {
77 | console.log(`
78 | * Role Revoked !
79 | `);
80 | }
81 | }
82 |
83 | task('access-control-revoke-role')
84 | .addParam('contractAddress', 'Contract concerned by the revokeRole call')
85 | .addParam('role', 'Role to revoke')
86 | .addParam('accountAddress', 'Account to receive the role')
87 | .setAction(revokeRole);
88 |
--------------------------------------------------------------------------------
/tasks/helpers/authorizations/attestations-registry-authorize-range.task.ts:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers';
2 | import { task } from 'hardhat/config';
3 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
4 | import { AttestationsRegistry__factory } from '../../../types';
5 | import { CommonTaskOptions } from '../../utils';
6 | import { confirm } from '../../utils/confirm';
7 |
8 | export type AuthorizeRangeArgs = {
9 | attestationsRegistryAddress: string;
10 | attesterAddress: string;
11 | collectionIdFirst: string;
12 | collectionIdLast: string;
13 | options?: CommonTaskOptions;
14 | };
15 |
16 | async function authorizeRange(
17 | {
18 | attestationsRegistryAddress,
19 | attesterAddress,
20 | collectionIdFirst,
21 | collectionIdLast,
22 | options,
23 | }: AuthorizeRangeArgs,
24 | hre: HardhatRuntimeEnvironment
25 | ): Promise {
26 | const [signer] = await hre.ethers.getSigners();
27 |
28 | if (options?.log || options?.manualConfirm) {
29 | console.log(`
30 | ************************************
31 | * AUTHORIZE ATTESTER *
32 | ************************************`);
33 | }
34 |
35 | const attestationsRegistry = AttestationsRegistry__factory.connect(
36 | attestationsRegistryAddress,
37 | signer
38 | );
39 |
40 | // Verify if attester is already authorized in the AttestationsRegistry
41 | const isFirstRangeAuthorized = await attestationsRegistry.isAuthorized(
42 | attesterAddress,
43 | collectionIdFirst
44 | );
45 | const isLastRangeAuthorized = await attestationsRegistry.isAuthorized(
46 | attesterAddress,
47 | collectionIdLast
48 | );
49 | if (isFirstRangeAuthorized && isLastRangeAuthorized) {
50 | if (options?.log || options?.manualConfirm) {
51 | console.log(
52 | `Range (${collectionIdFirst}, ${collectionIdLast}) for ${attesterAddress} seems already authorized.`
53 | );
54 | }
55 | return;
56 | }
57 |
58 | const currentOwner = await attestationsRegistry.owner();
59 |
60 | // Authorizing the collectionIdFirst and collectionIdLast for the attester
61 | const actionAuthorizeRange = {
62 | attester: attesterAddress,
63 | collectionIdFirst,
64 | collectionIdLast,
65 | attestationsRegistry: attestationsRegistry.address,
66 | currentOwner,
67 | };
68 | if (options?.log || options?.manualConfirm) {
69 | console.log(`
70 | ${Object.keys(actionAuthorizeRange as Object).map(
71 | (key) => `
72 | ${key}: ${actionAuthorizeRange?.[key]}`
73 | )}`);
74 | }
75 |
76 | // Verify if the current signer is the owner of the attestationsRegistry
77 | if (
78 | signer.address.toLowerCase() !== currentOwner.toLowerCase() &&
79 | process.env.OWNER_MANUAL_OPERATION !== 'true'
80 | ) {
81 | throw new Error(
82 | `The current signer (${signer.address}) is not owner of the attestations registry contract ${attestationsRegistry.address}. Can't authorize attester.`
83 | );
84 | } else if (process.env.OWNER_MANUAL_OPERATION === 'true') {
85 | if (options?.manualConfirm) {
86 | const iface = new ethers.utils.Interface(AttestationsRegistry__factory.abi);
87 | const data = iface.encodeFunctionData('authorizeRange', [
88 | actionAuthorizeRange.attester,
89 | actionAuthorizeRange.collectionIdFirst,
90 | actionAuthorizeRange.collectionIdLast,
91 | ]);
92 | console.log({
93 | from: currentOwner,
94 | to: attestationsRegistry.address,
95 | data: data,
96 | });
97 | console.log('Send the transaction using etherscan !');
98 | await confirm();
99 | }
100 | } else {
101 | if (options?.manualConfirm) {
102 | console.log();
103 | await confirm();
104 | }
105 |
106 | const tx = await attestationsRegistry.authorizeRange(
107 | actionAuthorizeRange.attester,
108 | actionAuthorizeRange.collectionIdFirst,
109 | actionAuthorizeRange.collectionIdLast
110 | );
111 | await tx.wait();
112 |
113 | if (options?.log || options?.manualConfirm) {
114 | console.log(`
115 | * Attester well authorized !
116 | `);
117 | }
118 | }
119 | }
120 |
121 | task('attestations-registry-authorize-range')
122 | .addParam('attestationsRegistryAddress', 'Address of the attestations registry')
123 | .addParam('attesterAddress', 'Address of the attester')
124 | .addParam(
125 | 'collectionIdFirst',
126 | 'collectionId min authorized by the attestations registry to the attester'
127 | )
128 | .addParam(
129 | 'collectionIdLast',
130 | 'collectionId max authorized by the attestations registry to the attester'
131 | )
132 | .setAction(authorizeRange);
133 |
--------------------------------------------------------------------------------
/tasks/helpers/authorizations/attestations-registry-transfer-ownership.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { deploymentsConfig } from '../../deploy-tasks/deployments-config';
4 | import { OwnableTransferOwnershipArgs } from './ownable-transfer-ownership.task';
5 | import { CommonTaskOptions, getCommonOptions } from '../../utils';
6 |
7 | export type AuthorizeRangeArgs = {
8 | options?: CommonTaskOptions;
9 | };
10 |
11 | async function authorizeRange(
12 | { options }: AuthorizeRangeArgs,
13 | hre: HardhatRuntimeEnvironment
14 | ): Promise {
15 | const config = deploymentsConfig[hre.network.name];
16 | options = { ...config.deployOptions, ...options };
17 |
18 | if (options.manualConfirm || options.log) {
19 | console.log(`
20 | ----------------------------------------------------------------
21 | * Transfer AttestationsRegistry ownership`);
22 | }
23 | await hre.run('ownable-transfer-ownership', {
24 | contractAddress: (await hre.deployments.all()).AttestationsRegistry.address,
25 | newOwner: config.attestationsRegistry.owner,
26 | options: getCommonOptions(options),
27 | } as OwnableTransferOwnershipArgs);
28 | }
29 |
30 | task('transfer-attestations-registry-ownership').setAction(authorizeRange);
31 |
--------------------------------------------------------------------------------
/tasks/helpers/authorizations/change-proxy-admin.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { TransparentUpgradeableProxy__factory } from '../../../types';
4 | import { CommonTaskOptions, wrapCommonOptions } from '../../utils';
5 | import { confirm } from '../../utils/confirm';
6 | import { deploymentsConfig } from '../../deploy-tasks/deployments-config';
7 |
8 | export type ChangeProxyAdminArgs = {
9 | proxyAddress: string;
10 | newAdmin: string;
11 | options?: CommonTaskOptions;
12 | };
13 |
14 | async function action(
15 | { proxyAddress, newAdmin, options }: ChangeProxyAdminArgs,
16 | hre: HardhatRuntimeEnvironment
17 | ): Promise {
18 | const [signer] = await hre.ethers.getSigners();
19 |
20 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
21 |
22 | const proxy = TransparentUpgradeableProxy__factory.connect(proxyAddress, signer);
23 |
24 | if (process.env.CHANGE_PROXY_ADMIN_MANUAL_OPERATION === 'true') {
25 | console.log(`
26 | ************************************
27 | * CHANGE PROXY ADMIN *
28 | ************************************`);
29 |
30 | if (options?.manualConfirm) {
31 | await confirm();
32 | }
33 |
34 | // we can't connect as signer, we need manual operation
35 | const iface = new hre.ethers.utils.Interface(TransparentUpgradeableProxy__factory.abi);
36 | const data = iface.encodeFunctionData('changeAdmin', [newAdmin]);
37 |
38 | console.log({
39 | from: signer.address,
40 | to: proxy.address,
41 | data: data,
42 | });
43 |
44 | console.log('Send the transaction using etherscan !');
45 | } else {
46 | console.log(`
47 | Aborting changeProxyAdmin...`);
48 | }
49 | }
50 |
51 | task('change-proxy-admin')
52 | .addParam('proxyAddress', "Address of the proxy we want to change it's admin")
53 | .addParam('newAdmin', 'Address of the new admin')
54 | .setAction(wrapCommonOptions(action));
55 |
--------------------------------------------------------------------------------
/tasks/helpers/authorizations/ownable-transfer-ownership.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { Ownable__factory } from '../../../types/factories/Ownable__factory';
4 | import { CommonTaskOptions } from '../../utils';
5 | import { confirm } from '../../utils/confirm';
6 |
7 | export type OwnableTransferOwnershipArgs = {
8 | contractAddress: string;
9 | newOwner: string;
10 | options?: CommonTaskOptions;
11 | };
12 |
13 | async function ownableTransferOwnership(
14 | { contractAddress, newOwner, options }: OwnableTransferOwnershipArgs,
15 | hre: HardhatRuntimeEnvironment
16 | ): Promise {
17 | const [signer] = await hre.ethers.getSigners();
18 |
19 | if (options?.log || options?.manualConfirm) {
20 | console.log(`
21 | ************************************
22 | * TRANSFER OWNERSHIP *
23 | ************************************`);
24 | }
25 |
26 | const ownableContract = Ownable__factory.connect(contractAddress, signer);
27 | const currentOwner = await ownableContract.owner();
28 |
29 | // verify is the newOwner il already owner of the contract
30 | if (currentOwner.toLowerCase() === newOwner.toLowerCase()) {
31 | if (options?.log || options?.manualConfirm) {
32 | console.log(`
33 | * CurrentOwner(${currentOwner}) is already the targetted owner. Nothing to do, exiting.
34 | `);
35 | }
36 | return;
37 | }
38 |
39 | // verify the signer has the rights to transfer ownership of the current contract
40 | if (
41 | signer.address.toLowerCase() !== currentOwner.toLowerCase() &&
42 | process.env.OWNER_MANUAL_OPERATION !== 'true'
43 | ) {
44 | throw new Error(
45 | `The current signer (${signer.address}) is not owner of the current contract ${ownableContract.address}. Can't transfer ownership`
46 | );
47 | }
48 |
49 | // transfering ownership section
50 | const actionTransferOwnership = {
51 | currentOwner,
52 | newOwner,
53 | contract: ownableContract.address,
54 | };
55 | if (options?.log || options?.manualConfirm) {
56 | console.log(`
57 | ${Object.keys(actionTransferOwnership as Object).map(
58 | (key) => `
59 | ${key}: ${actionTransferOwnership?.[key]}`
60 | )}`);
61 | }
62 | if (options?.manualConfirm) {
63 | console.log();
64 | await confirm();
65 | }
66 |
67 | if (process.env.OWNER_MANUAL_OPERATION === 'true') {
68 | // we can't connect as signer, we need manual operation
69 | const iface = new hre.ethers.utils.Interface(Ownable__factory.abi);
70 | const data = iface.encodeFunctionData('transferOwnership', [actionTransferOwnership.newOwner]);
71 |
72 | console.log({
73 | from: currentOwner.toLowerCase(),
74 | to: contractAddress,
75 | data: data,
76 | });
77 | } else {
78 | const tx = await ownableContract.transferOwnership(actionTransferOwnership.newOwner);
79 | await tx.wait();
80 |
81 | if (options?.log || options?.manualConfirm) {
82 | console.log(`
83 | * Ownership transferred !
84 | `);
85 | }
86 | }
87 | }
88 |
89 | task('ownable-transfer-ownership')
90 | .addParam('contractAddress', 'Ownable contract address to transfer ownership')
91 | .addParam('newOwner', 'New owner to transfer ownership')
92 | .setAction(ownableTransferOwnership);
93 |
--------------------------------------------------------------------------------
/tasks/helpers/print-accounts.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 |
4 | async function printAccounts({}, hre: HardhatRuntimeEnvironment): Promise {
5 | (await hre.ethers.getSigners()).map((signer, index) =>
6 | console.log(`
7 | Account #${index}: ${signer.address}`)
8 | );
9 | const signer = (await hre.ethers.getSigners())[0];
10 | const tx = await signer.sendTransaction({
11 | to: '0xfA6acea9De65F319aB583C05a49B2CB9cF5Ad111',
12 | data: '0xdce4534f000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000fd247ff5380d7da60e9018d1d29d529664839af2000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000202a4764782297e8e049f7dae7b25e5f9885dc5524aa5152db9bfc0175ac5e1cfb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000062a1f07e0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000024029243f4cedf90da2cef8712652a82b5e2c18b1ddbecd5c636719b8225868e72c2b705c6f8f6d8d2c426098d219bc5fab358341609b9788d80b03543f255454ec14b4ab1c5d6308f349e3566f8541dab61ccbd2f8afb4c8e10edab0be6665d8ab01bb8372d783f9b9fe626003d95502e8fa5fe5e1a8034edd87d35e9740fd629924d7e6248eccc662715ba2942b3c661ee53f687403a32dd4b07ccc7f7c3322c505c0ef373ca904d3f0de7e13240e6f256c3ca70bdf67439a8d2acbbe87d785ba0b0e361c1c9a5fdec9f06b06a68c7f718aa8f2ead8179f8591c6ef44a570335a2585771047fe68b4bda2592c2a59e7f771efafe184ee8a5518d250e38907fbf1000000000000000000000000fd247ff5380d7da60e9018d1d29d529664839af200000000000000000000000000000000000000000000000000000000000000041e468ad0fcde4edec429cd41eb28a0e78d4f31fa2c25172ef677468b2b38a9dc2b6e9a8e3b8ed419cca51e2e2ee7ae07d2902454deca17d7da7b00ae4a798add29c161c3ff1113059a064605aa9ddcfe636110a659037ef048f02a2e0233a79b2ef78ebff2f2e569060364b0d07798c61442f09f7e58f3f149cba98c09155fc222015ea96fc74d541186c5dcfca6813f2f55a5c525192f362928825f6165284500000000000000000000000000000000000000000000000000000000000000012a4764782297e8e049f7dae7b25e5f9885dc5524aa5152db9bfc0175ac5e1cfb0000000000000000000000000000000000000000000000000000000000000000',
13 | gasLimit: 8000000,
14 | });
15 | console.log(tx);
16 | console.log(await tx.wait());
17 | }
18 |
19 | task('print-accounts').setAction(printAccounts);
20 |
--------------------------------------------------------------------------------
/tasks/helpers/print-storage-layout.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 |
4 | async function printStorageLayout({}, hre: HardhatRuntimeEnvironment): Promise {
5 | await hre.run('deploy-full-local');
6 | await hre.storageLayout.export();
7 | }
8 |
9 | task('print-storage-layout').setAction(printStorageLayout);
10 |
--------------------------------------------------------------------------------
/tasks/helpers/proxy/upgrade-proxy.task.ts:
--------------------------------------------------------------------------------
1 | import { ethers } from 'ethers';
2 | import { task } from 'hardhat/config';
3 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
4 | import { deploymentsConfig } from '../../deploy-tasks/deployments-config';
5 | import { TransparentUpgradeableProxy__factory } from '../../../types';
6 | import { CommonTaskOptions } from '../../utils';
7 | import { confirm } from '../../utils/confirm';
8 |
9 | export type UpgradeProxyArgs = {
10 | proxyAddress: string;
11 | proxyData: string;
12 | newImplementationAddress: string;
13 | specificProxyAdmin?: string; // this proxy admin will be used instead of the one in the config
14 | options?: CommonTaskOptions;
15 | };
16 |
17 | async function upgradeProxy(
18 | {
19 | proxyAddress,
20 | proxyData,
21 | newImplementationAddress,
22 | specificProxyAdmin,
23 | options,
24 | }: UpgradeProxyArgs,
25 | hre: HardhatRuntimeEnvironment
26 | ): Promise {
27 | const config = deploymentsConfig[process.env.FORK_NETWORK ?? hre.network.name];
28 |
29 | if (options?.log || options?.manualConfirm) {
30 | console.log(`
31 | ************************************
32 | * UPGRADE PROXY *
33 | ************************************`);
34 |
35 | console.log(`
36 | * upgrading proxy ***********
37 | Proxy Address: ${proxyAddress}
38 | new Implementation Address: ${newImplementationAddress}
39 | `);
40 | if (options?.manualConfirm) {
41 | await confirm();
42 | }
43 | }
44 |
45 | if (process.env.MANUAL_UPGRADE_PROXY === 'true') {
46 | // we can't connect as signer, we need manual operation
47 | const iface = new ethers.utils.Interface(TransparentUpgradeableProxy__factory.abi);
48 | const data = iface.encodeFunctionData('upgradeToAndCall', [
49 | newImplementationAddress,
50 | proxyData,
51 | ]);
52 | console.log({
53 | proxyAddress,
54 | newImplementationAddress,
55 | data: data,
56 | });
57 | console.log('Send the transaction using etherscan !');
58 | } else {
59 | // We can connect as proxy admin because signer is unlock
60 | const proxyAdmin = specificProxyAdmin ?? (config.deployOptions.proxyAdmin as string);
61 | const proxyAdminSigner = await hre.ethers.getSigner(proxyAdmin);
62 | const proxy = TransparentUpgradeableProxy__factory.connect(proxyAddress, proxyAdminSigner);
63 |
64 | await (await proxy.upgradeToAndCall(newImplementationAddress, proxyData)).wait();
65 |
66 | if (options?.log || options?.manualConfirm) {
67 | console.log(`
68 | * Proxy implementation well updated !
69 | `);
70 | }
71 | }
72 |
73 | if (options?.log) {
74 | console.log(`
75 | * proxy upgraded ***********
76 | Proxy Address: ${proxyAddress}
77 | new Implementation Address: ${newImplementationAddress}
78 | `);
79 | }
80 | }
81 |
82 | task('upgrade-proxy')
83 | .addParam('proxyAddress', 'Address of the proxy to upgrade')
84 | .addParam('newImplementationAddress', 'Address of the new implementation')
85 | .setAction(upgradeProxy);
86 |
--------------------------------------------------------------------------------
/tasks/helpers/verify-contract.task.ts:
--------------------------------------------------------------------------------
1 | import { task } from 'hardhat/config';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import fs from 'fs';
4 | import fg from 'fast-glob';
5 | import { exec } from 'child_process';
6 | import util from 'util';
7 |
8 | // Verify with etherscan only one contract
9 | // identified by its deploymentName
10 | async function verifyContract({ deploymentName }, hre: HardhatRuntimeEnvironment): Promise {
11 | const deploymentPath = `${__dirname}/../../deployments/${hre.deployments.getNetworkName()}`;
12 | const deploymentFilesToHide = fg.sync([`${deploymentPath}/*`], {
13 | ignore: [`${deploymentPath}/${deploymentName}.json`],
14 | });
15 |
16 | // hide all files except the deployment we are interested in.
17 | await hideFiles(deploymentFilesToHide);
18 |
19 | try {
20 | // layer of security: avoid triggering the verify if there is still files left
21 | const filesNotHidden = fg.sync([`${deploymentPath}/*.json`]);
22 | if (filesNotHidden.length > 1) {
23 | throw new Error(
24 | 'A deployment file other than the expected is still in the deployment folder!'
25 | );
26 | } else if (filesNotHidden.length === 0) {
27 | throw new Error(`Deployment ${deploymentName} was not found!`);
28 | }
29 |
30 | // execute the etherscan-verify
31 | const { stdout, stderr } = await util.promisify(exec)(
32 | `npx hardhat etherscan-verify --network ${hre.deployments.getNetworkName()}`
33 | );
34 | console.log(stdout);
35 | console.log(stderr);
36 | } catch (e: any) {
37 | console.log(e);
38 | }
39 |
40 | // revert modification to deployment files
41 | await revealFiles(deploymentFilesToHide);
42 | }
43 |
44 | task('verify-contract')
45 | .addParam('deploymentName', 'Name of the deployment to verify')
46 | .setAction(verifyContract);
47 |
48 | const hideFiles = async (files: string[]) => {
49 | for (const file of files) {
50 | await fs.promises.rename(file, `${file}.hidden`);
51 | }
52 | };
53 |
54 | const revealFiles = async (files: string[]) => {
55 | for (const file of files) {
56 | await fs.promises.rename(`${file}.hidden`, file);
57 | }
58 | };
59 |
--------------------------------------------------------------------------------
/tasks/utils/common-options.ts:
--------------------------------------------------------------------------------
1 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
2 | import { CommonTaskOptions } from './types';
3 | import { DeployOptions } from '../deploy-tasks/utils';
4 | import { deploymentsConfig } from '../deploy-tasks/deployments-config';
5 |
6 | export const getCommonOptions = (options: DeployOptions | CommonTaskOptions): CommonTaskOptions => {
7 | return {
8 | manualConfirm: options.manualConfirm,
9 | log: options.log,
10 | };
11 | };
12 |
13 | export const wrapCommonOptions = (action: Function) => {
14 | return (args: any, hre: HardhatRuntimeEnvironment) => {
15 | const config = deploymentsConfig[hre.network.name];
16 | return action(
17 | {
18 | ...args,
19 | options: {
20 | ...getCommonOptions(config.deployOptions),
21 | ...args.options,
22 | },
23 | },
24 | hre
25 | );
26 | };
27 | };
28 |
--------------------------------------------------------------------------------
/tasks/utils/confirm.ts:
--------------------------------------------------------------------------------
1 | import readline from 'readline';
2 | import { CommonTaskOptions } from './types';
3 |
4 | export function confirm(): Promise {
5 | return new Promise((resolve) => {
6 | const myReadLine = readline.createInterface({
7 | input: process.stdin,
8 | output: process.stdout,
9 | });
10 |
11 | myReadLine.question('Do you want to continue? Y/n \n', (input) => {
12 | myReadLine.close();
13 | if (input === 'Y' || input == 'y') {
14 | console.log('\n');
15 | resolve(undefined);
16 | } else {
17 | console.log('Deployment aborted');
18 | process.exit(0);
19 | }
20 | });
21 | });
22 | }
23 |
24 | export const manualConfirmValidity = async (object: any, options?: CommonTaskOptions) => {
25 | if (options?.log || options?.manualConfirm) {
26 | console.log(`
27 | ${Object.keys(object as Object).map(
28 | (key) => `
29 | ${key}: ${object?.[key]}`
30 | )}`);
31 | }
32 | if (options?.manualConfirm) {
33 | console.log();
34 | await confirm();
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/tasks/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './common-options';
2 | export * from './confirm';
3 | export * from './types';
4 |
--------------------------------------------------------------------------------
/tasks/utils/relayer.ts:
--------------------------------------------------------------------------------
1 | import { DefenderRelayProvider, DefenderRelaySigner } from 'defender-relay-client/lib/ethers';
2 | import { Signer } from 'ethers';
3 |
4 | const { RELAYER_API_KEY, RELAYER_API_SECRET } = process.env;
5 |
6 | export const getRelayerSigner = async (): Promise => {
7 | if (!RELAYER_API_KEY || !RELAYER_API_SECRET) {
8 | throw new Error('RELAYER_API_KEY or RELAYER_API_SECRET env variables missing');
9 | }
10 | const credentials = { apiKey: RELAYER_API_KEY, apiSecret: RELAYER_API_SECRET };
11 | const provider = new DefenderRelayProvider(credentials);
12 | return new DefenderRelaySigner(credentials, provider, { speed: 'fast' });
13 | };
14 |
--------------------------------------------------------------------------------
/tasks/utils/types.ts:
--------------------------------------------------------------------------------
1 | export interface CommonTaskOptions {
2 | // Enable logging
3 | log?: boolean;
4 | // Manually confirm deployment
5 | manualConfirm?: boolean;
6 | }
7 |
--------------------------------------------------------------------------------
/test/unit/periphery/utils/frontend-lib.test.ts:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import hre from 'hardhat';
3 |
4 | import { MockHydraS1SimpleAttester__factory } from './../../../../types/factories/MockHydraS1SimpleAttester__factory';
5 | import { FrontendLib } from './../../../../types/FrontendLib';
6 | import { DeployedFrontendLib } from '../../../../tasks/deploy-tasks/unit/periphery/deploy-frontend-lib.task';
7 | import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
8 |
9 | describe('Test FrontendLib contract', () => {
10 | let deployer: SignerWithAddress;
11 | let frontendLib: FrontendLib;
12 | let dest1: SignerWithAddress;
13 | let nullifier1: string;
14 | let dest2: SignerWithAddress;
15 | let nullifier2: string;
16 | let dest3: SignerWithAddress;
17 | let nullifier3: string;
18 | let dest4: SignerWithAddress;
19 |
20 | before(async () => {
21 | const signers = await hre.ethers.getSigners();
22 | [deployer, dest1, dest2, dest3, dest4] = signers;
23 | [nullifier1, nullifier2, nullifier3] = [
24 | '0x1000000000000000000000000000000000000000000000000000000000000001',
25 | '0x2000000000000000000000000000000000000000000000000000000000000002',
26 | '0x3000000000000000000000000000000000000000000000000000000000000003',
27 | ];
28 | });
29 |
30 | /*************************************************************************************/
31 | /********************************** DEPLOYMENTS **************************************/
32 | /*************************************************************************************/
33 | describe('Deployments', () => {
34 | it('Should deploy the FrontendLib and an HydraS1SimpleAttester mock for tests', async () => {
35 | // MockHydraS1SimpleAttester
36 | const hydraS1AttesterMock = await hre.deployments.deploy('MockHydraS1SimpleAttesterTest', {
37 | contract: 'MockHydraS1SimpleAttester',
38 | from: deployer.address,
39 | args: [],
40 | });
41 | const mockHydraS1Attester = MockHydraS1SimpleAttester__factory.connect(
42 | hydraS1AttesterMock.address,
43 | deployer
44 | );
45 |
46 | await mockHydraS1Attester.setDestinationOfNullifier(nullifier1, dest1.address);
47 | await mockHydraS1Attester.setDestinationOfNullifier(nullifier2, dest2.address);
48 | await mockHydraS1Attester.setDestinationOfNullifier(nullifier3, dest3.address);
49 |
50 | ({ frontendLib } = (await hre.run('deploy-frontend-lib', {
51 | hydraS1AccountboundAttester: hydraS1AttesterMock.address,
52 | })) as DeployedFrontendLib);
53 | });
54 | });
55 |
56 | describe('Getter', () => {
57 | it('Should get all nullifier at once', async () => {
58 | const destinations =
59 | await frontendLib.getHydraS1AccountboundAttesterDestinationOfNullifierBatch([
60 | nullifier1,
61 | nullifier2,
62 | nullifier3,
63 | // unregistered nullifier
64 | '0x0000000000000000000000000000000000000000000000000000000000000123',
65 | ]);
66 | expect(destinations[0]).to.equal(dest1.address);
67 | expect(destinations[1]).to.equal(dest2.address);
68 | expect(destinations[2]).to.equal(dest3.address);
69 | expect(destinations[3]).to.equal('0x0000000000000000000000000000000000000000');
70 | });
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/test/utils/attestation-logic.ts:
--------------------------------------------------------------------------------
1 | import { BigNumber } from 'ethers';
2 |
3 | export const computeId = (shardId: number, id: number): BigNumber => {
4 | return BigNumber.from(shardId).mul(BigNumber.from(2).pow(224)).add(id);
5 | };
6 |
--------------------------------------------------------------------------------
/test/utils/evm.ts:
--------------------------------------------------------------------------------
1 | import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
2 | import { HardhatRuntimeEnvironment } from 'hardhat/types';
3 | import { ethers } from 'hardhat';
4 |
5 | export async function increaseTime(
6 | hre: HardhatRuntimeEnvironment,
7 | secondsToIncrease: number
8 | ): Promise {
9 | await hre.ethers.provider.send('evm_increaseTime', [secondsToIncrease]);
10 | await hre.ethers.provider.send('evm_mine', []);
11 | }
12 |
13 | export async function setTime(hre: HardhatRuntimeEnvironment, timestamp: number): Promise {
14 | await hre.ethers.provider.send('evm_setNextBlockTimestamp', [timestamp]);
15 | }
16 |
17 | export async function evmSnapshot(hre: HardhatRuntimeEnvironment): Promise {
18 | const snapshotId = hre.ethers.provider.send('evm_snapshot', []);
19 | return snapshotId;
20 | }
21 |
22 | export async function evmRevert(hre: HardhatRuntimeEnvironment, snapshotId: string): Promise {
23 | await hre.ethers.provider.send('evm_revert', [snapshotId]);
24 | }
25 |
26 | export async function impersonateAddress(
27 | hre: HardhatRuntimeEnvironment,
28 | address: string,
29 | overrideBalance?: boolean
30 | ): Promise {
31 | if (address === '0x0000000000000000000000000000000000000000') {
32 | throw new Error("You can't impersonate 0x0 address!");
33 | }
34 | await (hre as HardhatRuntimeEnvironment).network.provider.request({
35 | method: 'hardhat_impersonateAccount',
36 | params: [address],
37 | });
38 | if (overrideBalance) {
39 | await (hre as HardhatRuntimeEnvironment).network.provider.request({
40 | method: 'hardhat_setBalance',
41 | params: [address, '0x10000000000000000000'],
42 | });
43 | }
44 | const signer = hre.ethers.provider.getSigner(address);
45 | return SignerWithAddress.create(signer);
46 | }
47 |
48 | export async function getBlockTimestamp(): Promise {
49 | return (await ethers.provider.getBlock('latest')).timestamp;
50 | }
51 |
--------------------------------------------------------------------------------
/test/utils/expectEvent.ts:
--------------------------------------------------------------------------------
1 | export const getEventArgs = (events: any, name: string) => {
2 | const event = events && events.find((e: any) => e.event === name);
3 | const args = event && event.args;
4 | return args;
5 | };
6 |
--------------------------------------------------------------------------------
/test/utils/hydra-s1-accountbound.ts:
--------------------------------------------------------------------------------
1 | import { BigNumber, BigNumberish, ethers } from 'ethers';
2 | import {
3 | ACCOUNTS_TREE_HEIGHT,
4 | buildPoseidon,
5 | KVMerkleTree,
6 | MerkleTreeData,
7 | REGISTRY_TREE_HEIGHT,
8 | SNARK_FIELD,
9 | } from '@sismo-core/hydra-s1';
10 | import { GroupData, RegistryAccountsMerkle } from 'test/utils/hydra-s1';
11 |
12 | export type HydraS1AccountboundGroup = {
13 | data: MerkleTreeData;
14 | properties: HydraS1AccountboundGroupProperties;
15 | id: string;
16 | };
17 |
18 | export type HydraS1AccountboundGroupProperties = {
19 | groupIndex: number;
20 | generationTimestamp: number;
21 | cooldownDuration: number;
22 | isScore: boolean;
23 | };
24 |
25 | export type AvailableGroupsAccountbound = {
26 | groups: HydraS1AccountboundGroup[];
27 | dataFormat: RegistryAccountsMerkle;
28 | };
29 |
30 | export type generateHydraS1AccountBoundAttesterGroups = {
31 | cooldownDuration?;
32 | generationTimestamp?;
33 | isScore?;
34 | };
35 |
36 | export const generateHydraS1AccountboundAttesterGroups = async (
37 | allList: GroupData[],
38 | options: generateHydraS1AccountBoundAttesterGroups = {
39 | cooldownDuration: 10,
40 | }
41 | ): Promise => {
42 | let poseidon = await buildPoseidon();
43 |
44 | /*********************** GENERATE GROUPS *********************/
45 |
46 | const groups: HydraS1AccountboundGroup[] = [];
47 | let generationTimestamp = options.generationTimestamp
48 | ? options.generationTimestamp
49 | : Math.round(Date.now() / 1000);
50 |
51 | for (let i = 0; i < allList.length; i++) {
52 | const properties: HydraS1AccountboundGroupProperties = {
53 | groupIndex: i,
54 | generationTimestamp,
55 | isScore: options.isScore !== undefined ? options.isScore : i % 2 == 1,
56 | cooldownDuration: options.cooldownDuration,
57 | };
58 |
59 | groups.push({
60 | data: allList[i],
61 | properties,
62 | id: generateHydraS1AccountboundGroupIdFromProperties(properties).toHexString(),
63 | });
64 | generationTimestamp++;
65 | }
66 |
67 | /************************ FORMAT DATA *********************/
68 |
69 | const accountsTrees: KVMerkleTree[] = [];
70 | const registryTreeData: MerkleTreeData = {};
71 |
72 | for (let i = 0; i < groups.length; i++) {
73 | let _accountsTree = new KVMerkleTree(groups[i].data, poseidon, ACCOUNTS_TREE_HEIGHT);
74 | accountsTrees.push(_accountsTree);
75 | registryTreeData[_accountsTree.getRoot().toHexString()] = groups[i].id;
76 | }
77 |
78 | const registryTree = new KVMerkleTree(registryTreeData, poseidon, REGISTRY_TREE_HEIGHT);
79 |
80 | return {
81 | groups,
82 | dataFormat: {
83 | accountsTrees,
84 | registryTree,
85 | },
86 | };
87 | };
88 |
89 | export const generateHydraS1AccountboundGroupIdFromProperties = (
90 | groupProperties: HydraS1AccountboundGroupProperties
91 | ): BigNumber => {
92 | return generateHydraS1AccountboundGroupIdFromEncodedProperties(
93 | encodeHydraS1AccountboundGroupProperties(groupProperties)
94 | );
95 | };
96 |
97 | export const generateHydraS1AccountboundGroupIdFromEncodedProperties = (
98 | encodedProperties: string
99 | ): BigNumber => {
100 | return BigNumber.from(ethers.utils.keccak256(encodedProperties)).mod(SNARK_FIELD);
101 | };
102 |
103 | export const encodeHydraS1AccountboundGroupProperties = (
104 | groupProperties: HydraS1AccountboundGroupProperties
105 | ): string => {
106 | return ethers.utils.defaultAbiCoder.encode(
107 | ['uint128', 'uint32', 'uint32', 'bool'],
108 | [
109 | groupProperties.groupIndex,
110 | groupProperties.generationTimestamp,
111 | groupProperties.cooldownDuration,
112 | groupProperties.isScore,
113 | ]
114 | );
115 | };
116 |
117 | export const encodeAccountBoundAttestationExtraData = ({
118 | nullifier,
119 | burnCount,
120 | }: {
121 | nullifier: BigNumberish | BigInt;
122 | burnCount: number;
123 | }) => {
124 | return ethers.utils.defaultAbiCoder.encode(
125 | ['bytes', 'uint16'],
126 | [ethers.utils.defaultAbiCoder.encode(['uint256'], [nullifier]), burnCount]
127 | );
128 | };
129 |
130 | export const getNullifierFromExtraData = (extraData: string) => {
131 | return ethers.utils.defaultAbiCoder.decode(
132 | ['uint256'],
133 | ethers.utils.defaultAbiCoder.decode(['bytes', 'uint16'], extraData)[0]
134 | );
135 | };
136 |
--------------------------------------------------------------------------------
/test/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './setup';
2 | export * from './expectEvent';
3 | export * from './evm';
4 | export * from './attestation-logic';
5 | export * from './hydra-s1';
6 | export * from './hydra-s1-accountbound';
7 |
8 |
--------------------------------------------------------------------------------
/test/utils/pythia-1.ts:
--------------------------------------------------------------------------------
1 | import {
2 | EddsaAccount,
3 | EddsaPublicKey,
4 | EddsaSignature,
5 | buildPoseidon,
6 | SNARK_FIELD,
7 | } from '@sismo-core/crypto';
8 | import { BigNumber, BigNumberish, ethers } from 'ethers';
9 |
10 | export type Pythia1Group = {
11 | properties: Pythia1GroupProperties;
12 | id: string;
13 | };
14 |
15 | export type Pythia1GroupProperties = {
16 | internalCollectionId: number;
17 | isScore: boolean;
18 | };
19 |
20 | export const generatePythia1Group = ({ internalCollectionId, isScore }): Pythia1Group => {
21 | const properties: Pythia1GroupProperties = {
22 | internalCollectionId,
23 | isScore,
24 | };
25 |
26 | return {
27 | id: generatePythia1GroupIdFromProperties(properties).toHexString(),
28 | properties,
29 | };
30 | };
31 |
32 | export const computeNullifier = async (
33 | secret: BigNumberish,
34 | externalNullifier: BigNumberish
35 | ): Promise => {
36 | const poseidon = await buildPoseidon();
37 | return poseidon([secret, externalNullifier]);
38 | };
39 |
40 | export class CommitmentSignerTester {
41 | private seed: BigNumberish;
42 |
43 | constructor(seed: BigNumberish = '0x123321') {
44 | this.seed = seed;
45 | }
46 |
47 | async getCommitmentReceipt(
48 | commitment: BigNumberish,
49 | value: BigNumberish,
50 | groupId: BigNumberish
51 | ): Promise {
52 | const poseidon = await buildPoseidon();
53 | return (await this._getEddsaAccount()).sign(poseidon([commitment, value, groupId]));
54 | }
55 |
56 | async getPublicKey(): Promise {
57 | return (await this._getEddsaAccount()).getPubKey();
58 | }
59 |
60 | private async _getEddsaAccount(): Promise {
61 | const eddsaAccount = await EddsaAccount.generateFromSeed(this.seed);
62 | return eddsaAccount;
63 | }
64 | }
65 |
66 | export const generatePythia1GroupIdFromProperties = (
67 | groupProperties: Pythia1GroupProperties
68 | ): BigNumber => {
69 | return generatePythia1GroupIdFromEncodedProperties(encodePythia1GroupProperties(groupProperties));
70 | };
71 |
72 | export const generatePythia1GroupIdFromEncodedProperties = (
73 | encodedProperties: string
74 | ): BigNumber => {
75 | return BigNumber.from(ethers.utils.keccak256(encodedProperties)).mod(SNARK_FIELD);
76 | };
77 |
78 | export const encodePythia1GroupProperties = (groupProperties: Pythia1GroupProperties): string => {
79 | return ethers.utils.defaultAbiCoder.encode(
80 | ['uint128', 'bool'],
81 | [groupProperties.internalCollectionId, groupProperties.isScore]
82 | );
83 | };
84 |
--------------------------------------------------------------------------------
/test/utils/setup.ts:
--------------------------------------------------------------------------------
1 | import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
2 | import { BigNumber } from 'ethers';
3 | import { EddsaSignature, Poseidon } from '@sismo-core/hydra-s1';
4 | import { CommitmentMapperTester, getOwnershipMsg } from '@sismo-core/commitment-mapper-tester-js';
5 |
6 | export async function getMockedAccounts(
7 | signers: SignerWithAddress[],
8 | commitmentMapper: CommitmentMapperTester,
9 | poseidon: Poseidon
10 | ): Promise {
11 | const hydraS1Accounts: HydraS1MockedAccount[] = [];
12 | let i = 0;
13 | for (const signer of signers) {
14 | const signature = await signer.signMessage(getOwnershipMsg(signer.address));
15 | const secret = BigNumber.from(signer.address);
16 | const group1Value = i;
17 | const group2Value = 20000 - i;
18 | const group3Value = 40000 - group2Value;
19 | const commitment = poseidon([secret]).toHexString();
20 | const { commitmentReceipt } = await commitmentMapper.commit(
21 | signer.address,
22 | signature,
23 | commitment
24 | );
25 | hydraS1Accounts.push({
26 | signer,
27 | secret,
28 | commitmentReceipt,
29 | group1Value,
30 | group2Value,
31 | group3Value,
32 | });
33 | i++;
34 | }
35 | return hydraS1Accounts;
36 | }
37 |
38 | export type HydraS1MockedAccount = {
39 | signer: SignerWithAddress;
40 | secret: BigNumber;
41 | commitmentReceipt: EddsaSignature;
42 | group1Value: number;
43 | group2Value: number;
44 | group3Value: number;
45 | };
46 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2018",
4 | "module": "commonjs",
5 | "strict": true,
6 | "esModuleInterop": true,
7 | "declaration": true,
8 | "resolveJsonModule": true,
9 | "baseUrl": "./",
10 | "noImplicitAny": false
11 | },
12 | "include": ["./scripts", "./tasks", "./test", "./common"],
13 | "exclude": ["node_modules", "./types"],
14 | "files": ["./hardhat.config.ts"]
15 | }
--------------------------------------------------------------------------------
/utils/constants.ts:
--------------------------------------------------------------------------------
1 | import { ethers, BytesLike } from 'ethers';
2 | import { toUtf8Bytes } from 'ethers/lib/utils';
3 |
4 | export const EVENT_TRIGGERER_ROLE: BytesLike = ethers.utils.keccak256(
5 | toUtf8Bytes('EVENT_TRIGGERER_ROLE')
6 | );
7 |
--------------------------------------------------------------------------------
/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './constants';
2 | export * from './proxy';
3 |
--------------------------------------------------------------------------------
/utils/proxy.ts:
--------------------------------------------------------------------------------
1 | import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
2 | import { BaseContract, utils } from 'ethers';
3 |
4 | export const IMPLEMENTATION_SLOT: string =
5 | '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc';
6 |
7 | export const getImplementation = async (proxyContract: BaseContract): Promise => {
8 | return utils.defaultAbiCoder.decode(
9 | ['address'],
10 | (await proxyContract.provider?.getStorageAt(proxyContract.address, IMPLEMENTATION_SLOT)) || ''
11 | )[0];
12 | };
13 |
--------------------------------------------------------------------------------
/utils/singletonFactory.ts:
--------------------------------------------------------------------------------
1 | export const singletonFactory = {
2 | // mainnet
3 | 1: {
4 | gasPrice: 100000000000,
5 | gasLimit: 100000,
6 | signerAddress: '0xBa68986f673c9193BB79eA0d21990225d464bb5C',
7 | transaction:
8 | '0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf326a0b807b1020a20449a1d962455d100c13cea90fe72dd21c1abca7a9680c23de3ffa0725dfea391175a966ee02c6ba78a42519040bb9caef32b91522097d2601e9c00',
9 | address: '0xC4c11B14e9D876B031c1c7e05efE44088341f35B',
10 | },
11 | // goerli
12 | 5: {
13 | gasPrice: 100000000000,
14 | gasLimit: 100000,
15 | signerAddress: '0xBa68986f673c9193BB79eA0d21990225d464bb5C',
16 | transaction:
17 | '0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf32ea0bf23472b7c27cefcbfaf2241930df7a61e0e52f7e2af414c071d3cc6d92874a8a04d4315d5e555f794ef107a68765de376b83ee697658b7dacd578b2ec5f721183',
18 | address: '0xC4c11B14e9D876B031c1c7e05efE44088341f35B',
19 | },
20 | // polygon
21 | 137: {
22 | gasPrice: 100000000000,
23 | gasLimit: 100000,
24 | signerAddress: '0xBa68986f673c9193BB79eA0d21990225d464bb5C',
25 | transaction:
26 | '0xf8a78085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3820135a084ea92419a30b2851e105567772f3346d4ee23ab63a733f82c13a424604cbfdaa06716488c485f03825d5b5b52d982f130199767319e11453d7cacc5053818c23b',
27 | address: '0xC4c11B14e9D876B031c1c7e05efE44088341f35B',
28 | },
29 | // local
30 | 31337: {
31 | gasPrice: 100000000000,
32 | gasLimit: 100000,
33 | signerAddress: '0xBa68986f673c9193BB79eA0d21990225d464bb5C',
34 | transaction:
35 | '0xf8a78085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf382f4f5a019264dff42982fbff5b815e16a83fff4524568dd0e23a09c4d37cd86e6890f71a07db39e99070faa25eb46904f812cb12feadddf186e58a69ce7688b04a9ee2a0a',
36 | address: '0xC4c11B14e9D876B031c1c7e05efE44088341f35B',
37 | },
38 | // mumbai
39 | 80001: {
40 | gasPrice: 100000000000,
41 | gasLimit: 100000,
42 | signerAddress: '0xBa68986f673c9193BB79eA0d21990225d464bb5C',
43 | transaction:
44 | '0xf8a88085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf383027126a0b23aa3a7cf3654c8f2dc3ce3c6d37ff504a726085f835a9f4d32d61e865e261ea017add99e70915725b41244e4feefc854f5c17da90f4e1ac6fb994040ae5af242',
45 | address: '0xC4c11B14e9D876B031c1c7e05efE44088341f35B',
46 | },
47 | };
48 |
--------------------------------------------------------------------------------