From 4ae1641532edd5c601dd46f53e59a3def2e88574 Mon Sep 17 00:00:00 2001 From: Maksim Date: Thu, 4 Apr 2024 14:41:00 +0200 Subject: [PATCH] remove chainId and update git workflow --- .github/workflows/push.yml | 6 +- package.json | 1 - test/{ => erc4626}/vault.test.ts | 4 +- .../claim-issuers/claim-issuer.test.ts | 89 -- test/onchainid/factory/factory.test.ts | 162 ---- test/onchainid/factory/token-oid.test.ts | 75 -- test/onchainid/fixtures.ts | 102 --- test/onchainid/gateway/gateway.test.ts | 831 ------------------ test/onchainid/identities/claims.test.ts | 357 -------- test/onchainid/identities/executions.test.ts | 259 ------ test/onchainid/identities/init.test.ts | 42 - test/onchainid/identities/keys.test.ts | 180 ---- test/onchainid/proxy.test.ts | 65 -- .../onchainid/verifiers/verifier-user.test.ts | 107 --- test/onchainid/verifiers/verifier.test.ts | 523 ----------- yarn.lock | 36 +- 16 files changed, 10 insertions(+), 2829 deletions(-) rename test/{ => erc4626}/vault.test.ts (97%) delete mode 100644 test/onchainid/claim-issuers/claim-issuer.test.ts delete mode 100644 test/onchainid/factory/factory.test.ts delete mode 100644 test/onchainid/factory/token-oid.test.ts delete mode 100644 test/onchainid/fixtures.ts delete mode 100644 test/onchainid/gateway/gateway.test.ts delete mode 100644 test/onchainid/identities/claims.test.ts delete mode 100644 test/onchainid/identities/executions.test.ts delete mode 100644 test/onchainid/identities/init.test.ts delete mode 100644 test/onchainid/identities/keys.test.ts delete mode 100644 test/onchainid/proxy.test.ts delete mode 100644 test/onchainid/verifiers/verifier-user.test.ts delete mode 100644 test/onchainid/verifiers/verifier.test.ts diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 45e084d..286e1b5 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -34,4 +34,8 @@ jobs: run: yarn run compile - name: Run Tests - run: yarn hardhat test --network testnet + run: yarn hardhat test test/erc3643/**/**.ts --network hardhat + + -name: Run HTS Tests + run: yarn hardhat test test/erc4626/**.ts --network testnet + diff --git a/package.json b/package.json index 3ddb4d1..29e6e1d 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ }, "dependencies": { "@hashgraph/hedera-local": "^2.19.1", - "@onchain-id/solidity": "^2.0.0", "@openzeppelin/contracts": "^4.8.3", "@openzeppelin/contracts-upgradeable": "^4.8.3" } diff --git a/test/vault.test.ts b/test/erc4626/vault.test.ts similarity index 97% rename from test/vault.test.ts rename to test/erc4626/vault.test.ts index 5f9c01c..a89631c 100644 --- a/test/vault.test.ts +++ b/test/erc4626/vault.test.ts @@ -1,5 +1,5 @@ -import { anyValue, ethers, expect } from "./setup"; -import { TokenTransfer, createFungibleToken, TokenBalance, createAccount, addToken, mintToken } from "../scripts/utils"; +import { anyValue, ethers, expect } from "../setup"; +import { TokenTransfer, createFungibleToken, TokenBalance, createAccount, addToken, mintToken } from "../../scripts/utils"; import { PrivateKey, Client, AccountId, TokenAssociateTransaction, AccountBalanceQuery } from "@hashgraph/sdk"; // constants diff --git a/test/onchainid/claim-issuers/claim-issuer.test.ts b/test/onchainid/claim-issuers/claim-issuer.test.ts deleted file mode 100644 index 3a3aaf8..0000000 --- a/test/onchainid/claim-issuers/claim-issuer.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { expect } from "chai"; -import {ethers} from "hardhat"; -import {deployIdentityFixture} from "../fixtures"; -import { AbiCoder } from 'ethers'; - -describe('ClaimIssuer - Reference (with revoke)', () => { - describe('revokeClaim (deprecated)', () => { - describe('when calling as a non MANAGEMENT key', () => { - it('should revert for missing permissions', async () => { - const { claimIssuer, aliceWallet, aliceClaim666 } = await loadFixture(deployIdentityFixture); - - await expect(claimIssuer.connect(aliceWallet).revokeClaim(aliceClaim666.id, aliceClaim666.identity)).to.be.revertedWith('Permissions: Sender does not have management key'); - }); - }); - - describe("when calling as a MANAGEMENT key", () => { - describe('when claim was already revoked', () => { - it('should revert for conflict', async () => { - const { claimIssuer, claimIssuerWallet, aliceClaim666 } = await loadFixture(deployIdentityFixture); - - await claimIssuer.connect(claimIssuerWallet).revokeClaim(aliceClaim666.id, aliceClaim666.identity); - - await expect(claimIssuer.connect(claimIssuerWallet).revokeClaim(aliceClaim666.id, aliceClaim666.identity)).to.be.revertedWith('Conflict: Claim already revoked'); - }); - }); - - describe('when is not revoked already', () => { - it('should revoke the claim', async () => { - const { claimIssuer, claimIssuerWallet, aliceClaim666 } = await loadFixture(deployIdentityFixture); - - expect(await claimIssuer.isClaimValid(aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.signature, aliceClaim666.data)).to.be.true; - - const tx = await claimIssuer.connect(claimIssuerWallet).revokeClaim(aliceClaim666.id, aliceClaim666.identity); - - await expect(tx).to.emit(claimIssuer, 'ClaimRevoked').withArgs(aliceClaim666.signature); - - expect(await claimIssuer.isClaimRevoked(aliceClaim666.signature)).to.be.true; - expect(await claimIssuer.isClaimValid(aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.signature, aliceClaim666.data)).to.be.false; - }); - }); - }); - }); - - describe('revokeClaimBySignature', () => { - describe('when calling as a non MANAGEMENT key', () => { - it('should revert for missing permissions', async () => { - const { claimIssuer, aliceWallet, aliceClaim666 } = await loadFixture(deployIdentityFixture); - - await expect(claimIssuer.connect(aliceWallet).revokeClaimBySignature(aliceClaim666.signature)).to.be.revertedWith('Permissions: Sender does not have management key'); - }); - }); - - describe("when calling as a MANAGEMENT key", () => { - describe('when claim was already revoked', () => { - it('should revert for conflict', async () => { - const { claimIssuer, claimIssuerWallet, aliceClaim666 } = await loadFixture(deployIdentityFixture); - - await claimIssuer.connect(claimIssuerWallet).revokeClaimBySignature(aliceClaim666.signature); - - await expect(claimIssuer.connect(claimIssuerWallet).revokeClaimBySignature(aliceClaim666.signature)).to.be.revertedWith('Conflict: Claim already revoked'); - }); - }); - - describe('when is not revoked already', () => { - it('should revoke the claim', async () => { - const { claimIssuer, claimIssuerWallet, aliceClaim666 } = await loadFixture(deployIdentityFixture); - - expect(await claimIssuer.isClaimValid(aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.signature, aliceClaim666.data)).to.be.true; - - const tx = await claimIssuer.connect(claimIssuerWallet).revokeClaimBySignature(aliceClaim666.signature); - - await expect(tx).to.emit(claimIssuer, 'ClaimRevoked').withArgs(aliceClaim666.signature); - - expect(await claimIssuer.isClaimRevoked(aliceClaim666.signature)).to.be.true; - expect(await claimIssuer.isClaimValid(aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.signature, aliceClaim666.data)).to.be.false; - }); - }); - }); - }); - - describe('getRecoveredAddress', () => { - it('should return with a zero address with signature is not of proper length', async () => { - const { claimIssuer, aliceClaim666 } = await loadFixture(deployIdentityFixture); - - expect(await claimIssuer.getRecoveredAddress(aliceClaim666.signature + "00", ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.data]))))).to.be.equal(ethers.ZeroAddress); - }); - }); -}); diff --git a/test/onchainid/factory/factory.test.ts b/test/onchainid/factory/factory.test.ts deleted file mode 100644 index 9cc41ee..0000000 --- a/test/onchainid/factory/factory.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -import {expect} from "chai"; -import {ethers} from "hardhat"; -import {loadFixture} from "@nomicfoundation/hardhat-network-helpers"; -import { AbiCoder } from 'ethers'; - -import {deployIdentityFixture} from "../fixtures"; - -describe('IdFactory', () => { - it('should revert because authority is Zero address', async () => { - const [deployerWallet] = await ethers.getSigners(); - - const IdFactory = await ethers.getContractFactory('IdFactory'); - await expect(IdFactory.connect(deployerWallet).deploy(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should revert because sender is not allowed to create identities', async () => { - const {identityFactory, aliceWallet} = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(aliceWallet).createIdentity(ethers.ZeroAddress, 'salt1')).to.be.revertedWith('Ownable: caller is not the owner'); - }); - - it('should revert because wallet of identity cannot be Zero address', async () => { - const {identityFactory, deployerWallet} = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(deployerWallet).createIdentity(ethers.ZeroAddress, 'salt1')).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should revert because salt cannot be empty', async () => { - const {identityFactory, deployerWallet, davidWallet} = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(deployerWallet).createIdentity(davidWallet.address, '')).to.be.revertedWith('invalid argument - empty string'); - }); - - it('should revert because salt cannot be already used', async () => { - const {identityFactory, deployerWallet, davidWallet, carolWallet} = await loadFixture(deployIdentityFixture); - - await identityFactory.connect(deployerWallet).createIdentity(carolWallet.address, 'saltUsed'); - - await expect(identityFactory.connect(deployerWallet).createIdentity(davidWallet.address, 'saltUsed')).to.be.revertedWith('salt already taken'); - }); - - it('should revert because wallet is already linked to an identity', async () => { - const {identityFactory, deployerWallet, aliceWallet} = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(deployerWallet).createIdentity(aliceWallet.address, 'newSalt')).to.be.revertedWith('wallet already linked to an identity'); - }); - - describe('link/unlink wallet', () => { - describe('linkWallet', () => { - it('should revert for new wallet being zero address', async () => { - const { identityFactory, aliceWallet } = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(aliceWallet).linkWallet(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should revert for sender wallet being not linked', async () => { - const { identityFactory, davidWallet } = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(davidWallet).linkWallet(davidWallet.address)).to.be.revertedWith('wallet not linked to an identity contract'); - }); - - it('should revert for new wallet being already linked', async () => { - const { identityFactory, bobWallet, aliceWallet } = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(bobWallet).linkWallet(aliceWallet.address)).to.be.revertedWith('new wallet already linked'); - }); - - it('should revert for new wallet being already to a token identity', async () => { - const { identityFactory, bobWallet, tokenAddress } = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(bobWallet).linkWallet(tokenAddress)).to.be.revertedWith('invalid argument - token address'); - }); - - it('should link the new wallet to the existing identity', async () => { - const { identityFactory, aliceIdentity, aliceWallet, davidWallet } = await loadFixture(deployIdentityFixture); - - const tx = await identityFactory.connect(aliceWallet).linkWallet(davidWallet.address); - await expect(tx).to.emit(identityFactory, 'WalletLinked').withArgs(davidWallet.address, await aliceIdentity.getAddress()); - - expect(await identityFactory.getWallets(await aliceIdentity.getAddress())).to.deep.equal([aliceWallet.address, davidWallet.address]); - }); - }); - - describe('unlinkWallet', () => { - it('should revert for wallet to unlink being zero address', async () => { - const { identityFactory, aliceWallet } = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(aliceWallet).unlinkWallet(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should revert for sender wallet attemoting to unlink itself', async () => { - const { identityFactory, aliceWallet } = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(aliceWallet).unlinkWallet(aliceWallet.address)).to.be.revertedWith('cannot be called on sender address'); - }); - - it('should revert for sender wallet being not linked', async () => { - const { identityFactory, aliceWallet, davidWallet } = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(davidWallet).unlinkWallet(aliceWallet.address)).to.be.revertedWith('only a linked wallet can unlink'); - }); - - it('should unlink the wallet', async () => { - const { identityFactory, aliceIdentity, aliceWallet, davidWallet } = await loadFixture(deployIdentityFixture); - - await identityFactory.connect(aliceWallet).linkWallet(davidWallet.address); - const tx = await identityFactory.connect(aliceWallet).unlinkWallet(davidWallet.address); - await expect(tx).to.emit(identityFactory, 'WalletUnlinked').withArgs(davidWallet.address, await aliceIdentity.getAddress()); - - expect(await identityFactory.getWallets(await aliceIdentity.getAddress())).to.deep.equal([aliceWallet.address]); - }); - }); - }); - - describe('createIdentityWithManagementKeys()', () => { - describe('when no management keys are provided', () => { - it('should revert', async () => { - const {identityFactory, deployerWallet, davidWallet} = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(deployerWallet).createIdentityWithManagementKeys(davidWallet.address, 'salt1', [])).to.be.revertedWith('invalid argument - empty list of keys'); - }); - }); - - describe('when the wallet is included in the management keys listed', () => { - it('should revert', async () => { - const {identityFactory, deployerWallet, aliceWallet, davidWallet} = await loadFixture(deployIdentityFixture); - - await expect(identityFactory.connect(deployerWallet).createIdentityWithManagementKeys(davidWallet.address, 'salt1', [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address])), - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [davidWallet.address])), - ])).to.be.revertedWith('invalid argument - wallet is also listed in management keys'); - }); - }); - - describe('when other management keys are specified', () => { - it('should deploy the identity proxy, set keys and wallet as management, and link wallet to identity', async () => { - const {identityFactory, deployerWallet, aliceWallet, davidWallet} = await loadFixture(deployIdentityFixture); - - const tx = await identityFactory.connect(deployerWallet).createIdentityWithManagementKeys(davidWallet.address, 'salt1', [ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]))]); - - await expect(tx).to.emit(identityFactory, 'WalletLinked'); - await expect(tx).to.emit(identityFactory, 'Deployed'); - - const identity = await ethers.getContractAt('Identity', await identityFactory.getIdentity(davidWallet.address)); - - await expect(tx).to.emit(identity, 'KeyAdded').withArgs(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address])), 1, 1); - await expect(identity.keyHasPurpose( - AbiCoder.defaultAbiCoder().encode(['address'], [await identityFactory.getAddress()]), - 1 - )).to.eventually.be.false; - await expect(identity.keyHasPurpose( - AbiCoder.defaultAbiCoder().encode(['address'], [davidWallet.address]), - 1 - )).to.eventually.be.false; - await expect(identity.keyHasPurpose( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]), - 1 - )).to.eventually.be.false; - }); - }); - }); -}); diff --git a/test/onchainid/factory/token-oid.test.ts b/test/onchainid/factory/token-oid.test.ts deleted file mode 100644 index da497b5..0000000 --- a/test/onchainid/factory/token-oid.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { expect } from "chai"; -import {ethers} from "hardhat"; - -import {deployFactoryFixture, deployIdentityFixture} from "../fixtures"; - -describe('IdFactory', () => { - describe('add/remove Token factory', () => { - it('should manipulate Token factory list', async () => { - const { identityFactory, deployerWallet, aliceWallet, bobWallet } = await loadFixture(deployFactoryFixture); - - await expect(identityFactory.connect(aliceWallet).addTokenFactory(aliceWallet.address)).to.be.revertedWith('Ownable: caller is not the owner'); - - await expect(identityFactory.connect(deployerWallet).addTokenFactory(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); - - const addTx = await identityFactory.connect(deployerWallet).addTokenFactory(aliceWallet.address); - await expect(addTx).to.emit(identityFactory, 'TokenFactoryAdded').withArgs(aliceWallet.address); - - await expect(identityFactory.connect(deployerWallet).addTokenFactory(aliceWallet.address)).to.be.revertedWith('already a factory'); - - await expect(identityFactory.connect(aliceWallet).removeTokenFactory(bobWallet.address)).to.be.revertedWith('Ownable: caller is not the owner'); - - await expect(identityFactory.connect(deployerWallet).removeTokenFactory(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); - - await expect(identityFactory.connect(deployerWallet).removeTokenFactory(bobWallet.address)).to.be.revertedWith('not a factory'); - - const removeTx = await identityFactory.connect(deployerWallet).removeTokenFactory(aliceWallet.address); - await expect(removeTx).to.emit(identityFactory, 'TokenFactoryRemoved').withArgs(aliceWallet.address); - }); - }); - - describe('createTokenIdentity', () => { - it('should revert for being not authorized to deploy token', async () => { - const { identityFactory, aliceWallet } = await loadFixture(deployFactoryFixture); - - await expect(identityFactory.connect(aliceWallet).createTokenIdentity(aliceWallet.address, aliceWallet.address, 'TST')).to.be.revertedWith('only Factory or owner can call'); - }); - - it('should revert for token address being zero address', async () => { - const { identityFactory, deployerWallet, aliceWallet } = await loadFixture(deployFactoryFixture); - - await expect(identityFactory.connect(deployerWallet).createTokenIdentity(ethers.ZeroAddress, aliceWallet.address, 'TST')).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should revert for owner being zero address', async () => { - const { identityFactory, deployerWallet, aliceWallet } = await loadFixture(deployFactoryFixture); - - await expect(identityFactory.connect(deployerWallet).createTokenIdentity(aliceWallet.address, ethers.ZeroAddress, 'TST')).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should revert for salt being empty', async () => { - const { identityFactory, deployerWallet, aliceWallet } = await loadFixture(deployFactoryFixture); - - await expect(identityFactory.connect(deployerWallet).createTokenIdentity(aliceWallet.address, aliceWallet.address, '')).to.be.revertedWith('invalid argument - empty string'); - }); - - it('should create one identity and then revert for salt/address being already used', async () => { - const { identityFactory, deployerWallet, aliceWallet, bobWallet } = await loadFixture(deployFactoryFixture); - - expect(await identityFactory.isSaltTaken('Tokensalt1')).to.be.false; - - const tx = await identityFactory.connect(deployerWallet).createTokenIdentity(aliceWallet.address, bobWallet.address, 'salt1'); - const tokenIdentityAddress = await identityFactory.getIdentity(aliceWallet.address); - await expect(tx).to.emit(identityFactory, 'TokenLinked').withArgs(aliceWallet.address, tokenIdentityAddress); - await expect(tx).to.emit(identityFactory, 'Deployed').withArgs(tokenIdentityAddress); - - expect(await identityFactory.isSaltTaken('Tokensalt1')).to.be.true; - expect(await identityFactory.isSaltTaken('Tokensalt2')).to.be.false; - expect(await identityFactory.getToken(tokenIdentityAddress)).to.deep.equal(aliceWallet.address); - - await expect(identityFactory.connect(deployerWallet).createTokenIdentity(aliceWallet.address, aliceWallet.address, 'salt1')).to.be.revertedWith('salt already taken'); - await expect(identityFactory.connect(deployerWallet).createTokenIdentity(aliceWallet.address, aliceWallet.address, 'salt2')).to.be.revertedWith('token already linked to an identity'); - }); - }); -}); diff --git a/test/onchainid/fixtures.ts b/test/onchainid/fixtures.ts deleted file mode 100644 index 2031c85..0000000 --- a/test/onchainid/fixtures.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { ethers } from 'hardhat'; -import { AbiCoder } from 'ethers'; - -export async function deployFactoryFixture() { - const [deployerWallet, claimIssuerWallet, aliceWallet, bobWallet, carolWallet, davidWallet] = - await ethers.getSigners(); - - const Identity = await ethers.getContractFactory('Identity'); - const identityImplementation = await Identity.connect(deployerWallet).deploy(deployerWallet.address, true); - - const ImplementationAuthority = await ethers.getContractFactory( - 'ImplementationAuthority' - ); - const implementationAuthority = await ImplementationAuthority.connect(deployerWallet).deploy( - await identityImplementation.getAddress(), - ); - - const IdentityFactory = await ethers.getContractFactory('IdFactory'); - const identityFactory = await IdentityFactory.connect(deployerWallet).deploy( - await implementationAuthority.getAddress(), - ); - - return { - identityFactory, - identityImplementation, - implementationAuthority, - aliceWallet, - bobWallet, - carolWallet, - davidWallet, - deployerWallet, - claimIssuerWallet, - }; -} - -export async function deployIdentityFixture() { - const [deployerWallet, claimIssuerWallet, aliceWallet, bobWallet, carolWallet, davidWallet, tokenOwnerWallet] = - await ethers.getSigners(); - - const { identityFactory, identityImplementation, implementationAuthority } = await deployFactoryFixture(); - - const ClaimIssuer = await ethers.getContractFactory('ClaimIssuer'); - const claimIssuer = await ClaimIssuer.connect(claimIssuerWallet).deploy(claimIssuerWallet.address); - await claimIssuer.connect(claimIssuerWallet).addKey( - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [claimIssuerWallet.address]), - ), - 3, - 1, - ); - - await identityFactory.connect(deployerWallet).createIdentity(aliceWallet.address, 'alice'); - const aliceIdentity = await ethers.getContractAt('Identity', await identityFactory.getIdentity(aliceWallet.address)); - await aliceIdentity.connect(aliceWallet).addKey(ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [carolWallet.address]) - ), 3, 1); - await aliceIdentity.connect(aliceWallet).addKey(ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [davidWallet.address]) - ), 2, 1); - const aliceClaim666 = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 666, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - aliceClaim666.id = ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [aliceClaim666.issuer, aliceClaim666.topic])); - aliceClaim666.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.data])))); - - await aliceIdentity.connect(aliceWallet).addClaim(aliceClaim666.topic, aliceClaim666.scheme, aliceClaim666.issuer, aliceClaim666.signature, aliceClaim666.data, aliceClaim666.uri); - - await identityFactory.connect(deployerWallet).createIdentity(bobWallet.address, 'bob'); - const bobIdentity = await ethers.getContractAt('Identity', await identityFactory.getIdentity(bobWallet.address)); - - const tokenAddress = '0xdEE019486810C7C620f6098EEcacA0244b0fa3fB'; - await identityFactory.connect(deployerWallet).createTokenIdentity(tokenAddress, tokenOwnerWallet.address, 'tokenOwner'); - - return { - identityFactory, - identityImplementation, - implementationAuthority, - claimIssuer, - aliceWallet, - bobWallet, - carolWallet, - davidWallet, - deployerWallet, - claimIssuerWallet, - tokenOwnerWallet, - aliceIdentity, - bobIdentity, - aliceClaim666, - tokenAddress - }; -} - -export async function deployVerifierFixture() { - -} diff --git a/test/onchainid/gateway/gateway.test.ts b/test/onchainid/gateway/gateway.test.ts deleted file mode 100644 index c2bf669..0000000 --- a/test/onchainid/gateway/gateway.test.ts +++ /dev/null @@ -1,831 +0,0 @@ -import {ethers} from "hardhat"; -import {expect} from "chai"; -import {loadFixture} from "@nomicfoundation/hardhat-network-helpers"; -import {deployFactoryFixture} from "../fixtures"; -import { AbiCoder } from 'ethers'; - -describe('Gateway', () => { - describe('constructor', () => { - describe('when factory address is not specified', () => { - it('should revert', async () => { - await expect(ethers.deployContract('Gateway', [ethers.ZeroAddress, []])).to.be.reverted; - }); - }); - - describe('when specifying more than 10 signer', () => { - it('should revert', async () => { - const {identityFactory, carolWallet} = await loadFixture(deployFactoryFixture); - await expect(ethers.deployContract('Gateway', [await identityFactory.getAddress(), Array(11).fill(ethers.ZeroAddress)])).to.be.reverted; - }); - }); - }); - - describe('.deployIdentityWithSalt()', () => { - describe('when input address is the zero address', () => { - it('should revert', async () => { - const {identityFactory, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - - await expect(gateway.deployIdentityWithSalt(ethers.ZeroAddress, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60), ethers.randomBytes(65))).to.be.reverted; - }); - }); - - describe('when signature is not valid', () => { - it('should revert with UnsignedDeployment', async () => { - const {identityFactory, aliceWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - - await expect(gateway.deployIdentityWithSalt(aliceWallet.address, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60), ethers.randomBytes(65))).to.be.reverted; - }); - }); - - describe('when signature is signed by a non authorized signer', () => { - it('should revert with UnsignedDeployment', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - - await expect( - gateway.deployIdentityWithSalt( - aliceWallet.address, - 'saltToUse', - BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60), - await bobWallet.signMessage( - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['string', 'address', 'string', 'uint256'], ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60)])), - ), - ), - ).to.be.revertedWithCustomError(gateway, 'UnapprovedSigner'); - }); - }); - - describe('when signature is correct and signed by an authorized signer', () => { - it('should deploy the identity', async () => { - const {identityFactory, aliceWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - const tx = await gateway.deployIdentityWithSalt( - aliceWallet.address, - 'saltToUse', - BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60), - signature, - ); - await expect(tx).to.emit(identityFactory, "WalletLinked").withArgs(aliceWallet.address, await identityFactory.getIdentity(aliceWallet.address)); - await expect(tx).to.emit(identityFactory, "Deployed").withArgs(await identityFactory.getIdentity(aliceWallet.address)); - const identityAddress = await identityFactory.getIdentity(aliceWallet.address); - const identity = await ethers.getContractAt('Identity', identityAddress); - expect(await identity.keyHasPurpose(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address])), 1)).to.be.true; - }); - }); - - describe('when signature is correct with no expiry', () => { - it('should deploy the identity', async () => { - const {identityFactory, aliceWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', 0], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - const tx = await gateway.deployIdentityWithSalt( - aliceWallet.address, - 'saltToUse', - 0, - signature, - ); - await expect(tx).to.emit(identityFactory, "WalletLinked").withArgs(aliceWallet.address, await identityFactory.getIdentity(aliceWallet.address)); - await expect(tx).to.emit(identityFactory, "Deployed").withArgs(await identityFactory.getIdentity(aliceWallet.address)); - const identityAddress = await identityFactory.getIdentity(aliceWallet.address); - const identity = await ethers.getContractAt('Identity', identityAddress); - expect(await identity.keyHasPurpose(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address])), 1)).to.be.true; - }); - }); - - describe('when signature is correct and signed by an authorized signer, but revoked', () => { - it('should revert', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - await gateway.revokeSignature(signature); - - await expect(gateway.deployIdentityWithSalt( - aliceWallet.address, - 'saltToUse', - BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60), - signature, - )).to.be.revertedWithCustomError(gateway, 'RevokedSignature'); - }); - }); - - describe('when signature is correct and signed by an authorized signer, but has expired', () => { - it('should revert', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) - BigInt(2 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - await gateway.revokeSignature(signature); - - await expect(gateway.deployIdentityWithSalt( - aliceWallet.address, - 'saltToUse', - BigInt(new Date().getTime()) / BigInt(1000) - BigInt(2 * 24 * 60 * 60), - signature, - )).to.be.revertedWithCustomError(gateway, 'ExpiredSignature'); - }); - }); - }); - - describe('.deployIdentityWithSaltAndManagementKeys', () => { - describe('when input address is the zero address', () => { - it('should revert', async () => { - const {identityFactory, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - - await expect(gateway.deployIdentityWithSaltAndManagementKeys(ethers.ZeroAddress, 'saltToUse', [], BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60), ethers.randomBytes(65))).to.be.reverted; - }); - }); - - describe('when signature is not valid', () => { - it('should revert with UnsignedDeployment', async () => { - const {identityFactory, aliceWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - - await expect(gateway.deployIdentityWithSaltAndManagementKeys(aliceWallet.address, 'saltToUse', [], BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60), ethers.randomBytes(65))).to.be.reverted; - }); - }); - - describe('when signature is signed by a non authorized signer', () => { - it('should revert with UnsignedDeployment', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - - await expect( - gateway.deployIdentityWithSaltAndManagementKeys( - aliceWallet.address, - 'saltToUse', - [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), - ], - BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60), - await bobWallet.signMessage( - ethers.keccak256(AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'bytes32[]', 'uint256'], - [ - 'Authorize ONCHAINID deployment', - aliceWallet.address, - 'saltToUse', - [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), - ], - BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60) - ], - )), - ), - ), - ).to.be.revertedWithCustomError(gateway, 'UnapprovedSigner'); - }); - }); - - describe('when signature is correct and signed by an authorized signer', () => { - it('should deploy the identity', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'bytes32[]', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), - ], BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - const tx = await gateway.deployIdentityWithSaltAndManagementKeys( - aliceWallet.address, - 'saltToUse', - [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), - ], - BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60), - signature, - ); - await expect(tx).to.emit(identityFactory, "WalletLinked").withArgs(aliceWallet.address, await identityFactory.getIdentity(aliceWallet.address)); - await expect(tx).to.emit(identityFactory, "Deployed").withArgs(await identityFactory.getIdentity(aliceWallet.address)); - const identityAddress = await identityFactory.getIdentity(aliceWallet.address); - const identity = await ethers.getContractAt('Identity', identityAddress); - expect(await identity.keyHasPurpose(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address])), 1)).to.be.false; - expect(await identity.keyHasPurpose(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), 1)).to.be.true; - }); - }); - - describe('when signature is correct with no expiry', () => { - it('should deploy the identity', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'bytes32[]', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), - ], 0], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - const tx = await gateway.deployIdentityWithSaltAndManagementKeys( - aliceWallet.address, - 'saltToUse', - [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), - ], - 0, - signature, - ); - await expect(tx).to.emit(identityFactory, "WalletLinked").withArgs(aliceWallet.address, await identityFactory.getIdentity(aliceWallet.address)); - await expect(tx).to.emit(identityFactory, "Deployed").withArgs(await identityFactory.getIdentity(aliceWallet.address)); - const identityAddress = await identityFactory.getIdentity(aliceWallet.address); - const identity = await ethers.getContractAt('Identity', identityAddress); - expect(await identity.keyHasPurpose(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address])), 1)).to.be.false; - expect(await identity.keyHasPurpose(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), 1)).to.be.true; - }); - }); - - describe('when signature is correct and signed by an authorized signer, but revoked', () => { - it('should revert', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'bytes32[]', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), - ], BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - await gateway.revokeSignature(signature); - - await expect(gateway.deployIdentityWithSaltAndManagementKeys( - aliceWallet.address, - 'saltToUse', - [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), - ], - BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60), - signature, - )).to.be.revertedWithCustomError(gateway, 'RevokedSignature'); - }); - }); - - describe('when signature is correct and signed by an authorized signer, but has expired', () => { - it('should revert', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'bytes32[]', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), - ], BigInt(new Date().getTime()) / BigInt(1000) - BigInt(2 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - await gateway.revokeSignature(signature); - - await expect(gateway.deployIdentityWithSaltAndManagementKeys( - aliceWallet.address, - 'saltToUse', - [ - ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address])), - ], - BigInt(new Date().getTime()) / BigInt(1000) - BigInt(2 * 24 * 60 * 60), - signature, - )).to.be.revertedWithCustomError(gateway, 'ExpiredSignature'); - }); - }); - }); - - describe('deployIdentityForWallet', () => { - describe('when input address is the zero address', () => { - it('should revert', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - await expect(gateway.deployIdentityForWallet(ethers.ZeroAddress)).to.revertedWithCustomError(gateway, 'ZeroAddress'); - }); - }); - - describe('when sender is not the desired identity owner', () => { - it('should deploy the identity for the identity owner', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const tx = await gateway.connect(bobWallet).deployIdentityForWallet(aliceWallet.address); - - await expect(tx).to.emit(identityFactory, "WalletLinked").withArgs(aliceWallet.address, await identityFactory.getIdentity(aliceWallet.address)); - await expect(tx).to.emit(identityFactory, "Deployed").withArgs(await identityFactory.getIdentity(aliceWallet.address)); - const identityAddress = await identityFactory.getIdentity(aliceWallet.address); - const identity = await ethers.getContractAt('Identity', identityAddress); - - expect(await identity.keyHasPurpose(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address])), 1)).to.be.true; - }); - }); - - describe('when an identity was not yet deployed for this walet', () => { - it('should deploy the identity', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - const tx = await gateway.connect(aliceWallet).deployIdentityForWallet(aliceWallet.address); - - await expect(tx).to.emit(identityFactory, "WalletLinked").withArgs(aliceWallet.address, await identityFactory.getIdentity(aliceWallet.address)); - await expect(tx).to.emit(identityFactory, "Deployed").withArgs(await identityFactory.getIdentity(aliceWallet.address)); - const identityAddress = await identityFactory.getIdentity(aliceWallet.address); - const identity = await ethers.getContractAt('Identity', identityAddress); - - expect(await identity.keyHasPurpose(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address])), 1)).to.be.true; - }); - }); - - describe('when an identity was already deployed for this wallet as salt with the factory', () => { - it('should revert because factory reverts', async () => { - const {identityFactory, aliceWallet, bobWallet, carolWallet} = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await gateway.connect(aliceWallet).deployIdentityForWallet(aliceWallet.address); - - await expect(gateway.connect(aliceWallet).deployIdentityForWallet(aliceWallet.address)).to.be.revertedWith('salt already taken'); - }); - }); - }); - - describe('.transferFactoryOwnership', () => { - describe('when called by the owner', () => { - it('should transfer ownership of the factory to the specified address', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await expect(gateway.transferFactoryOwnership(bobWallet.address)).to.emit(identityFactory, "OwnershipTransferred").withArgs(await gateway.getAddress(), bobWallet.address); - expect(await identityFactory.owner()).to.be.equal(bobWallet.address); - }); - }); - - describe('when not called by the owner', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await expect(gateway.connect(aliceWallet).transferFactoryOwnership(bobWallet.address)).to.be.revertedWith('Ownable: caller is not the owner') - }); - }); - }); - - describe('.revokeSignature', () => { - describe('when calling not as owner', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - await expect(gateway.connect(aliceWallet).revokeSignature(signature)).to.be.revertedWith('Ownable: caller is not the owner'); - }); - }); - - describe('when signature was already revoked', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - await gateway.revokeSignature(signature); - - await expect(gateway.revokeSignature(signature)).to.be.revertedWithCustomError(gateway, 'SignatureAlreadyRevoked'); - }); - }) - }); - - describe('.approveSignature', () => { - describe('when calling not as owner', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - await expect(gateway.connect(aliceWallet).approveSignature(signature)).to.be.revertedWith('Ownable: caller is not the owner'); - }); - }); - - describe('when signature is not revoked', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - await expect(gateway.approveSignature(signature)).to.be.revertedWithCustomError(gateway, 'SignatureNotRevoked'); - }); - }); - - describe('when signature is revoked', () => { - it('should approve the signature', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const digest = - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode( - ['string', 'address', 'string', 'uint256'], - ['Authorize ONCHAINID deployment', aliceWallet.address, 'saltToUse', BigInt(new Date().getTime()) / BigInt(1000) + BigInt(365 * 24 * 60 * 60)], - ), - ); - const signature = await carolWallet.signMessage( - ethers.getBytes( - digest, - ), - ); - - await gateway.revokeSignature(signature); - - const tx = await gateway.approveSignature(signature); - - expect(tx).to.emit(gateway, "SignatureApproved").withArgs(signature); - }); - }); - }); - - describe('.approveSigner', () => { - describe('when signer address is zero', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await expect(gateway.approveSigner(ethers.ZeroAddress)).to.be.revertedWithCustomError(gateway, 'ZeroAddress'); - }); - }); - - describe('when calling not as owner', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await expect(gateway.connect(aliceWallet).approveSigner(bobWallet.address)).to.be.revertedWith('Ownable: caller is not the owner'); - }); - }); - - describe('when signer is already approved', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await gateway.approveSigner(bobWallet.address); - - await expect(gateway.approveSigner(bobWallet.address)).to.be.revertedWithCustomError(gateway, 'SignerAlreadyApproved'); - }); - }); - - describe('when signer is not approved', () => { - it('should approve the signer', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [carolWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const tx = await gateway.approveSigner(bobWallet.address); - - expect(tx).to.emit(gateway, "SignerApproved").withArgs(bobWallet.address); - }); - }); - }); - - describe('.revokeSigner', () => { - describe('when signer address is zero', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [aliceWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await expect(gateway.revokeSigner(ethers.ZeroAddress)).to.be.revertedWithCustomError(gateway, 'ZeroAddress'); - }); - }); - - describe('when calling not as owner', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [bobWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await expect(gateway.connect(aliceWallet).revokeSigner(bobWallet.address)).to.be.revertedWith('Ownable: caller is not the owner'); - }); - }); - - describe('when signer is not approved', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [aliceWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await expect(gateway.revokeSigner(bobWallet.address)).to.be.revertedWithCustomError(gateway, 'SignerAlreadyNotApproved'); - }); - }); - - describe('when signer is approved', () => { - it('should revoke the signer', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [bobWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const tx = await gateway.revokeSigner(bobWallet.address); - - expect(tx).to.emit(gateway, "SignerRevoked").withArgs(bobWallet.address); - }); - }); - }); - - describe('.callFactory', () => { - describe('when not calling as the owner', () => { - it('should revert', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [aliceWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await expect(gateway.connect(aliceWallet).callFactory( - new ethers.Interface(['function addTokenFactory(address)']).encodeFunctionData('addTokenFactory', [ethers.ZeroAddress])) - ).to.be.revertedWith('Ownable: caller is not the owner'); - }); - }); - - describe('when calling as the owner with invalid parameters', () => { - it('should revert for Factory error', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - carolWallet - } = await loadFixture(deployFactoryFixture); - - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [aliceWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - await expect(gateway.connect(deployerWallet).callFactory( - new ethers.Interface(['function addTokenFactory(address)']).encodeFunctionData('addTokenFactory', [ethers.ZeroAddress])) - ).to.be.revertedWith('Gateway: call to factory failed'); - }); - }); - - describe('when calling as the owner with correct parameters', () => { - it('should execute the function call', async () => { - const { - identityFactory, - deployerWallet, - aliceWallet, - bobWallet, - } = await loadFixture(deployFactoryFixture); - - const gateway = await ethers.deployContract('Gateway', [await identityFactory.getAddress(), [aliceWallet.address]]); - await identityFactory.transferOwnership(await gateway.getAddress()); - - const tx = await gateway.connect(deployerWallet).callFactory(new ethers.Interface(['function addTokenFactory(address)']).encodeFunctionData('addTokenFactory', [bobWallet.address])); - - expect(tx).to.emit(identityFactory, "TokenFactoryAdded").withArgs(bobWallet.address); - }); - }); - }); -}); diff --git a/test/onchainid/identities/claims.test.ts b/test/onchainid/identities/claims.test.ts deleted file mode 100644 index 68a3a57..0000000 --- a/test/onchainid/identities/claims.test.ts +++ /dev/null @@ -1,357 +0,0 @@ -import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { expect } from "chai"; -import {ethers} from "hardhat"; -import { AbiCoder } from 'ethers'; -import { HardhatEthersSigner } from '@nomicfoundation/hardhat-ethers/signers'; - -import { deployIdentityFixture } from '../fixtures'; -import { ClaimIssuer, Identity } from '../../typechain-types'; - -describe('Identity', () => { - describe('Claims', () => { - describe('addClaim', () => { - describe('when the claim is self-attested (issuer is identity address)', () => { - describe('when the claim is not valid', () => { - it('should add the claim anyway', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const claim = { - identity: await aliceIdentity.getAddress(), - issuer: await aliceIdentity.getAddress(), - topic: 42, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - claim.signature = await aliceWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claim.identity, claim.topic, '0x101010'])))); - - const tx = await aliceIdentity.connect(aliceWallet).addClaim(claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - await expect(tx).to.emit(aliceIdentity, 'ClaimAdded').withArgs(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [claim.issuer, claim.topic])), claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - await expect(aliceIdentity.isClaimValid(claim.identity, claim.topic, claim.signature, claim.data)).to.eventually.equal(false); - }); - }); - - describe('when the claim is valid', () => { - let claim = { identity: '', issuer: '', topic: 0, scheme: 1, data: '', uri: '', signature: '' }; - before(async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - claim = { - identity: await aliceIdentity.getAddress(), - issuer: await aliceIdentity.getAddress(), - topic: 42, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - claim.signature = await aliceWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claim.identity, claim.topic, claim.data])))); - }); - - describe('when caller is the identity itself (execute)', () => { - it('should add the claim', async () => { - const { aliceIdentity, aliceWallet, bobWallet } = await loadFixture(deployIdentityFixture); - - const action = { - to: await aliceIdentity.getAddress(), - value: 0, - data: new ethers.Interface([ - 'function addClaim(uint256 topic, uint256 scheme, address issuer, bytes calldata signature, bytes calldata data, string calldata uri) external returns (bytes32 claimRequestId)' - ]).encodeFunctionData('addClaim', [ - claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri - ]), - }; - - await aliceIdentity.connect(bobWallet).execute(action.to, action.value, action.data); - const tx = await aliceIdentity.connect(aliceWallet).approve(0, true); - await expect(tx).to.emit(aliceIdentity, 'ClaimAdded').withArgs(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [claim.issuer, claim.topic])), claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - await expect(tx).to.emit(aliceIdentity, 'Approved'); - await expect(tx).to.emit(aliceIdentity, 'Executed'); - await expect(aliceIdentity.isClaimValid(claim.identity, claim.topic, claim.signature, claim.data)).to.eventually.equal(true); - }); - }); - - describe('when caller is a CLAIM or MANAGEMENT key', () => { - it('should add the claim', async () => { - it('should add the claim anyway', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const tx = await aliceIdentity.connect(aliceWallet).addClaim(claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - await expect(tx).to.emit(aliceIdentity, 'ClaimAdded').withArgs(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [claim.issuer, claim.topic])), claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - }); - }); - }); - - describe('when caller is not a CLAIM key', () => { - it('should revert for missing permission', async () => { - const { aliceIdentity, bobWallet } = await loadFixture(deployIdentityFixture); - - await expect(aliceIdentity.connect(bobWallet).addClaim(claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri)).to.be.revertedWith('Permissions: Sender does not have claim signer key'); - }); - }); - }); - }); - - describe('when the claim is from a claim issuer', () => { - describe('when the claim is not valid', () => { - it('should revert for invalid claim', async () => { - const { aliceIdentity, aliceWallet, claimIssuerWallet, claimIssuer } = await loadFixture(deployIdentityFixture); - - const claim = { - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 42, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - claim.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claim.identity, claim.topic, '0x10101010'])))); - - await expect(aliceIdentity.connect(aliceWallet).addClaim(claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri)).to.be.revertedWith('invalid claim'); - }); - }); - - describe('when the claim is valid', () => { - let claim = { identity: '', issuer: '', topic: 0, scheme: 1, data: '', uri: '', signature: '' }; - before(async () => { - const { aliceIdentity, claimIssuer, claimIssuerWallet } = await loadFixture(deployIdentityFixture); - - claim = { - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 42, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - claim.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claim.identity, claim.topic, claim.data])))); - }); - - describe('when caller is the identity itself (execute)', () => { - it('should add the claim', async () => { - const { aliceIdentity, aliceWallet, bobWallet } = await loadFixture(deployIdentityFixture); - - const action = { - to: await aliceIdentity.getAddress(), - value: 0, - data: new ethers.Interface([ - 'function addClaim(uint256 topic, uint256 scheme, address issuer, bytes calldata signature, bytes calldata data, string calldata uri) external returns (bytes32 claimRequestId)' - ]).encodeFunctionData('addClaim', [ - claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri - ]), - }; - - await aliceIdentity.connect(bobWallet).execute(action.to, action.value, action.data); - const tx = await aliceIdentity.connect(aliceWallet).approve(0, true); - await expect(tx).to.emit(aliceIdentity, 'ClaimAdded').withArgs(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [claim.issuer, claim.topic])), claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - await expect(tx).to.emit(aliceIdentity, 'Approved'); - await expect(tx).to.emit(aliceIdentity, 'Executed'); - }); - }); - - describe('when caller is a CLAIM or MANAGEMENT key', () => { - it('should add the claim', async () => { - it('should add the claim anyway', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const tx = await aliceIdentity.connect(aliceWallet).addClaim(claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - await expect(tx).to.emit(aliceIdentity, 'ClaimAdded').withArgs(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [claim.issuer, claim.topic])), claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - }); - }); - }); - - describe('when caller is not a CLAIM key', () => { - it('should revert for missing permission', async () => { - const { aliceIdentity, bobWallet } = await loadFixture(deployIdentityFixture); - - await expect(aliceIdentity.connect(bobWallet).addClaim(claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri)).to.be.revertedWith('Permissions: Sender does not have claim signer key'); - }); - }); - }); - }); - }); - - describe('updateClaim (addClaim)', () => { - describe('when there is already a claim from this issuer and this topic', () => { - let aliceIdentity: Identity; - let aliceWallet: HardhatEthersSigner; - let claimIssuer: ClaimIssuer; - let claimIssuerWallet: HardhatEthersSigner; - before(async () => { - const params = await loadFixture(deployIdentityFixture); - aliceIdentity = params.aliceIdentity; - aliceWallet = params.aliceWallet; - claimIssuer = params.claimIssuer; - claimIssuerWallet = params.claimIssuerWallet; - - const claim = { - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 42, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - claim.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claim.identity, claim.topic, claim.data])))); - - await aliceIdentity.connect(aliceWallet).addClaim( - claim.topic, - claim.scheme, - claim.issuer, - claim.signature, - claim.data, - claim.uri, - ); - }); - - it('should replace the existing claim', async () => { - const claim = { - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 42, - scheme: 1, - data: '0x004200101010', - signature: '', - uri: 'https://example.com', - }; - claim.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claim.identity, claim.topic, claim.data])))); - - const tx = await aliceIdentity.connect(aliceWallet).addClaim( - claim.topic, - claim.scheme, - claim.issuer, - claim.signature, - claim.data, - claim.uri, - ); - await expect(tx).to.emit(aliceIdentity, 'ClaimChanged').withArgs(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [claim.issuer, claim.topic])), claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - }); - }); - }); - - describe('removeClaim', () => { - describe('When caller is the identity itself (execute)', () => { - it('should remove an existing claim', async () => { - const { aliceIdentity, aliceWallet, bobWallet, claimIssuer, claimIssuerWallet } = await loadFixture(deployIdentityFixture); - const claim = { - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 42, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - const claimId = ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [claim.issuer, claim.topic])); - claim.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claim.identity, claim.topic, claim.data])))); - - await aliceIdentity.connect(aliceWallet).addClaim(claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - - const action = { - to: await aliceIdentity.getAddress(), - value: 0, - data: new ethers.Interface([ - 'function removeClaim(bytes32 claimId) external returns (bool success)' - ]).encodeFunctionData('removeClaim', [ - claimId, - ]), - }; - - await aliceIdentity.connect(bobWallet).execute(action.to, action.value, action.data); - const tx = await aliceIdentity.connect(aliceWallet).approve(0, true); - await expect(tx).to.emit(aliceIdentity, 'ClaimRemoved').withArgs(claimId, claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - }); - }); - - describe('When caller is not a CLAIM key', () => { - it('should revert for missing permission', async () => { - const { aliceIdentity, bobWallet, claimIssuer } = await loadFixture(deployIdentityFixture); - - const claimId = ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [await claimIssuer.getAddress(), 42])); - - await expect(aliceIdentity.connect(bobWallet).removeClaim(claimId)).to.be.revertedWith('Permissions: Sender does not have claim signer key'); - }); - }); - - describe('When claim does not exist', () => { - it('should revert for non existing claim', async () => { - const { aliceIdentity, carolWallet, claimIssuer } = await loadFixture(deployIdentityFixture); - - const claimId = ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [await claimIssuer.getAddress(), 42])); - - await expect(aliceIdentity.connect(carolWallet).removeClaim(claimId)).to.be.revertedWith('NonExisting: There is no claim with this ID'); - }); - }); - - describe('When claim does exist', () => { - it('should remove the claim', async () => { - const { aliceIdentity, aliceWallet, claimIssuer, claimIssuerWallet } = await loadFixture(deployIdentityFixture); - const claim = { - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 42, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - const claimId = ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [claim.issuer, claim.topic])); - claim.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [claim.identity, claim.topic, claim.data])))); - - await aliceIdentity.connect(aliceWallet).addClaim(claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - - const tx = await aliceIdentity.connect(aliceWallet).removeClaim(claimId); - await expect(tx).to.emit(aliceIdentity, 'ClaimRemoved').withArgs(claimId, claim.topic, claim.scheme, claim.issuer, claim.signature, claim.data, claim.uri); - }); - }); - }); - - describe('getClaim', () => { - describe('when claim does not exist', () => { - it('should return an empty struct', async () => { - const { aliceIdentity, claimIssuer } = await loadFixture(deployIdentityFixture); - const claimId = ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [await claimIssuer.getAddress(), 42])); - const found = await aliceIdentity.getClaim(claimId); - expect(found.issuer).to.equal(ethers.ZeroAddress); - expect(found.topic).to.equal(0); - expect(found.scheme).to.equal(0); - expect(found.data).to.equal('0x'); - expect(found.signature).to.equal('0x'); - expect(found.uri).to.equal(''); - }); - }); - - describe('when claim does exist', () => { - it('should return the claim', async () => { - const { aliceIdentity, aliceClaim666 } = await loadFixture(deployIdentityFixture); - - const found = await aliceIdentity.getClaim(aliceClaim666.id); - expect(found.issuer).to.equal(aliceClaim666.issuer); - expect(found.topic).to.equal(aliceClaim666.topic); - expect(found.scheme).to.equal(aliceClaim666.scheme); - expect(found.data).to.equal(aliceClaim666.data); - expect(found.signature).to.equal(aliceClaim666.signature); - expect(found.uri).to.equal(aliceClaim666.uri); - }); - }); - }); - - describe('getClaimIdsByTopic', () => { - it('should return an empty array when there are no claims for the topic', async () => { - const { aliceIdentity } = await loadFixture(deployIdentityFixture); - - await expect(aliceIdentity.getClaimIdsByTopic(101010)).to.eventually.deep.equal([]); - }); - - it('should return an array of claim Id existing fo the topic', async () => { - const { aliceIdentity, aliceClaim666 } = await loadFixture(deployIdentityFixture); - - await expect(aliceIdentity.getClaimIdsByTopic(aliceClaim666.topic)).to.eventually.deep.equal([aliceClaim666.id]); - }); - }); - }); -}); diff --git a/test/onchainid/identities/executions.test.ts b/test/onchainid/identities/executions.test.ts deleted file mode 100644 index cf456f4..0000000 --- a/test/onchainid/identities/executions.test.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { expect } from "chai"; -import {ethers} from "hardhat"; -import { AbiCoder } from 'ethers'; - -import { deployIdentityFixture } from '../fixtures'; - -describe('Identity', () => { - describe('Execute', () => { - describe('when calling execute as a MANAGEMENT key', () => { - describe('when execution is possible (transferring value with enough funds on the identity)', () => { - it('should execute immediately the action', async () => { - const { aliceIdentity, aliceWallet, carolWallet } = await loadFixture(deployIdentityFixture); - - const previousBalance = await ethers.provider.getBalance(carolWallet.address); - const action = { - to: carolWallet.address, - value: 10, - data: '0x', - }; - - const tx = await aliceIdentity.connect(aliceWallet).execute(action.to, action.value, action.data, { value: action.value }); - await expect(tx).to.emit(aliceIdentity, 'Approved'); - await expect(tx).to.emit(aliceIdentity, 'Executed'); - const newBalance = await ethers.provider.getBalance(carolWallet.address); - - expect(newBalance).to.equal(previousBalance + BigInt(action.value)); - }); - }); - - describe('when execution is possible (successfull call)', () => { - it('should emit Executed', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - - const action = { - to: await aliceIdentity.getAddress(), - value: 0, - data: new ethers.Interface(['function addKey(bytes32 key, uint256 purpose, uint256 keyType) returns (bool success)']).encodeFunctionData('addKey', [ - aliceKeyHash, - 3, - 1, - ]), - }; - - const tx = await aliceIdentity.connect(aliceWallet).execute(action.to, action.value, action.data); - await expect(tx).to.emit(aliceIdentity, 'Approved'); - await expect(tx).to.emit(aliceIdentity, 'Executed'); - - const purposes = await aliceIdentity.getKeyPurposes(aliceKeyHash); - expect(purposes).to.deep.equal([1, 3]); - }); - }); - - describe('when execution is not possible (failing call)', () => { - it('should emit an ExecutionFailed event', async () => { - const { aliceIdentity, aliceWallet, carolWallet } = await loadFixture(deployIdentityFixture); - - const previousBalance = await ethers.provider.getBalance(carolWallet.address); - const action = { - to: await aliceIdentity.getAddress(), - value: 0, - data: new ethers.Interface(['function addKey(bytes32 key, uint256 purpose, uint256 keyType) returns (bool success)']).encodeFunctionData('addKey', [ - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ), - 1, - 1, - ]), - }; - - const tx = await aliceIdentity.connect(aliceWallet).execute(action.to, action.value, action.data); - await expect(tx).to.emit(aliceIdentity, 'Approved'); - await expect(tx).to.emit(aliceIdentity, 'ExecutionFailed'); - const newBalance = await ethers.provider.getBalance(carolWallet.address); - - expect(newBalance).to.equal(previousBalance + BigInt(action.value)); - }); - }); - }); - - describe('when calling execute as an ACTION key', () => { - describe('when target is the identity contract', () => { - it('should create an execution request', async () => { - const { aliceIdentity, aliceWallet, bobWallet, carolWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - const carolKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [carolWallet.address]) - ); - await aliceIdentity.connect(aliceWallet).addKey(carolKeyHash, 2, 1); - - const action = { - to: await aliceIdentity.getAddress(), - value: 0, - data: new ethers.Interface(['function addKey(bytes32 key, uint256 purpose, uint256 keyType) returns (bool success)']).encodeFunctionData('addKey', [ - aliceKeyHash, - 2, - 1, - ]), - }; - - const tx = await aliceIdentity.connect(carolWallet).execute(action.to, action.value, action.data, { value: action.value }); - await expect(tx).to.emit(aliceIdentity, 'ExecutionRequested'); - }); - }); - - describe('when target is another address', () => { - it('should emit ExecutionFailed for a failed execution', async () => { - const { aliceIdentity, aliceWallet, carolWallet, davidWallet, bobIdentity } = await loadFixture(deployIdentityFixture); - - const carolKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [carolWallet.address]) - ); - await aliceIdentity.connect(aliceWallet).addKey(carolKeyHash, 2, 1); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - - const action = { - to: await bobIdentity.getAddress(), - value: 10, - data: new ethers.Interface(['function addKey(bytes32 key, uint256 purpose, uint256 keyType) returns (bool success)']).encodeFunctionData('addKey', [ - aliceKeyHash, - 3, - 1, - ]), - }; - - const previousBalance = await ethers.provider.getBalance(await bobIdentity.getAddress()); - - const tx = await aliceIdentity.connect(carolWallet).execute(action.to, action.value, action.data, { value: action.value }); - await expect(tx).to.emit(aliceIdentity, 'Approved'); - await expect(tx).to.emit(aliceIdentity, 'ExecutionFailed'); - const newBalance = await ethers.provider.getBalance(await bobIdentity.getAddress()); - - expect(newBalance).to.equal(previousBalance); - }); - - it('should execute immediately the action', async () => { - const { aliceIdentity, aliceWallet, carolWallet, davidWallet } = await loadFixture(deployIdentityFixture); - - const carolKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [carolWallet.address]) - ); - await aliceIdentity.connect(aliceWallet).addKey(carolKeyHash, 2, 1); - - const previousBalance = await ethers.provider.getBalance(davidWallet.address); - const action = { - to: davidWallet.address, - value: 10, - data: '0x', - }; - - const tx = await aliceIdentity.connect(carolWallet).execute(action.to, action.value, action.data, { value: action.value }); - await expect(tx).to.emit(aliceIdentity, 'Approved'); - await expect(tx).to.emit(aliceIdentity, 'Executed'); - const newBalance = await ethers.provider.getBalance(davidWallet.address); - - expect(newBalance).to.equal(previousBalance + BigInt(action.value)); - }); - }); - }); - - describe('when calling execute as a non-action key', () => { - it('should create a pending execution request', async () => { - const { aliceIdentity, bobWallet, carolWallet } = await loadFixture(deployIdentityFixture); - - const previousBalance = await ethers.provider.getBalance(carolWallet.address); - const action = { - to: carolWallet.address, - value: 10, - data: '0x', - }; - - const tx = await aliceIdentity.connect(bobWallet).execute(action.to, action.value, action.data, { value: action.value }); - await expect(tx).to.emit(aliceIdentity, 'ExecutionRequested'); - const newBalance = await ethers.provider.getBalance(carolWallet.address); - - expect(newBalance).to.equal(previousBalance); - }); - }); - }); - - describe('Approve', () => { - describe('when calling a non-existing execution request', () => { - it('should revert for execution request not found', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - await expect(aliceIdentity.connect(aliceWallet).approve(2, true)).to.be.revertedWith('Cannot approve a non-existing execution'); - }); - }); - - describe('when calling an already executed request', () => { - it('should revert for execution request already executed', async () => { - const { aliceIdentity, aliceWallet, bobWallet } = await loadFixture(deployIdentityFixture); - - await aliceIdentity.connect(aliceWallet).execute(bobWallet.address, 10, '0x', { value: 10 }); - - await expect(aliceIdentity.connect(aliceWallet).approve(0, true)).to.be.revertedWith('Request already executed'); - }); - }); - - describe('when calling approve for an execution targeting another address as a non-action key', () => { - it('should revert for not authorized', async () => { - const { aliceIdentity, bobWallet, carolWallet } = await loadFixture(deployIdentityFixture); - - await aliceIdentity.connect(bobWallet).execute(carolWallet.address, 10, '0x', { value: 10 }); - - await expect(aliceIdentity.connect(bobWallet).approve(0, true)).to.be.revertedWith('Sender does not have action key'); - }); - }); - - describe('when calling approve for an execution targeting another address as a non-management key', () => { - it('should revert for not authorized', async () => { - const { aliceIdentity, davidWallet, bobWallet } = await loadFixture(deployIdentityFixture); - - await aliceIdentity.connect(bobWallet).execute(await aliceIdentity.getAddress(), 10, '0x', { value: 10 }); - - await expect(aliceIdentity.connect(davidWallet).approve(0, true)).to.be.revertedWith('Sender does not have management key'); - }); - }); - - describe('when calling approve as a MANAGEMENT key', () => { - it('should approve the execution request', async () => { - const { aliceIdentity, aliceWallet, bobWallet, carolWallet } = await loadFixture(deployIdentityFixture); - - const previousBalance = await ethers.provider.getBalance(carolWallet.address); - await aliceIdentity.connect(bobWallet).execute(carolWallet.address, 10, '0x', { value: 10 }); - - const tx = await aliceIdentity.connect(aliceWallet).approve(0, true); - await expect(tx).to.emit(aliceIdentity, 'Approved'); - await expect(tx).to.emit(aliceIdentity, 'Executed'); - const newBalance = await ethers.provider.getBalance(carolWallet.address); - - expect(newBalance).to.equal(previousBalance + BigInt(10)); - }); - - it('should leave approve to false', async () => { - const { aliceIdentity, aliceWallet, bobWallet, carolWallet } = await loadFixture(deployIdentityFixture); - - const previousBalance = await ethers.provider.getBalance(carolWallet.address); - await aliceIdentity.connect(bobWallet).execute(carolWallet.address, 10, '0x', { value: 10 }); - - const tx = await aliceIdentity.connect(aliceWallet).approve(0, false); - await expect(tx).to.emit(aliceIdentity, 'Approved'); - const newBalance = await ethers.provider.getBalance(carolWallet.address); - - expect(newBalance).to.equal(previousBalance); - }); - }); - }); -}); diff --git a/test/onchainid/identities/init.test.ts b/test/onchainid/identities/init.test.ts deleted file mode 100644 index aa6d00f..0000000 --- a/test/onchainid/identities/init.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {loadFixture} from '@nomicfoundation/hardhat-network-helpers'; -import {expect} from "chai"; -import {ethers} from "hardhat"; -import { AbiCoder } from 'ethers'; - -import {deployIdentityFixture} from '../fixtures'; - -describe('Identity', () => { - it('should revert when attempting to initialize an already deployed identity', async () => { - const {aliceIdentity, aliceWallet} = await loadFixture(deployIdentityFixture); - - await expect(aliceIdentity.connect(aliceWallet).initialize(aliceWallet.address)).to.be.revertedWith('Initial key was already setup.'); - }); - - it('should revert because interaction with library is forbidden', async () => { - const {identityImplementation, aliceWallet, deployerWallet} = await loadFixture(deployIdentityFixture); - - await expect(identityImplementation.connect(deployerWallet).addKey( - ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ), - 3, - 1, - )).to.be.revertedWith('Interacting with the library contract is forbidden.'); - - await expect(identityImplementation.connect(aliceWallet).initialize(deployerWallet.address)) - .to.be.revertedWith('Initial key was already setup.'); - }); - - it('should prevent creating an identity with an invalid initial key', async () => { - const [identityOwnerWallet] = await ethers.getSigners(); - - const Identity = await ethers.getContractFactory('Identity'); - await expect(Identity.connect(identityOwnerWallet).deploy(ethers.ZeroAddress, false)).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should return the version of the implementation', async () => { - const {identityImplementation} = await loadFixture(deployIdentityFixture); - - expect(await identityImplementation.version()).to.equal('2.2.1'); - }); -}); diff --git a/test/onchainid/identities/keys.test.ts b/test/onchainid/identities/keys.test.ts deleted file mode 100644 index f712b83..0000000 --- a/test/onchainid/identities/keys.test.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -import { expect } from "chai"; -import {ethers} from "hardhat"; -import { AbiCoder } from 'ethers'; - -import { deployIdentityFixture } from '../fixtures'; - -describe('Identity', () => { - describe('Key Management', () => { - describe('Read key methods', () => { - it('should retrieve an existing key', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - const aliceKey = await aliceIdentity.getKey(aliceKeyHash); - expect(aliceKey.key).to.equal(aliceKeyHash); - expect(aliceKey.purposes).to.deep.equal([1]); - expect(aliceKey.keyType).to.equal(1); - }); - - it('should retrieve existing key purposes', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - const purposes = await aliceIdentity.getKeyPurposes(aliceKeyHash); - expect(purposes).to.deep.equal([1]); - }); - - it('should retrieve existing keys with given purpose', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - const keys = await aliceIdentity.getKeysByPurpose(1); - expect(keys).to.deep.equal([aliceKeyHash]); - }); - - it('should return true if a key has a given purpose', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - const hasPurpose = await aliceIdentity.keyHasPurpose(aliceKeyHash, 1); - expect(hasPurpose).to.equal(true); - }); - - it('should return false if a key has not a given purpose but is a MANAGEMENT key', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - const hasPurpose = await aliceIdentity.keyHasPurpose(aliceKeyHash, 2); - expect(hasPurpose).to.equal(true); - }); - - it('should return false if a key has not a given purpose', async () => { - const { aliceIdentity, bobWallet } = await loadFixture(deployIdentityFixture); - - const bobKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address]) - ); - const hasPurpose = await aliceIdentity.keyHasPurpose(bobKeyHash, 2); - expect(hasPurpose).to.equal(false); - }); - }); - - describe('Add key methods', () => { - describe('when calling as a non-MANAGEMENT key', () => { - it('should revert because the signer is not a MANAGEMENT key', async () => { - const { aliceIdentity, bobWallet } = await loadFixture(deployIdentityFixture); - - const bobKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address]) - ); - await expect( - aliceIdentity.connect(bobWallet).addKey(bobKeyHash, 1, 1) - ).to.be.revertedWith('Permissions: Sender does not have management key'); - }); - }); - - describe('when calling as a MANAGEMENT key', () => { - it('should add the purpose to the existing key', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - await aliceIdentity.connect(aliceWallet).addKey(aliceKeyHash, 2, 1); - const aliceKey = await aliceIdentity.getKey(aliceKeyHash); - expect(aliceKey.key).to.equal(aliceKeyHash); - expect(aliceKey.purposes).to.deep.equal([1, 2]); - expect(aliceKey.keyType).to.equal(1); - }); - - it('should add a new key with a purpose', async () => { - const { aliceIdentity, bobWallet, aliceWallet } = await loadFixture(deployIdentityFixture); - - const bobKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address]) - ); - await aliceIdentity.connect(aliceWallet).addKey(bobKeyHash, 1, 1); - const bobKey = await aliceIdentity.getKey(bobKeyHash); - expect(bobKey.key).to.equal(bobKeyHash); - expect(bobKey.purposes).to.deep.equal([1]); - expect(bobKey.keyType).to.equal(1); - }); - - it('should revert because key already has the purpose', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - await expect( - aliceIdentity.connect(aliceWallet).addKey(aliceKeyHash, 1, 1) - ).to.be.revertedWith('Conflict: Key already has purpose'); - }); - }); - }); - - describe('Remove key methods', () => { - describe('when calling as a non-MANAGEMENT key', () => { - it('should revert because the signer is not a MANAGEMENT key', async () => { - const { aliceIdentity, aliceWallet, bobWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - await expect( - aliceIdentity.connect(bobWallet).removeKey(aliceKeyHash, 1) - ).to.be.revertedWith('Permissions: Sender does not have management key'); - }); - }); - - describe('when calling as a MANAGEMENT key', () => { - it('should remove the purpose from the existing key', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - await aliceIdentity.connect(aliceWallet).removeKey(aliceKeyHash, 1); - const aliceKey = await aliceIdentity.getKey(aliceKeyHash); - expect(aliceKey.key).to.equal('0x0000000000000000000000000000000000000000000000000000000000000000'); - expect(aliceKey.purposes).to.deep.equal([]); - expect(aliceKey.keyType).to.equal(0); - }); - - it('should revert because key does not exists', async () => { - const { aliceIdentity, aliceWallet, bobWallet } = await loadFixture(deployIdentityFixture); - - const bobKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [bobWallet.address]) - ); - await expect( - aliceIdentity.connect(aliceWallet).removeKey(bobKeyHash, 2) - ).to.be.revertedWith("NonExisting: Key isn't registered"); - }); - - it('should revert because key does not have the purpose', async () => { - const { aliceIdentity, aliceWallet } = await loadFixture(deployIdentityFixture); - - const aliceKeyHash = ethers.keccak256( - AbiCoder.defaultAbiCoder().encode(['address'], [aliceWallet.address]) - ); - await expect( - aliceIdentity.connect(aliceWallet).removeKey(aliceKeyHash, 2) - ).to.be.revertedWith("NonExisting: Key doesn't have such purpose"); - }); - }); - }); - }); -}); diff --git a/test/onchainid/proxy.test.ts b/test/onchainid/proxy.test.ts deleted file mode 100644 index 4636671..0000000 --- a/test/onchainid/proxy.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import {expect} from "chai"; -import {ethers} from "hardhat"; -import {loadFixture} from "@nomicfoundation/hardhat-network-helpers"; -import {deployIdentityFixture} from "./fixtures"; - -describe('Proxy', () => { - it('should revert because implementation is Zero address', async () => { - const [deployerWallet, identityOwnerWallet] = await ethers.getSigners(); - - const IdentityProxy = await ethers.getContractFactory('IdentityProxy'); - await expect(IdentityProxy.connect(deployerWallet).deploy(ethers.ZeroAddress, identityOwnerWallet.address)).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should revert because implementation is not an identity', async () => { - const [deployerWallet, identityOwnerWallet] = await ethers.getSigners(); - - const claimIssuer = await ethers.deployContract('Test'); - - const authority = await ethers.deployContract('ImplementationAuthority', [await claimIssuer.getAddress()]); - - const IdentityProxy = await ethers.getContractFactory('IdentityProxy'); - await expect(IdentityProxy.connect(deployerWallet).deploy(await authority.getAddress(), identityOwnerWallet.address)).to.be.revertedWith('Initialization failed.'); - }); - - it('should revert because initial key is Zero address', async () => { - const [deployerWallet] = await ethers.getSigners(); - - const implementation = await ethers.deployContract('Identity', [deployerWallet.address, true]); - const implementationAuthority = await ethers.deployContract('ImplementationAuthority', [await implementation.getAddress()]); - - const IdentityProxy = await ethers.getContractFactory('IdentityProxy'); - await expect(IdentityProxy.connect(deployerWallet).deploy(await implementationAuthority.getAddress(), ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should prevent creating an implementation authority with a zero address implementation', async () => { - const [deployerWallet] = await ethers.getSigners(); - - const ImplementationAuthority = await ethers.getContractFactory('ImplementationAuthority'); - await expect(ImplementationAuthority.connect(deployerWallet).deploy(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should prevent updating to a Zero address implementation', async () => { - const {implementationAuthority, deployerWallet} = await loadFixture(deployIdentityFixture); - - await expect(implementationAuthority.connect(deployerWallet).updateImplementation(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); - }); - - it('should prevent updating when not owner', async () => { - const {implementationAuthority, aliceWallet} = await loadFixture(deployIdentityFixture); - - await expect(implementationAuthority.connect(aliceWallet).updateImplementation(ethers.ZeroAddress)).to.be.revertedWith('Ownable: caller is not the owner'); - }); - - it('should update the implementation address', async () => { - const [deployerWallet] = await ethers.getSigners(); - - const implementation = await ethers.deployContract('Identity', [deployerWallet.address, true]); - const implementationAuthority = await ethers.deployContract('ImplementationAuthority', [await implementation.getAddress()]); - - const newImplementation = await ethers.deployContract('Identity', [deployerWallet.address, true]); - - const tx = await implementationAuthority.connect(deployerWallet).updateImplementation(await newImplementation.getAddress()); - await expect(tx).to.emit(implementationAuthority, 'UpdatedImplementation').withArgs(await newImplementation.getAddress()); - }); -}); diff --git a/test/onchainid/verifiers/verifier-user.test.ts b/test/onchainid/verifiers/verifier-user.test.ts deleted file mode 100644 index e3edb5c..0000000 --- a/test/onchainid/verifiers/verifier-user.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import {ethers} from "hardhat"; -import {expect} from "chai"; -import {AbiCoder} from 'ethers'; - -describe('VerifierUser', () => { - describe('when calling a verified function not as an identity', () => { - it('should revert', async () => { - const verifierUser = await ethers.deployContract('VerifierUser', []); - - await verifierUser.addClaimTopic(666); - - await expect(verifierUser.doSomething()).to.be.reverted; - }); - }); - - describe('when identity is verified', () => { - it('should return', async () => { - const [deployer, aliceWallet, claimIssuerWallet] = await ethers.getSigners(); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [claimIssuerWallet.address]); - const aliceIdentity = await ethers.deployContract('Identity', [aliceWallet.address, false]); - const verifierUser = await ethers.deployContract('VerifierUser', []); - - await verifierUser.addClaimTopic(666); - await verifierUser.addTrustedIssuer(await claimIssuer.getAddress(), [666]); - - const aliceClaim666 = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 666, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - aliceClaim666.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim666.topic, - aliceClaim666.scheme, - aliceClaim666.issuer, - aliceClaim666.signature, - aliceClaim666.data, - aliceClaim666.uri, - ); - - const action = { - to: await verifierUser.getAddress(), - value: 0, - data: new ethers.Interface(['function doSomething()']).encodeFunctionData('doSomething'), - }; - - const tx = await aliceIdentity.connect(aliceWallet).execute( - action.to, - action.value, - action.data, - ); - expect(tx).to.emit(aliceIdentity, 'Executed'); - }); - }); - - describe('when identity is not verified', () => { - it('should revert', async () => { - const [deployer, aliceWallet, claimIssuerWallet] = await ethers.getSigners(); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [claimIssuerWallet.address]); - const aliceIdentity = await ethers.deployContract('Identity', [aliceWallet.address, false]); - const verifierUser = await ethers.deployContract('VerifierUser', []); - - await verifierUser.addClaimTopic(666); - await verifierUser.addTrustedIssuer(await claimIssuer.getAddress(), [666]); - - const aliceClaim666 = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 666, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - aliceClaim666.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim666.topic, - aliceClaim666.scheme, - aliceClaim666.issuer, - aliceClaim666.signature, - aliceClaim666.data, - aliceClaim666.uri, - ); - - await claimIssuer.connect(claimIssuerWallet).revokeClaimBySignature(aliceClaim666.signature); - - const action = { - to: await verifierUser.getAddress(), - value: 0, - data: new ethers.Interface(['function doSomething()']).encodeFunctionData('doSomething'), - }; - - const tx = await aliceIdentity.connect(aliceWallet).execute( - action.to, - action.value, - action.data, - ); - expect(tx).to.emit(aliceIdentity, 'ExecutionFailed'); - }); - }); -}); diff --git a/test/onchainid/verifiers/verifier.test.ts b/test/onchainid/verifiers/verifier.test.ts deleted file mode 100644 index 3ec0673..0000000 --- a/test/onchainid/verifiers/verifier.test.ts +++ /dev/null @@ -1,523 +0,0 @@ -import {ethers} from "hardhat"; -import {expect} from "chai"; -import { AbiCoder } from 'ethers'; - -describe('Verifier', () => { - describe('.verify()', () => { - describe('when the Verifier does expect claim topics', () => { - it('should return true', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - - await expect(verifier.verify(aliceWallet.address)).to.eventually.be.true; - }); - }); - - describe('when the Verifier expect one claim topic but has no trusted issuers', () => { - it('should return false', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - await verifier.addClaimTopic(ethers.encodeBytes32String('SOME_TOPIC')); - - await expect(verifier.verify(aliceWallet.address)).to.eventually.be.false; - }); - }); - - describe('when the Verifier expect one claim topic and a trusted issuer for another topic', () => { - it('should return false', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - await verifier.addClaimTopic(ethers.encodeBytes32String('SOME_TOPIC')); - await verifier.addTrustedIssuer(deployer.address, [ethers.encodeBytes32String('SOME_OTHER_TOPIC')]); - - await expect(verifier.verify(aliceWallet.address)).to.eventually.be.false; - }); - }); - - describe('when the Verifier expect one claim topic and a trusted issuer for the topic', () => { - describe('when the identity does not have the claim', () => { - it('should return false', async () => { - const [deployer, aliceWallet, claimIssuerWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [claimIssuerWallet.address]); - const aliceIdentity = await ethers.deployContract('Identity', [aliceWallet.address, false]); - await verifier.addClaimTopic(ethers.encodeBytes32String('SOME_TOPIC')); - await verifier.addTrustedIssuer(await claimIssuer.getAddress(), [ethers.encodeBytes32String('SOME_TOPIC')]); - - await expect(verifier.verify(await aliceIdentity.getAddress())).to.eventually.be.false; - }); - }); - - describe('when the identity does not have a valid expected claim', () => { - it('should return false', async () => { - const [deployer, aliceWallet, claimIssuerWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [claimIssuerWallet.address]); - const aliceIdentity = await ethers.deployContract('Identity', [aliceWallet.address, false]); - - await verifier.addClaimTopic(666); - await verifier.addTrustedIssuer(await claimIssuer.getAddress(), [666]); - - const aliceClaim666 = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 666, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - aliceClaim666.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim666.topic, - aliceClaim666.scheme, - aliceClaim666.issuer, - aliceClaim666.signature, - aliceClaim666.data, - aliceClaim666.uri, - ); - await claimIssuer.connect(claimIssuerWallet).revokeClaimBySignature( - aliceClaim666.signature, - ); - - await expect(verifier.verify(await aliceIdentity.getAddress())).to.eventually.be.false; - }); - }); - - describe('when the identity has the valid expected claim', () => { - it('should return true', async () => { - const [deployer, aliceWallet, claimIssuerWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [claimIssuerWallet.address]); - const aliceIdentity = await ethers.deployContract('Identity', [aliceWallet.address, false]); - - await verifier.addClaimTopic(666); - await verifier.addTrustedIssuer(await claimIssuer.getAddress(), [666]); - - const aliceClaim666 = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuer.getAddress(), - topic: 666, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - aliceClaim666.signature = await claimIssuerWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim666.topic, - aliceClaim666.scheme, - aliceClaim666.issuer, - aliceClaim666.signature, - aliceClaim666.data, - aliceClaim666.uri, - ); - - await expect(verifier.verify(await aliceIdentity.getAddress())).to.eventually.be.true; - }); - }); - }); - - describe('when the Verifier expect multiple claim topics and allow multiple trusted issuers', () => { - describe('when identity is compliant', () => { - it('should return true', async () => { - const [deployer, aliceWallet, claimIssuerAWallet, claimIssuerBWallet, claimIssuerCWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuerA = await ethers.deployContract('ClaimIssuer', [claimIssuerAWallet.address]); - const claimIssuerB = await ethers.deployContract('ClaimIssuer', [claimIssuerBWallet.address]); - const claimIssuerC = await ethers.deployContract('ClaimIssuer', [claimIssuerCWallet.address]); - const aliceIdentity = await ethers.deployContract('Identity', [aliceWallet.address, false]); - - await verifier.addClaimTopic(666); - await verifier.addTrustedIssuer(await claimIssuerA.getAddress(), [666]); - await verifier.addClaimTopic(42); - await verifier.addTrustedIssuer(await claimIssuerB.getAddress(), [42, 666]); - - const aliceClaim666C = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuerC.getAddress(), - topic: 666, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - aliceClaim666C.signature = await claimIssuerCWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666C.identity, aliceClaim666C.topic, aliceClaim666C.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim666C.topic, - aliceClaim666C.scheme, - aliceClaim666C.issuer, - aliceClaim666C.signature, - aliceClaim666C.data, - aliceClaim666C.uri, - ); - - const aliceClaim666 = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuerA.getAddress(), - topic: 666, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - aliceClaim666.signature = await claimIssuerAWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim666.topic, - aliceClaim666.scheme, - aliceClaim666.issuer, - aliceClaim666.signature, - aliceClaim666.data, - aliceClaim666.uri, - ); - - const aliceClaim666B = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuerB.getAddress(), - topic: 666, - scheme: 1, - data: '0x0066', - signature: '', - uri: 'https://example.com/B/666', - }; - aliceClaim666B.signature = await claimIssuerBWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666B.identity, aliceClaim666B.topic, aliceClaim666B.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim666B.topic, - aliceClaim666B.scheme, - aliceClaim666B.issuer, - aliceClaim666B.signature, - aliceClaim666B.data, - aliceClaim666B.uri, - ); - - const aliceClaim42 = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuerB.getAddress(), - topic: 42, - scheme: 1, - data: '0x0010', - signature: '', - uri: 'https://example.com/42', - }; - aliceClaim42.signature = await claimIssuerBWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim42.identity, aliceClaim42.topic, aliceClaim42.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim42.topic, - aliceClaim42.scheme, - aliceClaim42.issuer, - aliceClaim42.signature, - aliceClaim42.data, - aliceClaim42.uri, - ); - - await claimIssuerB.connect(claimIssuerBWallet).revokeClaimBySignature(aliceClaim666B.signature); - - await expect(verifier.verify(await aliceIdentity.getAddress())).to.eventually.be.true; - }); - }); - - describe('when identity is not compliant', () => { - it('should return false', async () => { - const [deployer, aliceWallet, claimIssuerAWallet, claimIssuerBWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuerA = await ethers.deployContract('ClaimIssuer', [claimIssuerAWallet.address]); - const claimIssuerB = await ethers.deployContract('ClaimIssuer', [claimIssuerBWallet.address]); - const aliceIdentity = await ethers.deployContract('Identity', [aliceWallet.address, false]); - - await verifier.addClaimTopic(666); - await verifier.addTrustedIssuer(await claimIssuerA.getAddress(), [666]); - await verifier.addClaimTopic(42); - await verifier.addTrustedIssuer(await claimIssuerB.getAddress(), [42, 666]); - - const aliceClaim666 = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuerA.getAddress(), - topic: 666, - scheme: 1, - data: '0x0042', - signature: '', - uri: 'https://example.com', - }; - aliceClaim666.signature = await claimIssuerAWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666.identity, aliceClaim666.topic, aliceClaim666.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim666.topic, - aliceClaim666.scheme, - aliceClaim666.issuer, - aliceClaim666.signature, - aliceClaim666.data, - aliceClaim666.uri, - ); - - const aliceClaim666B = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuerB.getAddress(), - topic: 666, - scheme: 1, - data: '0x0066', - signature: '', - uri: 'https://example.com/B/666', - }; - aliceClaim666B.signature = await claimIssuerBWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim666B.identity, aliceClaim666B.topic, aliceClaim666B.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim666B.topic, - aliceClaim666B.scheme, - aliceClaim666B.issuer, - aliceClaim666B.signature, - aliceClaim666B.data, - aliceClaim666B.uri, - ); - - const aliceClaim42 = { - id: '', - identity: await aliceIdentity.getAddress(), - issuer: await claimIssuerB.getAddress(), - topic: 42, - scheme: 1, - data: '0x0010', - signature: '', - uri: 'https://example.com/42', - }; - aliceClaim42.signature = await claimIssuerBWallet.signMessage(ethers.getBytes(ethers.keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256', 'bytes'], [aliceClaim42.identity, aliceClaim42.topic, aliceClaim42.data])))); - await aliceIdentity.connect(aliceWallet).addClaim( - aliceClaim42.topic, - aliceClaim42.scheme, - aliceClaim42.issuer, - aliceClaim42.signature, - aliceClaim42.data, - aliceClaim42.uri, - ); - - await claimIssuerB.connect(claimIssuerBWallet).revokeClaimBySignature(aliceClaim42.signature); - - await expect(verifier.verify(await aliceIdentity.getAddress())).to.eventually.be.false; - }); - }); - }); - }); - - describe('.removeClaimTopic', () => { - describe('when not called by the owner', () => { - it('should revert', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - - await expect(verifier.connect(aliceWallet).removeClaimTopic(2)).to.be.revertedWith('Ownable: caller is not the owner'); - }); - }); - - describe('when called by the owner', () => { - it('should remove the claim topic', async () => { - const [deployer] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - await verifier.addClaimTopic(1); - await verifier.addClaimTopic(2); - await verifier.addClaimTopic(3); - - const tx = await verifier.removeClaimTopic(2); - await expect(tx).to.emit(verifier, 'ClaimTopicRemoved').withArgs(2); - expect(await verifier.isClaimTopicRequired(1)).to.be.true; - expect(await verifier.isClaimTopicRequired(2)).to.be.false; - expect(await verifier.isClaimTopicRequired(3)).to.be.true; - }); - }); - }); - - describe('.removeTrustedIssuer', () => { - describe('when not called by the owner', () => { - it('should revert', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - - await expect(verifier.connect(aliceWallet).removeTrustedIssuer(await claimIssuer.getAddress())).to.be.revertedWith('Ownable: caller is not the owner'); - }); - }); - - describe('when called by the owner', () => { - it('should remove the trusted issuer', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - const claimIssuerB = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - await verifier.addTrustedIssuer(await claimIssuer.getAddress(), [1]); - await verifier.addTrustedIssuer(await claimIssuerB.getAddress(), [2]); - - const tx = await verifier.removeTrustedIssuer(await claimIssuer.getAddress()); - await expect(tx).to.emit(verifier, 'TrustedIssuerRemoved').withArgs(await claimIssuer.getAddress()); - expect(await verifier.isTrustedIssuer(await claimIssuer.getAddress())).to.be.false; - expect(await verifier.getTrustedIssuers()).to.be.deep.equal([await claimIssuerB.getAddress()]); - }); - }); - - describe('when issuer address is zero', () => { - it('should revert', async () => { - const [deployer] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - - await expect(verifier.removeTrustedIssuer(ethers.ZeroAddress)).to.be.revertedWith('invalid argument - zero address'); - }); - }); - - describe('when issuer is not trusted', () => { - it('should revert', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - - await expect(verifier.removeTrustedIssuer(await claimIssuer.getAddress())).to.be.revertedWith('NOT a trusted issuer'); - }); - }); - }); - - describe('.addTrustedIssuer', () => { - describe('when not called by the owner', () => { - it('should revert', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - - await expect(verifier.connect(aliceWallet).addTrustedIssuer(await claimIssuer.getAddress(), [1])).to.be.revertedWith('Ownable: caller is not the owner'); - }); - }); - - describe('when issuer address is the zero', () => { - it('should revert', async () => { - const [deployer] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - - await expect(verifier.addTrustedIssuer(ethers.ZeroAddress, [1])).to.be.revertedWith('invalid argument - zero address'); - }); - }); - - describe('when issuer is already trusted', () => { - it('should revert', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - await verifier.addTrustedIssuer(await claimIssuer.getAddress(), [1]); - - await expect(verifier.addTrustedIssuer(await claimIssuer.getAddress(), [2])).to.be.revertedWith('trusted Issuer already exists'); - }); - }); - - describe('when claim topics array is empty', () => { - it('should revert', async () => { - const [deployer] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - - await expect(verifier.addTrustedIssuer(deployer.address, [])).to.be.revertedWith('trusted claim topics cannot be empty'); - }); - }); - - describe('when claim topics array contains more than 15 topics', () => { - it('should revert', async () => { - const [deployer] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - - await expect(verifier.addTrustedIssuer(deployer.address, [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16])).to.be.revertedWith('cannot have more than 15 claim topics'); - }); - }); - - describe('when adding a 51th trusted issuer', () => { - it('should revert', async () => { - const [deployer] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - for (let i = 0; i < 50; i++) { - const claimIssuer = await ethers.deployContract('ClaimIssuer', [deployer.address]); - await verifier.addTrustedIssuer(await claimIssuer.getAddress(), [1]); - } - - const claimIssuer = await ethers.deployContract('ClaimIssuer', [deployer.address]); - await expect(verifier.addTrustedIssuer(await claimIssuer.getAddress(), [1])).to.be.revertedWith('cannot have more than 50 trusted issuers'); - }); - }); - }); - - describe('.updateIssuerClaimTopics', () => { - describe('when not called by the owner', () => { - it('should revert', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - - await expect(verifier.connect(aliceWallet).updateIssuerClaimTopics(await claimIssuer.getAddress(), [1])).to.be.revertedWith('Ownable: caller is not the owner'); - }); - }); - - describe('when called by the owner', () => { - it('should update the issuer claim topics', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - await verifier.addTrustedIssuer(await claimIssuer.getAddress(), [1]); - - const tx = await verifier.updateIssuerClaimTopics(await claimIssuer.getAddress(), [2, 3]); - await expect(tx).to.emit(verifier, 'ClaimTopicsUpdated').withArgs(await claimIssuer.getAddress(), [2, 3]); - expect(await verifier.isTrustedIssuer(await claimIssuer.getAddress())).to.be.true; - expect(await verifier.getTrustedIssuersForClaimTopic(1)).to.be.empty; - expect(await verifier.getTrustedIssuerClaimTopics(await claimIssuer.getAddress())).to.be.deep.equal([2, 3]); - expect(await verifier.hasClaimTopic(await claimIssuer.getAddress(), 2)).to.be.true; - expect(await verifier.hasClaimTopic(await claimIssuer.getAddress(), 1)).to.be.false; - }); - }); - - describe('when issuer address is the zero address', () => { - it('should revert', async () => { - const verifier = await ethers.deployContract('Verifier'); - - await expect(verifier.updateIssuerClaimTopics(ethers.ZeroAddress, [1])).to.be.revertedWith('invalid argument - zero address'); - }); - }); - - describe('when issuer is not trusted', () => { - it('should revert', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - - await expect(verifier.updateIssuerClaimTopics(await claimIssuer.getAddress(), [1])).to.be.revertedWith('NOT a trusted issuer'); - }); - }); - - describe('when list of topics contains more than 15 topics', () => { - it('should revert', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - await verifier.addTrustedIssuer(await claimIssuer.getAddress(), [1]); - - await expect(verifier.updateIssuerClaimTopics(await claimIssuer.getAddress(), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])).to.be.revertedWith('cannot have more than 15 claim topics'); - }); - }); - - describe('when list of topics is empty', () => { - it('should revert', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - await verifier.addTrustedIssuer(await claimIssuer.getAddress(), [1]); - - await expect(verifier.updateIssuerClaimTopics(await claimIssuer.getAddress(), [])).to.be.revertedWith('claim topics cannot be empty'); - }); - }); - }); - - describe('.getTrustedIssuerClaimTopic', () => { - describe('when issuer is not trusted', () => { - it('should revert', async () => { - const [deployer, aliceWallet] = await ethers.getSigners(); - const verifier = await ethers.deployContract('Verifier'); - const claimIssuer = await ethers.deployContract('ClaimIssuer', [aliceWallet.address]); - - await expect(verifier.getTrustedIssuerClaimTopics(await claimIssuer.getAddress())).to.be.revertedWith('trusted Issuer doesn\'t exist'); - }); - }); - }); -}); diff --git a/yarn.lock b/yarn.lock index 0f3b0b4..c5708fd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -860,11 +860,6 @@ resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== -"@onchain-id/solidity@^2.0.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@onchain-id/solidity/-/solidity-2.2.1.tgz#8bfc290ad75a95cf6a9803b786b3532fb9fd8c0a" - integrity sha512-B54InT8yi89qlh9UVCARcfdQLVDP7Lef87B/Ww2Wn19oyEbPmlWho2EK1sgnrt/8Q0fGX/7y5rDnx3HPy28NTA== - "@openzeppelin/contracts-upgradeable@^4.8.3": version "4.9.6" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.6.tgz#38b21708a719da647de4bb0e4802ee235a0d24df" @@ -5767,7 +5762,7 @@ string-format@^2.0.0: resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5784,15 +5779,6 @@ string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -5848,7 +5834,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -5862,13 +5848,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -6440,16 +6419,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==