├── packages ├── contracts │ ├── lib │ │ └── .gitkeep │ ├── tsconfig.json │ ├── test │ │ ├── vanchor │ │ │ └── mocks │ │ │ │ └── retryPromiseMock.ts │ │ ├── startGanache.ts │ │ └── token │ │ │ └── FungibleTokenWrapper.test.ts │ ├── tsconfig.build.json │ ├── foundry.toml │ ├── contracts │ │ ├── mocks │ │ │ ├── ERC20Mock.sol │ │ │ ├── ERC721Mock.sol │ │ │ ├── MerkleTreeMock.sol │ │ │ ├── MerkleForestMock.sol │ │ │ └── LinkableAnchorMock.sol │ │ ├── interfaces │ │ │ ├── external │ │ │ │ ├── chainalysis │ │ │ │ │ └── ISanctionsList.sol │ │ │ │ └── aave │ │ │ │ │ └── IAaveLendingPool.sol │ │ │ ├── verifiers │ │ │ │ ├── ISetVerifier.sol │ │ │ │ ├── IAnchorVerifier.sol │ │ │ │ └── IVAnchorVerifier.sol │ │ │ ├── tokens │ │ │ │ ├── IAaveTokenWrapper.sol │ │ │ │ ├── IMintableERC20.sol │ │ │ │ └── IFungibleTokenWrapper.sol │ │ │ ├── ITreasury.sol │ │ │ ├── IExecutor.sol │ │ │ └── ILinkableAnchor.sol │ │ ├── hashers │ │ │ ├── SnarkConstants.sol │ │ │ ├── IHasher.sol │ │ │ └── Poseidon.sol │ │ ├── utils │ │ │ ├── Initialized.sol │ │ │ ├── SanctionFilter.sol │ │ │ ├── ProposalNonceTracker.sol │ │ │ ├── ProofUtils.sol │ │ │ └── ChainIdWithType.sol │ │ ├── package.json │ │ ├── structs │ │ │ ├── Edge.sol │ │ │ ├── SingleAssetExtData.sol │ │ │ └── PublicInputs.sol │ │ ├── trees │ │ │ └── MerkleTree.sol │ │ ├── verifiers │ │ │ ├── TxProofVerifier.sol │ │ │ └── VAnchorVerifier.sol │ │ ├── vanchors │ │ │ ├── extensions │ │ │ │ └── ChainalysisVAnchor.sol │ │ │ └── instances │ │ │ │ ├── VAnchorTree.sol │ │ │ │ └── VAnchorForest.sol │ │ ├── handlers │ │ │ └── HandlerHelpers.sol │ │ ├── test │ │ │ └── TreasuryHandler.t.sol │ │ ├── Treasury.sol │ │ ├── tokens │ │ │ └── AaveTokenWrapper.sol │ │ └── DeterministicDeployFactory.sol │ ├── scripts │ │ └── deployFactory.js │ ├── README.md │ ├── LICENSE.MIT │ ├── package.json │ ├── hardhatAccounts.js │ └── hardhat.config.ts ├── create2-utils │ ├── src │ │ ├── index.ts │ │ └── Deployer.ts │ ├── tsconfig.json │ ├── tsconfig.build.json │ ├── README.md │ ├── package.json │ └── LICENSE.MIT ├── interfaces │ ├── src │ │ ├── IBridgeSide.ts │ │ ├── index.ts │ │ ├── IVAnchor.ts │ │ ├── bridge │ │ │ └── index.ts │ │ └── vanchor │ │ │ └── index.ts │ ├── tsconfig.json │ ├── tsconfig.build.json │ ├── README.md │ ├── package.json │ └── LICENSE.MIT ├── proposals │ ├── tsconfig.json │ ├── tsconfig.build.json │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── ProposalHeader.ts │ └── LICENSE.MIT ├── tokens │ ├── tsconfig.json │ ├── tsconfig.build.json │ ├── src │ │ ├── index.ts │ │ ├── erc │ │ │ ├── ERC20.ts │ │ │ └── ERC721.ts │ │ ├── TreasuryHandler.ts │ │ ├── TokenWrapperHandler.ts │ │ └── MintableToken.ts │ ├── README.md │ ├── package.json │ └── LICENSE.MIT ├── utils │ ├── tsconfig.json │ ├── src │ │ ├── bytes │ │ │ ├── index.ts │ │ │ ├── u8aToHex.ts │ │ │ └── hexToU8a.ts │ │ ├── index.ts │ │ ├── protocol │ │ │ ├── index.ts │ │ │ └── typed-chain-id.ts │ │ ├── __test__ │ │ │ ├── sign.spec.ts │ │ │ ├── typed-chain-id.spec.ts │ │ │ └── keypair.spec.ts │ │ └── proof │ │ │ ├── index.ts │ │ │ └── variable-anchor.ts │ ├── .mocharc.json │ ├── tsconfig.build.json │ ├── README.md │ ├── LICENSE.MIT │ └── package.json ├── vbridge │ ├── tsconfig.json │ ├── src │ │ └── index.ts │ ├── tsconfig.build.json │ ├── README.md │ ├── package.json │ └── LICENSE.MIT ├── evm-test-utils │ ├── tsconfig.json │ ├── src │ │ ├── index.ts │ │ ├── startGanacheServer.ts │ │ └── localTestnet.ts │ ├── tsconfig.build.json │ ├── package.json │ └── LICENSE.MIT └── anchors │ ├── typings.ts │ ├── tsconfig.json │ ├── tsconfig.build.json │ ├── src │ ├── index.ts │ ├── utils.ts │ ├── AnchorHandler.ts │ ├── types.ts │ └── extensions │ │ └── ChainalysisVAnchor.ts │ ├── README.md │ ├── package.json │ └── LICENSE.MIT ├── audits └── VAR_Webb_Tools.pdf ├── .github ├── assets │ ├── webb_banner_dark.png │ └── webb_banner_light.png └── workflows │ ├── check.yml │ ├── publish-packages.yml │ ├── publish-ts-docs.yml │ ├── forge.yml │ ├── test-check.yml │ └── codeql-analysis.yml ├── lerna.json ├── .envrc ├── circuits ├── main │ ├── batchMerkleTreeUpdate_16.circom │ ├── batchMerkleTreeUpdate_4.circom │ ├── batchMerkleTreeUpdate_32.circom │ ├── batchMerkleTreeUpdate_64.circom │ ├── batchMerkleTreeUpdate_8.circom │ ├── poseidon_vanchor_2_2.circom │ ├── poseidon_vanchor_2_8.circom │ ├── poseidon_vanchor_16_2.circom │ ├── poseidon_vanchor_16_8.circom │ ├── vanchor_forest_2_2.circom │ ├── vanchor_forest_2_8.circom │ ├── vanchor_forest_16_2.circom │ └── vanchor_forest_16_8.circom ├── vanchor │ └── keypair.circom ├── set │ ├── membership_wo_diffs.circom │ ├── membership.circom │ └── membership_if_enabled.circom └── merkle-tree │ ├── merkleTreeUpdater.circom │ ├── manyMerkleProof.circom │ ├── merkleTree.circom │ ├── merkleForest.circom │ └── treeUpdateArgsHasher.circom ├── .editorconfig ├── .changeset └── config.json ├── tsconfig.build.json ├── scripts └── bash │ ├── plonk │ ├── vanchor │ │ ├── phase2_poseidon_vanchor2.sh │ │ └── phase2_poseidon_vanchor8.sh │ └── phase2_circuit_plonk.sh │ ├── groth16 │ ├── vanchor │ │ ├── phase2_poseidon_vanchor8.sh │ │ ├── phase2_poseidon_vanchor2.sh │ │ ├── phase2_vanchor_forest2.sh │ │ └── phase2_vanchor_forest8.sh │ └── phase2_circuit_groth16.sh │ ├── build_circuits.sh │ ├── generate_phase1_ptau.sh │ └── build_circuits_plonk.sh ├── .gitignore ├── .gitmodules ├── typedoc-tsconfig.json ├── .prettierrc.json ├── .prettierignore ├── LICENSE.MIT ├── flake.nix ├── tsconfig.json ├── flake.lock └── package.json /packages/contracts/lib/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/contracts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } -------------------------------------------------------------------------------- /packages/create2-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export { Deployer } from './Deployer'; 2 | -------------------------------------------------------------------------------- /packages/interfaces/src/IBridgeSide.ts: -------------------------------------------------------------------------------- 1 | export interface IBridgeSide {} 2 | -------------------------------------------------------------------------------- /packages/proposals/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } -------------------------------------------------------------------------------- /packages/tokens/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } -------------------------------------------------------------------------------- /packages/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } -------------------------------------------------------------------------------- /packages/vbridge/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } -------------------------------------------------------------------------------- /packages/create2-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } -------------------------------------------------------------------------------- /packages/evm-test-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } -------------------------------------------------------------------------------- /packages/interfaces/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } -------------------------------------------------------------------------------- /packages/anchors/typings.ts: -------------------------------------------------------------------------------- 1 | declare module 'circomlibjs'; 2 | 3 | declare module 'snarkjs'; 4 | -------------------------------------------------------------------------------- /packages/utils/src/bytes/index.ts: -------------------------------------------------------------------------------- 1 | export * from './hexToU8a'; 2 | export * from './u8aToHex'; 3 | -------------------------------------------------------------------------------- /packages/vbridge/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './VBridge'; 2 | export * from './SignatureBridgeSide'; 3 | -------------------------------------------------------------------------------- /audits/VAR_Webb_Tools.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangle-network/protocol-solidity/HEAD/audits/VAR_Webb_Tools.pdf -------------------------------------------------------------------------------- /packages/utils/.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": "ts-node/register", 3 | "extensions": ["ts"], 4 | "spec": ["**/*.spec.*"] 5 | } -------------------------------------------------------------------------------- /.github/assets/webb_banner_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangle-network/protocol-solidity/HEAD/.github/assets/webb_banner_dark.png -------------------------------------------------------------------------------- /.github/assets/webb_banner_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tangle-network/protocol-solidity/HEAD/.github/assets/webb_banner_light.png -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*", 4 | "examples/*" 5 | ], 6 | "version": "independent", 7 | "npmClient": "yarn" 8 | } 9 | -------------------------------------------------------------------------------- /packages/evm-test-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './startGanacheServer'; 2 | export * from './localEvmChain'; 3 | export * from './localTestnet'; 4 | -------------------------------------------------------------------------------- /packages/interfaces/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './vanchor'; 2 | export * from './bridge'; 3 | export * from './IVAnchor'; 4 | export * from './IBridgeSide'; 5 | -------------------------------------------------------------------------------- /packages/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './utils'; 2 | export * from './bytes'; 3 | export * from './fixtures'; 4 | export * from './protocol'; 5 | export * from './proof'; 6 | -------------------------------------------------------------------------------- /packages/anchors/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "strict": true, 5 | "strictPropertyInitialization": false, 6 | } 7 | } -------------------------------------------------------------------------------- /packages/contracts/test/vanchor/mocks/retryPromiseMock.ts: -------------------------------------------------------------------------------- 1 | export async function retryPromiseMock Promise>( 2 | executor: T 3 | ): Promise> { 4 | return executor(); 5 | } 6 | -------------------------------------------------------------------------------- /packages/contracts/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/" 4 | }, 5 | "exclude": [], 6 | "extends": "../../tsconfig.build.json", 7 | "include": [ 8 | "./typechain-types/**/*.ts" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/interfaces/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": "./src/", 4 | "outDir": "./dist/", 5 | }, 6 | "exclude": [], 7 | "extends": "../../tsconfig.build.json", 8 | "include": [ 9 | "./src/**/*.ts", 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then 2 | source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" 3 | fi 4 | use flake 5 | dotenv_if_exists 6 | layout node 7 | 8 | # vi: ft=sh 9 | -------------------------------------------------------------------------------- /packages/contracts/foundry.toml: -------------------------------------------------------------------------------- 1 | [default] 2 | src = 'contracts' 3 | out = 'out' 4 | libs = ['lib'] 5 | test = 'test' 6 | remappings = [ 7 | '@openzeppelin/=lib/openzeppelin-contracts/', 8 | '@prb/test/=lib/prb-test/src/', 9 | 'forge-std/=lib/forge-std/src/', 10 | 'src/=src/', 11 | ] 12 | -------------------------------------------------------------------------------- /packages/utils/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": "./src/", 4 | "outDir": "./dist/", 5 | "baseUrl": "." 6 | }, 7 | "exclude": ["./src/**/*.spec.ts"], 8 | "extends": "../../tsconfig.build.json", 9 | "include": [ 10 | "./src/**/*.ts", 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/proposals/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": "./src/", 4 | "outDir": "./dist/", 5 | "baseUrl": "." 6 | }, 7 | "exclude": ["./src/**/*.spec.ts"], 8 | "extends": "../../tsconfig.build.json", 9 | "include": [ 10 | "./src/**/*.ts", 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /circuits/main/batchMerkleTreeUpdate_16.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../merkle-tree/batchMerkleTreeUpdate.circom"; 4 | 5 | /* var CHUNK_TREE_HEIGHT = 4 */ 6 | /* component main {public [argsHash]} = BatchTreeUpdate(20, 4, nthZero(4)); */ 7 | component main {public [argsHash]} = BatchTreeUpdate(20, 4, nthZero(4)); 8 | -------------------------------------------------------------------------------- /circuits/main/batchMerkleTreeUpdate_4.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../merkle-tree/batchMerkleTreeUpdate.circom"; 4 | 5 | /* var CHUNK_TREE_HEIGHT = 4 */ 6 | /* component main {public [argsHash]} = BatchTreeUpdate(20, 4, nthZero(4)); */ 7 | component main {public [argsHash]} = BatchTreeUpdate(20, 2, nthZero(2)); 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.sol] 4 | indent_style = space 5 | indent_size = 4 6 | trim_trailing_whitespace = true 7 | 8 | [*.ts] 9 | indent_style = space 10 | indent_size = 2 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | indent_style = space 15 | indent_size = 4 16 | max_line_length = 80 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /packages/vbridge/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": "./src/", 4 | "outDir": "./dist/", 5 | "baseUrl": ".", 6 | "paths": { 7 | "@webb-tools/*": ["../*/dist"] 8 | }, 9 | }, 10 | "extends": "../../tsconfig.build.json", 11 | "include": [ 12 | "src/**/*.ts", 13 | ] 14 | } -------------------------------------------------------------------------------- /packages/anchors/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": "./src/", 4 | "outDir": "./dist/", 5 | "baseUrl": ".", 6 | "paths": { 7 | "@webb-tools/*": ["../*/dist"] 8 | }, 9 | }, 10 | "exclude": [], 11 | "extends": "../../tsconfig.build.json", 12 | "include": [ 13 | "./src/*.ts", 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/tokens/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": "./src/", 4 | "outDir": "./dist/", 5 | "baseUrl": ".", 6 | "paths": { 7 | "@webb-tools/*": ["../*/dist"] 8 | }, 9 | }, 10 | "exclude": [], 11 | "extends": "../../tsconfig.build.json", 12 | "include": [ 13 | "./src/**/*.ts", 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/create2-utils/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": "./src/", 4 | "outDir": "./dist/", 5 | "baseUrl": ".", 6 | "paths": { 7 | "@webb-tools/*": ["../*/dist"] 8 | }, 9 | }, 10 | "exclude": [], 11 | "extends": "../../tsconfig.build.json", 12 | "include": [ 13 | "./src/**/*.ts", 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/evm-test-utils/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": "./src/", 4 | "outDir": "./dist/", 5 | "baseUrl": ".", 6 | "paths": { 7 | "@webb-tools/*": ["../*/dist"] 8 | }, 9 | }, 10 | "exclude": [], 11 | "extends": "../../tsconfig.build.json", 12 | "include": [ 13 | "./src/**/*.ts", 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/tokens/src/index.ts: -------------------------------------------------------------------------------- 1 | export { ERC20 } from './erc/ERC20'; 2 | export { ERC721 } from './erc/ERC721'; 3 | 4 | export { MintableToken } from './MintableToken'; 5 | export { TokenWrapperHandler } from './TokenWrapperHandler'; 6 | export { Treasury } from './Treasury'; 7 | export { TreasuryHandler } from './TreasuryHandler'; 8 | 9 | export { FungibleTokenWrapper } from './FungibleTokenWrapper'; 10 | -------------------------------------------------------------------------------- /packages/anchors/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AnchorHandler'; 2 | export * from './extensions/ChainalysisVAnchor'; 3 | export * from './extensions/RateLimitedVAnchor'; 4 | export * from './PoseidonHasher'; 5 | export * from './VAnchor'; 6 | export * from './VAnchorForest'; 7 | export * from './Common'; 8 | export * from './Verifier'; 9 | export * from './types'; 10 | 11 | export type RawPublicSignals = string[11]; 12 | -------------------------------------------------------------------------------- /packages/contracts/contracts/mocks/ERC20Mock.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | pragma solidity ^0.8.18; 6 | 7 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 8 | 9 | contract ERC20Mock is ERC20("DAIMock", "DAIM") { 10 | function mint(address account, uint256 amount) public { 11 | _mint(account, amount); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.6.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "linked": [], 6 | "access": "public", 7 | "baseBranch": "main", 8 | "updateInternalDependencies": "minor", 9 | "ignore": [""], 10 | "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { 11 | "onlyUpdatePeerDependentsWhenOutOfRange": true 12 | } 13 | } -------------------------------------------------------------------------------- /circuits/main/batchMerkleTreeUpdate_32.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../merkle-tree/batchMerkleTreeUpdate.circom"; 4 | 5 | /* var CHUNK_TREE_HEIGHT = 4 */ 6 | /* component main {public [argsHash]} = BatchTreeUpdate(20, 4, nthZero(4)); */ 7 | /* component main {public [argsHash]} = BatchTreeUpdate(20, 4, 17903822129909817717122288064678017104411031693253675943446999432073303897479); */ 8 | component main {public [argsHash]} = BatchTreeUpdate(20, 5, nthZero(5)); 9 | -------------------------------------------------------------------------------- /circuits/main/batchMerkleTreeUpdate_64.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../merkle-tree/batchMerkleTreeUpdate.circom"; 4 | 5 | /* var CHUNK_TREE_HEIGHT = 4 */ 6 | /* component main {public [argsHash]} = BatchTreeUpdate(20, 4, nthZero(4)); */ 7 | /* component main {public [argsHash]} = BatchTreeUpdate(20, 4, 17903822129909817717122288064678017104411031693253675943446999432073303897479); */ 8 | component main {public [argsHash]} = BatchTreeUpdate(20, 6, nthZero(6)); 9 | -------------------------------------------------------------------------------- /circuits/main/batchMerkleTreeUpdate_8.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../merkle-tree/batchMerkleTreeUpdate.circom"; 4 | 5 | /* var CHUNK_TREE_HEIGHT = 4 */ 6 | /* component main {public [argsHash]} = BatchTreeUpdate(20, 4, nthZero(4)); */ 7 | /* component main {public [argsHash]} = BatchTreeUpdate(20, 4, 17903822129909817717122288064678017104411031693253675943446999432073303897479); */ 8 | component main {public [argsHash]} = BatchTreeUpdate(20, 3, nthZero(3)); 9 | -------------------------------------------------------------------------------- /packages/contracts/contracts/mocks/ERC721Mock.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | pragma solidity ^0.8.18; 6 | 7 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 8 | 9 | contract ERC721Mintable is ERC721 { 10 | constructor(string memory name, string memory symbol) ERC721(name, symbol) {} 11 | 12 | function mint(address account, uint256 tokenId) public { 13 | _mint(account, tokenId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/contracts/scripts/deployFactory.js: -------------------------------------------------------------------------------- 1 | const ethers = require('hardhat').ethers; 2 | // import { ethers } from "hardhat"; 3 | 4 | const main = async () => { 5 | const Factory = await ethers.getContractFactory('DeterministicDeployFactory'); 6 | const factory = await Factory.deploy(); 7 | await factory.deployed(); 8 | console.log('Factory deployed to:', factory.address); 9 | }; 10 | 11 | main().catch((error) => { 12 | console.error(error); 13 | process.exitCode = 1; 14 | }); 15 | -------------------------------------------------------------------------------- /circuits/main/poseidon_vanchor_2_2.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../vanchor/transaction.circom"; 4 | 5 | // zeroLeaf = Poseidon(zero, zero) 6 | // default `zero` value is keccak256("tornado") % FIELD_SIZE = 21663839004416932945382355908790599225266501822907911457504978515578255421292 7 | component main {public [publicAmount, extDataHash, inputNullifier, outputCommitment, chainID, roots]} = Transaction(30, 2, 2, 11850551329423159860688778991827824730037759162201783566284850822760196767874, 2); -------------------------------------------------------------------------------- /circuits/main/poseidon_vanchor_2_8.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../vanchor/transaction.circom"; 4 | 5 | // zeroLeaf = Poseidon(zero, zero) 6 | // default `zero` value is keccak256("tornado") % FIELD_SIZE = 21663839004416932945382355908790599225266501822907911457504978515578255421292 7 | component main {public [publicAmount, extDataHash, inputNullifier, outputCommitment, chainID, roots]} = Transaction(30, 2, 2, 11850551329423159860688778991827824730037759162201783566284850822760196767874, 8); -------------------------------------------------------------------------------- /packages/contracts/contracts/mocks/MerkleTreeMock.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | pragma solidity ^0.8.18; 6 | 7 | import "../trees/MerkleTree.sol"; 8 | import "../hashers/IHasher.sol"; 9 | 10 | contract MerkleTreeMock is MerkleTree { 11 | constructor(uint32 _treeLevels, IHasher _hasher) MerkleTree(_treeLevels, _hasher) {} 12 | 13 | function insert(uint256 _leaf) public { 14 | _insert(_leaf); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /circuits/main/poseidon_vanchor_16_2.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../vanchor/transaction.circom"; 4 | 5 | // zeroLeaf = Poseidon(zero, zero) 6 | // default `zero` value is keccak256("tornado") % FIELD_SIZE = 21663839004416932945382355908790599225266501822907911457504978515578255421292 7 | component main {public [publicAmount, extDataHash, inputNullifier, outputCommitment, chainID, roots]} = Transaction(30, 16, 2, 11850551329423159860688778991827824730037759162201783566284850822760196767874, 2); 8 | -------------------------------------------------------------------------------- /circuits/main/poseidon_vanchor_16_8.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../vanchor/transaction.circom"; 4 | 5 | // zeroLeaf = Poseidon(zero, zero) 6 | // default `zero` value is keccak256("tornado") % FIELD_SIZE = 21663839004416932945382355908790599225266501822907911457504978515578255421292 7 | component main {public [publicAmount, extDataHash, inputNullifier, outputCommitment, chainID, roots]} = Transaction(30, 16, 2, 11850551329423159860688778991827824730037759162201783566284850822760196767874, 8); 8 | -------------------------------------------------------------------------------- /circuits/main/vanchor_forest_2_2.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../vanchor/transactionForest.circom"; 4 | 5 | // zeroLeaf = Poseidon(zero, zero) 6 | // default `zero` value is keccak256("tornado") % FIELD_SIZE = 21663839004416932945382355908790599225266501822907911457504978515578255421292 7 | component main {public [publicAmount, extDataHash, inputNullifier, outputCommitment, chainID, roots]} = TransactionForest(5, 30, 2, 2, 11850551329423159860688778991827824730037759162201783566284850822760196767874, 2); 8 | -------------------------------------------------------------------------------- /circuits/main/vanchor_forest_2_8.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../vanchor/transactionForest.circom"; 4 | 5 | // zeroLeaf = Poseidon(zero, zero) 6 | // default `zero` value is keccak256("tornado") % FIELD_SIZE = 21663839004416932945382355908790599225266501822907911457504978515578255421292 7 | component main {public [publicAmount, extDataHash, inputNullifier, outputCommitment, chainID, roots]} = TransactionForest(5, 30, 2, 2, 11850551329423159860688778991827824730037759162201783566284850822760196767874, 8); 8 | -------------------------------------------------------------------------------- /circuits/main/vanchor_forest_16_2.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../vanchor/transactionForest.circom"; 4 | 5 | // zeroLeaf = Poseidon(zero, zero) 6 | // default `zero` value is keccak256("tornado") % FIELD_SIZE = 21663839004416932945382355908790599225266501822907911457504978515578255421292 7 | component main {public [publicAmount, extDataHash, inputNullifier, outputCommitment, chainID, roots]} = TransactionForest(5, 30, 16, 2, 11850551329423159860688778991827824730037759162201783566284850822760196767874, 2); 8 | -------------------------------------------------------------------------------- /circuits/main/vanchor_forest_16_8.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../vanchor/transactionForest.circom"; 4 | 5 | // zeroLeaf = Poseidon(zero, zero) 6 | // default `zero` value is keccak256("tornado") % FIELD_SIZE = 21663839004416932945382355908790599225266501822907911457504978515578255421292 7 | component main {public [publicAmount, extDataHash, inputNullifier, outputCommitment, chainID, roots]} = TransactionForest(5, 30, 16, 2, 11850551329423159860688778991827824730037759162201783566284850822760196767874, 8); 8 | -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/external/chainalysis/ISanctionsList.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title SanctionsList interface for Chainalysis Sanctions List 9 | /// @author Chainalysis 10 | /// @notice This contract is meant to be used to check if an address is sanctioned. 11 | interface ISanctionsList { 12 | function isSanctioned(address addr) external view returns (bool); 13 | } 14 | -------------------------------------------------------------------------------- /packages/interfaces/README.md: -------------------------------------------------------------------------------- 1 |

Webb Interfaces

2 | 3 | Interfaces for various classes and types. 4 | 5 | ## License 6 | 7 | 8 | Licensed under Apache 2.0 / MIT license. 9 | 10 | 11 |
12 | 13 | 14 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the MIT OR Apache 2.0 license, shall be licensed as above, without any additional terms or conditions. 15 | 16 | 17 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": [ 3 | "node_modules/**/*", 4 | "**/node_modules/**/*", 5 | ], 6 | "include": [ 7 | "packages/**/*", 8 | "scripts/**/*", 9 | ], 10 | "compilerOptions": { 11 | "declaration": true, 12 | "downlevelIteration": true, 13 | "esModuleInterop": true, 14 | "module": "commonjs", 15 | "moduleResolution": "node", 16 | "target": "ES2017", 17 | "noEmitOnError": true, 18 | "skipLibCheck": true, 19 | "preserveSymlinks": true 20 | } 21 | } -------------------------------------------------------------------------------- /packages/contracts/contracts/hashers/SnarkConstants.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | pragma solidity ^0.8.18; 6 | 7 | /// @title SnarkConstants 8 | /// @author Webb Technologies. 9 | /// @notice This contract contains the SNARK scalar field. 10 | contract SnarkConstants { 11 | /// The scalar field 12 | uint256 internal constant SNARK_SCALAR_FIELD = 13 | 21888242871839275222246405745257275088548364400416034343698204186575808495617; 14 | } 15 | -------------------------------------------------------------------------------- /packages/create2-utils/README.md: -------------------------------------------------------------------------------- 1 |

Webb Solidity Utils

2 | 3 | This sub-module is for defining create2 utils. 4 | 5 | ## License 6 | 7 | 8 | Licensed under Apache 2.0 / MIT license. 9 | 10 | 11 |
12 | 13 | 14 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the MIT OR Apache 2.0 license, shall be licensed as above, without any additional terms or conditions. 15 | 16 | 17 | -------------------------------------------------------------------------------- /scripts/bash/plonk/vanchor/phase2_poseidon_vanchor2.sh: -------------------------------------------------------------------------------- 1 | echo "sourcing" 2 | source ./scripts/bash/plonk/phase2_circuit_plonk.sh 3 | 4 | echo "compiling" 5 | compile_phase2 ./build/vanchor_2/2 poseidon_vanchor_2_2 ./artifacts/circuits/vanchor_2 6 | echo "moving files" 7 | move_verifiers_and_metadata ./build/vanchor_2/2 2 vanchor_2 2 8 | 9 | echo "compiling" 10 | compile_phase2 ./build/vanchor_16/2 poseidon_vanchor_16_2 ./artifacts/circuits/vanchor_16 11 | echo "moving files" 12 | move_verifiers_and_metadata ./build/vanchor_16/2 2 vanchor_16 16 13 | -------------------------------------------------------------------------------- /scripts/bash/plonk/vanchor/phase2_poseidon_vanchor8.sh: -------------------------------------------------------------------------------- 1 | echo "sourcing" 2 | source ./scripts/bash/plonk/phase2_circuit_plonk.sh 3 | 4 | echo "compiling" 5 | compile_phase2 ./build/vanchor_2/8 poseidon_vanchor_2_8 ./artifacts/circuits/vanchor_2 6 | echo "moving files" 7 | move_verifiers_and_metadata ./build/vanchor_2/8 8 vanchor_2 2 8 | 9 | echo "compiling" 10 | compile_phase2 ./build/vanchor_16/8 poseidon_vanchor_16_8 ./artifacts/circuits/vanchor_16 11 | echo "moving files" 12 | move_verifiers_and_metadata ./build/vanchor_16/8 8 vanchor_16 16 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | .DS_STORE 4 | build/ 5 | *.env 6 | 7 | # Packages 8 | packages/*/node_modules 9 | packages/*/dist 10 | packages/*/tsconfig.tsbuildinfo 11 | 12 | # Typechain 13 | typechain-types 14 | typechain 15 | 16 | # Directories 17 | cache 18 | out 19 | artifacts 20 | 21 | dist 22 | 23 | *.ptau 24 | yarn-error.log 25 | 26 | # files 27 | *.log 28 | .DS_Store 29 | .pnp.* 30 | lcov.info 31 | yarn.lock 32 | 33 | # broadcasts 34 | !broadcast 35 | broadcast/* 36 | broadcast/*/31337/ 37 | .direnv 38 | 39 | coverage 40 | report 41 | -------------------------------------------------------------------------------- /packages/tokens/README.md: -------------------------------------------------------------------------------- 1 |

Webb Solidity Tokens

2 | 3 | This sub-module is for defining token-related functionality in webb solidity. 4 | 5 | ## License 6 | 7 | 8 | Licensed under Apache 2.0 / MIT license. 9 | 10 | 11 |
12 | 13 | 14 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the MIT OR Apache 2.0 license, shall be licensed as above, without any additional terms or conditions. 15 | 16 | 17 | -------------------------------------------------------------------------------- /scripts/bash/groth16/vanchor/phase2_poseidon_vanchor8.sh: -------------------------------------------------------------------------------- 1 | source ./scripts/bash/groth16/phase2_circuit_groth16.sh 2 | 3 | compile_phase2 ./solidity-fixtures/solidity-fixtures/vanchor_2/8 poseidon_vanchor_2_8 ./artifacts/circuits/vanchor_2 4 | move_verifiers_and_metadata_vanchor ./solidity-fixtures/solidity-fixtures/vanchor_2/8 8 vanchor_2 2 5 | 6 | compile_phase2 ./solidity-fixtures/solidity-fixtures/vanchor_16/8 poseidon_vanchor_16_8 ./artifacts/circuits/vanchor_16 7 | move_verifiers_and_metadata_vanchor ./solidity-fixtures/solidity-fixtures/vanchor_16/8 8 vanchor_16 16 -------------------------------------------------------------------------------- /packages/vbridge/README.md: -------------------------------------------------------------------------------- 1 |

Webb Variable Bridge

2 | 3 | This sub-module is for defining variable-bridge (vbridge) classes and functionality. 4 | 5 | ## License 6 | 7 | 8 | Licensed under Apache 2.0 / MIT license. 9 | 10 | 11 |
12 | 13 | 14 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the MIT OR Apache 2.0 license, shall be licensed as above, without any additional terms or conditions. 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/anchors/README.md: -------------------------------------------------------------------------------- 1 |

Webb Anchors

2 | 3 | Wrapper classes and utilities for deploying and interacting with zero-knowledge Anchors in solidity. 4 | 5 | ## License 6 | 7 | 8 | Licensed under Apache 2.0 / MIT license. 9 | 10 | 11 |
12 | 13 | 14 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the MIT OR Apache 2.0 license, shall be licensed as above, without any additional terms or conditions. 15 | 16 | 17 | -------------------------------------------------------------------------------- /scripts/bash/groth16/vanchor/phase2_poseidon_vanchor2.sh: -------------------------------------------------------------------------------- 1 | source ./scripts/bash/groth16/phase2_circuit_groth16.sh 2 | 3 | compile_phase2 ./solidity-fixtures/solidity-fixtures/vanchor_2/2 poseidon_vanchor_2_2 ./artifacts/circuits/vanchor_2 4 | move_verifiers_and_metadata_vanchor_forest ./solidity-fixtures/solidity-fixtures/vanchor_2/2 2 vanchor_2 2 5 | 6 | compile_phase2 ./solidity-fixtures/solidity-fixtures/vanchor_16/2 poseidon_vanchor_16_2 ./artifacts/circuits/vanchor_16 7 | move_verifiers_and_metadata_vanchor_forest ./solidity-fixtures/solidity-fixtures/vanchor_16/2 2 vanchor_16 16 8 | -------------------------------------------------------------------------------- /packages/utils/README.md: -------------------------------------------------------------------------------- 1 |

Webb Solidity Utils

2 | 3 | This sub-module is for defining common functionality / types used across other packages in webb solidity. 4 | 5 | ## License 6 | 7 | 8 | Licensed under Apache 2.0 / MIT license. 9 | 10 | 11 |
12 | 13 | 14 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the MIT OR Apache 2.0 license, shall be licensed as above, without any additional terms or conditions. 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/proposals/README.md: -------------------------------------------------------------------------------- 1 |

Webb Solidity Utils

2 | 3 | This sub-module is for defining common functionality / types used across other packages in webb solidity. 4 | 5 | ## License 6 | 7 | 8 | Licensed under Apache 2.0 / MIT license. 9 | 10 | 11 |
12 | 13 | 14 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the MIT OR Apache 2.0 license, shall be licensed as above, without any additional terms or conditions. 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/utils/src/protocol/index.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from 'ethers'; 2 | 3 | export const ZERO_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000000000000'; 4 | export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; 5 | 6 | export const FIELD_SIZE = BigNumber.from( 7 | '21888242871839275222246405745257275088548364400416034343698204186575808495617' 8 | ); 9 | 10 | export * from '../utils'; 11 | export * from './merkle-tree'; 12 | export * from './note'; 13 | export * from './utxo'; 14 | export * from './typed-chain-id'; 15 | export * from './keypair'; 16 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "packages/contracts/lib/forge-std"] 2 | path = packages/contracts/lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | [submodule "packages/contracts/lib/openzeppelin-contracts"] 5 | path = packages/contracts/lib/openzeppelin-contracts 6 | url = https://github.com/openzeppelin/openzeppelin-contracts 7 | [submodule "packages/contracts/lib/prb-test"] 8 | path = packages/contracts/lib/prb-test 9 | url = https://github.com/PaulRBerg/prb-test 10 | [submodule "solidity-fixtures"] 11 | path = solidity-fixtures 12 | url = https://github.com/webb-tools/solidity-fixtures.git 13 | -------------------------------------------------------------------------------- /scripts/bash/groth16/vanchor/phase2_vanchor_forest2.sh: -------------------------------------------------------------------------------- 1 | source ./scripts/bash/groth16/phase2_circuit_groth16.sh 2 | 3 | compile_phase2 ./solidity-fixtures/solidity-fixtures/vanchor_forest_2/2 vanchor_forest_2_2 ./artifacts/circuits/vanchor_forest_2 4 | move_verifiers_and_metadata_vanchor_forest ./solidity-fixtures/solidity-fixtures/vanchor_forest_2/2 2 vanchor_forest_2 2 5 | 6 | compile_phase2 ./solidity-fixtures/solidity-fixtures/vanchor_forest_16/2 vanchor_forest_16_2 ./artifacts/circuits/vanchor_forest_16 7 | move_verifiers_and_metadata_vanchor_forest ./solidity-fixtures/solidity-fixtures/vanchor_forest_16/2 2 vanchor_forest_16 16 8 | -------------------------------------------------------------------------------- /scripts/bash/groth16/vanchor/phase2_vanchor_forest8.sh: -------------------------------------------------------------------------------- 1 | source ./scripts/bash/groth16/phase2_circuit_groth16.sh 2 | 3 | compile_phase2 ./solidity-fixtures/solidity-fixtures/vanchor_forest_2/8 vanchor_forest_2_8 ./artifacts/circuits/vanchor_forest_2 4 | move_verifiers_and_metadata_vanchor_forest ./solidity-fixtures/solidity-fixtures/vanchor_forest_2/8 8 vanchor_forest_2 2 5 | 6 | compile_phase2 ./solidity-fixtures/solidity-fixtures/vanchor_forest_16/8 vanchor_forest_16_8 ./artifacts/circuits/vanchor_forest_16 7 | move_verifiers_and_metadata_vanchor_forest ./solidity-fixtures/solidity-fixtures/vanchor_forest_16/8 8 vanchor_forest_16 16 8 | -------------------------------------------------------------------------------- /typedoc-tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "lib": ["es2017", "dom"], 6 | "sourceMap": true, 7 | "declaration": true, 8 | "experimentalDecorators": true, 9 | "downlevelIteration": true, 10 | "noImplicitReturns": true, 11 | "resolveJsonModule": true, 12 | "preserveSymlinks": true, 13 | "pretty": true, 14 | "skipLibCheck": true, 15 | "strict": true, 16 | "exclude": [ 17 | "**/*.spec.ts", 18 | "**/*.test.ts" 19 | ] 20 | } 21 | } -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "overrides": [ 3 | { 4 | "files": "packages/**/*.sol", 5 | "options": { 6 | "printWidth": 100, 7 | "tabWidth": 4, 8 | "useTabs": true, 9 | "singleQuote": false, 10 | "bracketSpacing": true 11 | } 12 | }, 13 | { 14 | "files": [ 15 | "packages/**/*.{ts,tsx,js,jsx}", 16 | "scripts/**/*.{ts,tsx,js,jsx}" 17 | ], 18 | "options": { 19 | "printWidth": 100, 20 | "tabWidth": 2, 21 | "useTabs": false, 22 | "singleQuote": true, 23 | "bracketSpacing": true 24 | } 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/verifiers/ISetVerifier.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title Interface for setting the verifier for a contract. 9 | /// @author Webb Technologies. 10 | /// @notice This contract is meant to be used with the `VAnchor` contract. 11 | interface ISetVerifier { 12 | /// @notice Sets the verifier for the contract 13 | /// @param verifier The new verifier address 14 | /// @param nonce The nonce for tracking update counts 15 | function setVerifier(address verifier, uint32 nonce) external; 16 | } 17 | -------------------------------------------------------------------------------- /packages/contracts/README.md: -------------------------------------------------------------------------------- 1 |

Webb Solidity Contracts

2 | 3 | This sub-module is for defining types and factories for contracts of webb solidity. 4 | It is essentially the typechain-generated output packaged up and exposed for other areas of webb. 5 | 6 | ## License 7 | 8 | 9 | Licensed under Apache 2.0 / MIT license. 10 | 11 | 12 |
13 | 14 | 15 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the MIT OR Apache 2.0 license, shall be licensed as above, without any additional terms or conditions. 16 | 17 | 18 | -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/external/aave/IAaveLendingPool.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title Lending pool deposit/withdraw functionality for Aave 9 | /// @author Webb Technologies. 10 | /// @notice This contract is meant to be used with the `TokenWrapper.sol`. 11 | interface IAaveLendingPool { 12 | function deposit( 13 | address asset, 14 | uint256 amount, 15 | address onBehalfOf, 16 | uint16 referralCode 17 | ) external; 18 | 19 | function withdraw(address asset, uint256 amount, address to) external returns (uint256); 20 | } 21 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | .DS_STORE 4 | build/ 5 | .env 6 | 7 | *.md 8 | *.json 9 | *.cjs 10 | *.yml 11 | 12 | # Packages 13 | packages/contracts/typechain 14 | packages/*/node_modules 15 | packages/*/lib 16 | packages/*/dist 17 | packages/*/tsconfig.tsbuildinfo 18 | 19 | solidity-fixtures 20 | 21 | # Hardhat files 22 | cache 23 | artifacts 24 | typechain 25 | typechain-types 26 | /src 27 | 28 | dist 29 | 30 | *.ptau 31 | yarn-error.log 32 | 33 | # directories 34 | broadcast 35 | cache 36 | lib 37 | node_modules 38 | out 39 | 40 | # files 41 | *.env 42 | *.log 43 | .DS_Store 44 | .pnp.* 45 | lcov.info 46 | package-lock.json 47 | pnpm-lock.yaml 48 | yarn.lock 49 | 50 | -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/verifiers/IAnchorVerifier.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title IAnchorVerifier interface 9 | /// @notice A generic interface for verifying zero-knowledge proofs for anchors of different sizes. 10 | /// @dev This contract is meant to be used with the `VAnchor` contract. 11 | interface IAnchorVerifier { 12 | function verifyProof( 13 | uint[2] memory a, 14 | uint[2][2] memory b, 15 | uint[2] memory c, 16 | bytes memory input, 17 | uint8 maxEdges, 18 | bool smallInputs 19 | ) external view returns (bool r); 20 | } 21 | -------------------------------------------------------------------------------- /packages/contracts/contracts/utils/Initialized.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title A contract that can be initialized once and only once 9 | /// @author Webb Technologies. 10 | /// @notice This contract is used to ensure that a contract can only be initialized once. 11 | contract Initialized { 12 | bool public initialized; 13 | 14 | modifier onlyUninitialized() { 15 | require(!initialized, "Initialized: Already initialized"); 16 | _; 17 | } 18 | 19 | modifier onlyInitialized() { 20 | require(initialized, "Initialized: Not initialized"); 21 | _; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/contracts/contracts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webb-tools/protocol-solidity", 3 | "description": "Solidity contracts for protocol-solidity", 4 | "version": "1.1.1", 5 | "files": [ 6 | "**/*.sol" 7 | ], 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/webb-tools/protocol-solidity.git" 11 | }, 12 | "keywords": [ 13 | "solidity", 14 | "ethereum", 15 | "smart", 16 | "contracts", 17 | "security" 18 | ], 19 | "author": "Webb Developers ", 20 | "license": "(MIT OR Apache-2.0)", 21 | "bugs": { 22 | "url": "https://github.com/webb-tools/protocol-solidity/issues" 23 | }, 24 | "homepage": "https://webb.tools" 25 | } -------------------------------------------------------------------------------- /packages/interfaces/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webb-tools/interfaces", 3 | "main": "./dist/index.js", 4 | "license": "(MIT OR Apache-2.0)", 5 | "author": "Webb Developers ", 6 | "scripts": { 7 | "build": "yarn run clean && yarn run compile", 8 | "clean": "rimraf -rf ./dist", 9 | "compile": "tsc -p tsconfig.build.json" 10 | }, 11 | "dependencies": { 12 | "@webb-tools/utils": "^1.1.1" 13 | }, 14 | "publishConfig": { 15 | "access": "public" 16 | }, 17 | "repository": { 18 | "directory": "packages/interfaces", 19 | "type": "git", 20 | "url": "git://github.com/webb-tools/protocol-solidity.git" 21 | }, 22 | "version": "1.1.1", 23 | "gitHead": "e1f3b300b6e004ac5a346dc0458bb1d303969d97" 24 | } 25 | -------------------------------------------------------------------------------- /packages/contracts/contracts/structs/Edge.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @dev The Edge struct is used to store the edge data for linkable tree connections. 9 | /// @param chainId The chain id where the LinkableTree contract being linked is located. 10 | /// @param root The latest merkle root of the LinkableTree contract being linked. 11 | /// @param nonce The latest leaf insertion index of the LinkableTree contract being linked. 12 | /// @param srcResourceID The contract address or tree identifier of the LinkableTree being linked. 13 | struct Edge { 14 | uint256 chainID; 15 | uint256 root; 16 | uint256 latestLeafIndex; 17 | bytes32 srcResourceID; 18 | } 19 | -------------------------------------------------------------------------------- /circuits/vanchor/keypair.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../../node_modules/circomlib/circuits/poseidon.circom"; 4 | 5 | // Since we don't use signatures, the keypair can be based on a simple hash 6 | template Keypair() { 7 | signal input privateKey; 8 | signal output publicKey; 9 | 10 | component hasher = Poseidon(1); 11 | hasher.inputs[0] <== privateKey; 12 | publicKey <== hasher.out; 13 | } 14 | 15 | template Signature() { 16 | signal input privateKey; 17 | signal input commitment; 18 | signal input merklePath; 19 | signal output out; 20 | 21 | component hasher = Poseidon(3); 22 | hasher.inputs[0] <== privateKey; 23 | hasher.inputs[1] <== commitment; 24 | hasher.inputs[2] <== merklePath; 25 | out <== hasher.out; 26 | } -------------------------------------------------------------------------------- /packages/contracts/test/startGanache.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Webb Technologies Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import ganache from 'ganache'; 5 | 6 | export type GanacheAccounts = { 7 | balance: string; 8 | secretKey: string; 9 | }; 10 | 11 | export async function startGanacheServer( 12 | port: number, 13 | networkId: number, 14 | populatedAccounts: GanacheAccounts[], 15 | options: any = {} 16 | ) { 17 | const ganacheServer = ganache.server({ 18 | accounts: populatedAccounts, 19 | chainId: networkId, 20 | network_id: networkId, 21 | quiet: true, 22 | ...options, 23 | }); 24 | 25 | await ganacheServer.listen(port); 26 | console.log(`Ganache Started on http://127.0.0.1:${port} ..`); 27 | 28 | return ganacheServer; 29 | } 30 | -------------------------------------------------------------------------------- /packages/evm-test-utils/src/startGanacheServer.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Webb Technologies Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import ganache from 'ganache'; 5 | 6 | export type GanacheAccounts = { 7 | balance: string; 8 | secretKey: string; 9 | }; 10 | 11 | export async function startGanacheServer( 12 | port: number, 13 | networkId: number, 14 | populatedAccounts: GanacheAccounts[], 15 | options: any = {} 16 | ) { 17 | const ganacheServer = ganache.server({ 18 | accounts: populatedAccounts, 19 | chainId: networkId, 20 | network_id: networkId, 21 | quiet: true, 22 | ...options, 23 | }); 24 | 25 | await ganacheServer.listen(port); 26 | console.log(`Ganache Started on http://127.0.0.1:${port} ..`); 27 | 28 | return ganacheServer; 29 | } 30 | -------------------------------------------------------------------------------- /circuits/set/membership_wo_diffs.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../../node_modules/circomlib/circuits/comparators.circom"; 4 | 5 | template SetMembership(length) { 6 | signal input element; 7 | signal input set[length]; 8 | 9 | signal product[length + 1]; 10 | product[0] <== 1; 11 | 12 | component isEqualChecker[length]; 13 | component isZeroChecker[length]; 14 | 15 | for(var i = 0; i < length; i++) { 16 | isEqualChecker[i] = IsEqual(); 17 | isZeroChecker[i] = IsZero(); 18 | 19 | isEqualChecker[i].in[0] <== element; 20 | isEqualChecker[i].in[1] <== set[i]; 21 | 22 | isZeroChecker[i].in <== isEqualChecker[i].out; 23 | 24 | product[i + 1] <== product[i] * isZeroChecker[i].out; 25 | } 26 | 27 | product[length] === 0; 28 | } -------------------------------------------------------------------------------- /packages/proposals/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webb-tools/proposals", 3 | "main": "./dist/index.js", 4 | "license": "(MIT OR Apache-2.0)", 5 | "author": "Webb Developers ", 6 | "scripts": { 7 | "build": "yarn run clean && yarn run compile", 8 | "clean": "rimraf -rf ./dist", 9 | "compile": "tsc -p tsconfig.build.json", 10 | "test": "mocha -r ts-node/register 'src/__test__/**/*.ts'" 11 | }, 12 | "dependencies": { 13 | "@webb-tools/utils": "^1.1.1" 14 | }, 15 | "publishConfig": { 16 | "access": "public" 17 | }, 18 | "repository": { 19 | "directory": "packages/proposals", 20 | "type": "git", 21 | "url": "git://github.com/webb-tools/protocol-solidity.git" 22 | }, 23 | "version": "1.1.1", 24 | "gitHead": "e1f3b300b6e004ac5a346dc0458bb1d303969d97" 25 | } 26 | -------------------------------------------------------------------------------- /packages/create2-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webb-tools/create2-utils", 3 | "main": "./dist/index.js", 4 | "types": "./dist/index.d.ts", 5 | "license": "(MIT OR Apache-2.0)", 6 | "author": "Webb Developers ", 7 | "scripts": { 8 | "build": "yarn run clean && yarn run compile", 9 | "clean": "rimraf -rf ./dist", 10 | "compile": "tsc -p tsconfig.build.json" 11 | }, 12 | "dependencies": { 13 | "@webb-tools/contracts": "^1.1.1", 14 | "ethers": "5.7.0" 15 | }, 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "directory": "packages/create2-utils", 21 | "type": "git", 22 | "url": "git://github.com/webb-tools/protocol-solidity.git" 23 | }, 24 | "version": "1.1.1", 25 | "gitHead": "e1f3b300b6e004ac5a346dc0458bb1d303969d97" 26 | } 27 | -------------------------------------------------------------------------------- /packages/contracts/contracts/trees/MerkleTree.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | import "./MerkleTreeWithHistory.sol"; 9 | 10 | /// @title MerkleTree contract. 11 | /// @author Webb Technologies. 12 | /// @notice This contract is used to store the merkle tree data. 13 | contract MerkleTree is MerkleTreeWithHistory { 14 | constructor(uint32 _levels, IHasher _hasher) { 15 | require(_levels > 0, "_levels should be greater than zero"); 16 | require(_levels < 32, "_levels should be less than 32"); 17 | levels = _levels; 18 | hasher = _hasher; 19 | 20 | for (uint32 i = 0; i < _levels; i++) { 21 | filledSubtrees[i] = uint256(hasher.zeros(i)); 22 | } 23 | 24 | roots[0] = Root(uint256(hasher.zeros(_levels - 1)), 0); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/tokens/src/erc/ERC20.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers'; 2 | import { 3 | ERC20PresetMinterPauser as ERC20PresetMinterPauserContract, 4 | ERC20PresetMinterPauser__factory, 5 | } from '@webb-tools/contracts'; 6 | 7 | class ERC20 { 8 | contract: ERC20PresetMinterPauserContract; 9 | 10 | constructor(contract: ERC20PresetMinterPauserContract) { 11 | this.contract = contract; 12 | } 13 | 14 | public static async createERC20PresetMinterPauser( 15 | name: string, 16 | symbol: string, 17 | deployer: ethers.Signer 18 | ): Promise { 19 | const factory = new ERC20PresetMinterPauser__factory(deployer); 20 | const contract = await factory.deploy(name, symbol); 21 | await contract.deployed(); 22 | 23 | const handler = new ERC20(contract); 24 | return handler; 25 | } 26 | } 27 | 28 | export { ERC20 }; 29 | -------------------------------------------------------------------------------- /packages/tokens/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webb-tools/tokens", 3 | "main": "./dist/index.js", 4 | "license": "(MIT OR Apache-2.0)", 5 | "author": "Webb Developers ", 6 | "scripts": { 7 | "build": "yarn run clean && yarn run compile", 8 | "clean": "rimraf -rf ./dist", 9 | "compile": "tsc -p tsconfig.build.json" 10 | }, 11 | "dependencies": { 12 | "@webb-tools/contracts": "^1.1.1", 13 | "@webb-tools/create2-utils": "^1.1.1", 14 | "@webb-tools/utils": "^1.1.1", 15 | "ethers": "5.7.0" 16 | }, 17 | "publishConfig": { 18 | "access": "public" 19 | }, 20 | "repository": { 21 | "directory": "packages/tokens", 22 | "type": "git", 23 | "url": "git://github.com/webb-tools/protocol-solidity.git" 24 | }, 25 | "version": "1.1.1", 26 | "gitHead": "e1f3b300b6e004ac5a346dc0458bb1d303969d97" 27 | } 28 | -------------------------------------------------------------------------------- /packages/contracts/contracts/hashers/IHasher.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title Hasher interface for hashing 2 uint256 elements. 9 | /// @author Webb Technologies. 10 | /// @notice This contract is meant to be used to generalize over different hash functions. 11 | interface IHasher { 12 | function hash3(uint256[3] memory array) external view returns (uint256); 13 | 14 | function hash4(uint256[4] memory array) external view returns (uint256); 15 | 16 | /// @dev provides a 2 elemtns hash with left and right elements 17 | function hashLeftRight(uint256 _left, uint256 _right) external view returns (uint256); 18 | 19 | /// @dev provides Zero (Empty) elements for a IHasher based MerkleTree. Up to 32 levels 20 | function zeros(uint256 i) external view returns (bytes32); 21 | } 22 | -------------------------------------------------------------------------------- /packages/contracts/contracts/mocks/MerkleForestMock.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | pragma solidity ^0.8.18; 6 | 7 | import "../trees/MerkleForest.sol"; 8 | import "../hashers/IHasher.sol"; 9 | 10 | contract MerkleForestMock is MerkleForest { 11 | constructor( 12 | uint32 _forestLevels, 13 | uint32 _subtreeLevels, 14 | IHasher _hasher 15 | ) MerkleForest(_forestLevels, _subtreeLevels, _hasher) {} 16 | 17 | function insert(uint256 _leaf) public { 18 | _insert(_leaf); 19 | } 20 | 21 | function insertTwoTest(uint256 _leaf1, uint256 _leaf2) public { 22 | _insertTwo(_leaf1, _leaf2); 23 | } 24 | 25 | function insertTest(uint256 _leaf) public { 26 | _insert(_leaf); 27 | } 28 | 29 | function insertSubtreeTest(uint32 _subtreeId, uint256 _leaf) public { 30 | _insertSubtree(_subtreeId, _leaf); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/utils/src/__test__/sign.spec.ts: -------------------------------------------------------------------------------- 1 | import { signMessage } from '../utils'; 2 | import { Wallet } from 'ethers'; 3 | 4 | describe('signMessage constructor tests', () => { 5 | it('Should sign a message without throwing an error', async function () { 6 | const testPrivateKey = '0x0000000000000000000000000000000000000000000000000000000000000001'; 7 | const wallet = new Wallet(testPrivateKey); 8 | // Signing this messages trigger an error 9 | // that forces the code to execute the fallback in the catch block. 10 | // which is what we want to test. 11 | const message = 12 | '0x02f87684e78946d5148459682f0084648944a482520894f39fd6e51aad88f6f4ce6ab8827279cfffb92266880d96f6e53a4cdfd580c080a0ca72e1f12c44f0aa05c27993b9f03ac8f071497c4fb3f6f7bc68d21261b5f858a0552bfa27994327f777aa2ee496b3dd6a26ed6d980ce2fce849cdb6b2c08fe950'; 13 | signMessage(wallet, message); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /packages/contracts/contracts/utils/SanctionFilter.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | import "../interfaces/external/chainalysis/ISanctionsList.sol"; 7 | 8 | pragma solidity ^0.8.18; 9 | 10 | /// @title SanctionFilter contract. 11 | /// @notice This contract is used to filter out sanctioned addresses. 12 | /// @notice The hardcoded `SANCTIONS_CONTRACT` only exists on certain chains. 13 | /// Refer to https://go.chainalysis.com/chainalysis-oracle-docs.html for compatible chains. 14 | contract SanctionFilter { 15 | address constant SANCTIONS_CONTRACT = 0x40C57923924B5c5c5455c48D93317139ADDaC8fb; 16 | 17 | modifier isNotSanctioned(address addr) { 18 | ISanctionsList sanctionsList = ISanctionsList(SANCTIONS_CONTRACT); 19 | require(!sanctionsList.isSanctioned(addr), "SanctionFilter: Sanctioned address"); 20 | _; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/vbridge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webb-tools/vbridge", 3 | "main": "./dist/index.js", 4 | "license": "(MIT OR Apache-2.0)", 5 | "author": "Webb Developers ", 6 | "scripts": { 7 | "build": "yarn run clean && yarn run compile", 8 | "clean": "rimraf -rf ./dist", 9 | "compile": "tsc -p tsconfig.build.json" 10 | }, 11 | "dependencies": { 12 | "@webb-tools/anchors": "^1.1.1", 13 | "@webb-tools/contracts": "^1.1.1", 14 | "@webb-tools/interfaces": "^1.1.1", 15 | "@webb-tools/tokens": "^1.1.1", 16 | "@webb-tools/utils": "^1.1.1", 17 | "ethers": "5.7.0" 18 | }, 19 | "publishConfig": { 20 | "access": "public" 21 | }, 22 | "repository": { 23 | "directory": "packages/vbridge", 24 | "type": "git", 25 | "url": "git://github.com/webb-tools/protocol-solidity.git" 26 | }, 27 | "version": "1.1.1", 28 | "gitHead": "e1f3b300b6e004ac5a346dc0458bb1d303969d97" 29 | } 30 | -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/tokens/IAaveTokenWrapper.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title Interface for Aave Token Wrapper contract. 9 | /// @author Webb Technologies. 10 | /// @notice This contract is meant to be used with the `TokenWrapper` contract. 11 | interface IAaveTokenWrapper { 12 | /// @notice Deposits token at `_tokenAddress` into Aave Lending Pool 13 | /// @param _tokenAddress The address of the token to deposit 14 | /// @param _amount The amount to deposit 15 | function deposit(address _tokenAddress, uint256 _amount) external; 16 | 17 | /// @notice Withdraws token at `_tokenAddress` from Aave Lending Pool 18 | /// @param _tokenAddress The address of the token to withdraw 19 | /// @param _amount The amount to withdraw 20 | function withdraw(address _tokenAddress, uint256 _amount) external; 21 | } 22 | -------------------------------------------------------------------------------- /packages/contracts/contracts/utils/ProposalNonceTracker.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title A contract that can be initialized once and only once 9 | /// @author Webb Technologies. 10 | /// @notice This contract tracks nonces for proposal execution. 11 | contract ProposalNonceTracker { 12 | uint32 public proposalNonce; 13 | 14 | modifier manyIncrementingByOne(uint32[] memory nonces) { 15 | for (uint256 i = 0; i < nonces.length; i++) { 16 | require( 17 | nonces[i] == proposalNonce + 1, 18 | "ProposalNonceTracker: Nonce must increment by 1" 19 | ); 20 | proposalNonce = nonces[i]; 21 | } 22 | _; 23 | } 24 | 25 | modifier onlyIncrementingByOne(uint32 nonce) { 26 | require(nonce == proposalNonce + 1, "ProposalNonceTracker: Nonce must increment by 1"); 27 | proposalNonce = nonce; 28 | _; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/contracts/contracts/hashers/Poseidon.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title Poseidon hash functions for 2, 3, 4, 5, and 6 input elements. 9 | /// @author Webb Technologies. 10 | /// @notice These contracts are meant to be used in the `PoseidonHasher.sol` 11 | library PoseidonT2 { 12 | function poseidon(uint256[1] memory input) public pure returns (uint256) {} 13 | } 14 | 15 | library PoseidonT3 { 16 | function poseidon(uint256[2] memory input) public pure returns (uint256) {} 17 | } 18 | 19 | library PoseidonT4 { 20 | function poseidon(uint256[3] memory input) public pure returns (uint256) {} 21 | } 22 | 23 | library PoseidonT5 { 24 | function poseidon(uint256[4] memory input) public pure returns (uint256) {} 25 | } 26 | 27 | library PoseidonT6 { 28 | function poseidon(uint256[5] memory input) public pure returns (uint256) {} 29 | } 30 | -------------------------------------------------------------------------------- /packages/contracts/contracts/utils/ProofUtils.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2022 Webb Technologies 3 | * SPDX-License-Identifier: GPL-3.0-or-later-only 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title ProofUtils contract. 9 | /// @author Webb Technologies. 10 | /// @notice This contract is used to unpack the proof values. 11 | contract ProofUtils { 12 | /// @notice A helper function to convert an array of 8 uint256 values into the a, b, 13 | /// and c array values that the zk-SNARK verifier's verifyProof accepts. 14 | /// @param _proof The array of 8 uint256 values 15 | /// @return (uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c) The unpacked proof values 16 | function unpackProof( 17 | uint256[8] memory _proof 18 | ) public pure returns (uint256[2] memory, uint256[2][2] memory, uint256[2] memory) { 19 | return ( 20 | [_proof[0], _proof[1]], 21 | [[_proof[2], _proof[3]], [_proof[4], _proof[5]]], 22 | [_proof[6], _proof[7]] 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/evm-test-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webb-tools/evm-test-utils", 3 | "main": "./dist/index.js", 4 | "types": "./dist/index.d.ts", 5 | "license": "(MIT OR Apache-2.0)", 6 | "author": "Webb Developers ", 7 | "scripts": { 8 | "build": "yarn run clean && yarn run compile", 9 | "clean": "rimraf -rf ./dist", 10 | "compile": "tsc -p tsconfig.build.json" 11 | }, 12 | "dependencies": { 13 | "@webb-tools/interfaces": "^1.1.1", 14 | "@webb-tools/utils": "^1.1.1", 15 | "@webb-tools/vbridge": "^1.1.1", 16 | "ecpair": "^2.0.1", 17 | "ethers": "5.7.0", 18 | "ganache": "7.5.0", 19 | "tiny-secp256k1": "^2.2.1" 20 | }, 21 | "publishConfig": { 22 | "access": "public" 23 | }, 24 | "repository": { 25 | "directory": "packages/evm-test-utils", 26 | "type": "git", 27 | "url": "git://github.com/webb-tools/protocol-solidity.git" 28 | }, 29 | "version": "1.1.1", 30 | "gitHead": "e1f3b300b6e004ac5a346dc0458bb1d303969d97" 31 | } 32 | -------------------------------------------------------------------------------- /packages/interfaces/src/IVAnchor.ts: -------------------------------------------------------------------------------- 1 | import { MerkleProof, Utxo } from '@webb-tools/utils'; 2 | import { ethers, BaseContract } from 'ethers'; 3 | 4 | export interface IVAnchor { 5 | signer: ethers.Signer; 6 | contract: A; 7 | latestSyncedBlock: number; 8 | token?: string; 9 | 10 | setSigner(signer: ethers.Signer); 11 | 12 | getToken(): Promise; 13 | getContract(): Promise; 14 | 15 | getProposalData(resourceID: string, leafIndex?: number): Promise; 16 | getHandler(): Promise; 17 | getHandlerProposalData(newHandler: string): Promise; 18 | getAddress(): string; 19 | getMinWithdrawalLimitProposalData(_minimumWithdrawalAmount: string): Promise; 20 | getMaxDepositLimitProposalData(_maximumDepositAmount: string): Promise; 21 | createResourceId(): Promise; 22 | update(blockNumber?: number): Promise; 23 | 24 | // VAnchor methods 25 | getMerkleProof(input: Utxo, leavesMap?: Uint8Array[]): MerkleProof; 26 | } 27 | -------------------------------------------------------------------------------- /packages/anchors/src/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2023 @webb-tools/ 2 | // File contains all the utility functions used in the anchors package 3 | 4 | import { TransactionOptions } from './types'; 5 | 6 | export const zeroAddress = '0x0000000000000000000000000000000000000000'; 7 | 8 | /** 9 | * Checks if the given address is a native address 10 | * @param tokenAddress the address of the token to check 11 | * @returns true if the token is a native token 12 | */ 13 | export function checkNativeAddress(tokenAddress: string): boolean { 14 | if (tokenAddress === zeroAddress || tokenAddress === '0') { 15 | return true; 16 | } 17 | return false; 18 | } 19 | 20 | export function splitTransactionOptions( 21 | options?: T & TransactionOptions 22 | ): [T, TransactionOptions] { 23 | const { keypair, treeChainId, externalLeaves, onTransactionState, ...rest } = options ?? {}; 24 | 25 | return [rest, { keypair, treeChainId, externalLeaves, onTransactionState }] as [ 26 | T, 27 | TransactionOptions 28 | ]; 29 | } 30 | -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/ITreasury.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title Interface for Treasury contract. 9 | /// @author Webb Technologies. 10 | interface ITreasury { 11 | /// @notice Sends an `_amountToRescue` of tokens at `_tokenAddress` from the treasury contract to `_to` 12 | /// @param _tokenAddress Address of the token to rescue. 13 | /// @param _to Address of the recipient. 14 | /// @param _amountToRescue Amount of tokens to rescue. 15 | /// @param _nonce Nonce of the rescue transaction. 16 | function rescueTokens( 17 | address _tokenAddress, 18 | address payable _to, 19 | uint256 _amountToRescue, 20 | uint32 _nonce 21 | ) external; 22 | 23 | /// @notice Sets the handler responsible with relaying rescue transactions. 24 | /// @param _newHandler Address of the handler. 25 | /// @param _nonce Nonce of the update. 26 | function setHandler(address _newHandler, uint32 _nonce) external; 27 | } 28 | -------------------------------------------------------------------------------- /packages/proposals/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Webb Technologies Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | // Flags used to indicate the type of encoding to be used 19 | // in various encoding functions. 20 | // 21 | // For example: `const nonce = new DataView(bytes.buffer).getUint32(36, BE);` 22 | export const LE = true; 23 | export const BE = false; 24 | 25 | export * from './ProposalHeader'; 26 | export * from './ResourceId'; 27 | export * from './ProposalKinds'; 28 | -------------------------------------------------------------------------------- /packages/anchors/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webb-tools/anchors", 3 | "main": "./dist/index.js", 4 | "types": "./dist/index.d.ts", 5 | "license": "(MIT OR Apache-2.0)", 6 | "author": "Webb Developers ", 7 | "version": "1.1.1", 8 | "scripts": { 9 | "build": "yarn run clean && yarn run compile", 10 | "clean": "rimraf -rf ./dist", 11 | "compile": "tsc -p tsconfig.build.json" 12 | }, 13 | "dependencies": { 14 | "@webb-tools/contracts": "^1.1.1", 15 | "@webb-tools/create2-utils": "^1.1.1", 16 | "@webb-tools/interfaces": "^1.1.1", 17 | "@webb-tools/tokens": "^1.1.1", 18 | "@webb-tools/utils": "^1.1.1", 19 | "circomlibjs": "^0.0.8", 20 | "ethers": "5.7.0", 21 | "jssha": "^3.2.0", 22 | "snarkjs": "^0.7.2" 23 | }, 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "gitHead": "e1f3b300b6e004ac5a346dc0458bb1d303969d97", 28 | "repository": { 29 | "directory": "packages/anchors", 30 | "type": "git", 31 | "url": "git://github.com/webb-tools/protocol-solidity.git" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Webb Technologies Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /packages/anchors/LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Webb Technologies Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /packages/tokens/LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Webb Technologies Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /packages/utils/LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Webb Technologies Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /packages/vbridge/LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Webb Technologies Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /packages/contracts/LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Webb Technologies Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /packages/create2-utils/LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Webb Technologies Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /packages/interfaces/LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Webb Technologies Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /packages/proposals/LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Webb Technologies Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /circuits/set/membership.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../../node_modules/circomlib/circuits/comparators.circom"; 4 | 5 | // Set membership gadget is handled with a multiplicative trick. 6 | // 7 | // For a given set of elements, a prover first computes the difference between 8 | // each element in the set and the element they are proving knowledge of. We 9 | // constrain this operation accordingly. We then multiply all differences and constrain 10 | // this value by zero. If the prover actually knows an element in the set then for that 11 | // element, it must hold that the difference is 0. Therefore, the product of 0 and 12 | // anything else should be 0. The prove can't lie by adding a zero into the diffs set 13 | // because we constrain those to match all elements in the set respectively. 14 | template SetMembership(length) { 15 | signal input element; 16 | signal input set[length]; 17 | 18 | signal diffs[length]; 19 | signal product[length + 1]; 20 | product[0] <== 1; 21 | 22 | for (var i = 0; i < length; i++) { 23 | diffs[i] <== set[i] - element; 24 | product[i + 1] <== product[i] * diffs[i]; 25 | } 26 | 27 | product[length] === 0; 28 | } 29 | -------------------------------------------------------------------------------- /packages/evm-test-utils/LICENSE.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Webb Technologies Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/tokens/IMintableERC20.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title Interface for a mintable ERC20 token contract. 9 | /// @author Webb Technologies. 10 | interface IMintableERC20 { 11 | /// @dev Mints `amount` tokens to account `to`. 12 | /// @notice Emits a {Transfer} event. 13 | function mint(address to, uint256 amount) external; 14 | 15 | /// @dev Moves `amount` tokens from the caller's account to `recipient`. 16 | /// @dev Returns a boolean value indicating whether the operation succeeded. 17 | /// @notice Emits a {Transfer} event. 18 | function transfer(address recipient, uint256 amount) external returns (bool); 19 | 20 | /// @dev Moves `amount` tokens from `sender` to `recipient` using theallowance mechanism. `amount` is then deducted from the caller'sallowance. 21 | /// @dev Returns a boolean value indicating whether the operation succeeded. 22 | /// @notice Emits a {Transfer} event. 23 | function transferFrom( 24 | address sender, 25 | address recipient, 26 | uint256 amount 27 | ) external returns (bool); 28 | } 29 | -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/IExecutor.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title Interface for handler contracts that support proposal executions. 9 | /// @author Webb Technologies, adapted from ChainSafe Systems. 10 | /// @notice This contract is meant to be used with the `Bridge` and `Handler` contract. 11 | interface IExecutor { 12 | /// @notice It is intended that proposals are executed by the Bridge contract. 13 | /// @param data Consists of additional data needed for a specific deposit execution. 14 | function executeProposal(bytes32 resourceID, bytes calldata data) external; 15 | 16 | /// @notice Correlates {resourceID} with {contractAddress}. 17 | /// @param resourceID ResourceID to be used when making deposits. 18 | /// @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. 19 | function setResource(bytes32 resourceID, address contractAddress) external; 20 | 21 | /// @notice Migrates the bridge to a new bridge address 22 | /// @param newBridge New bridge address 23 | function migrateBridge(address newBridge) external; 24 | } 25 | -------------------------------------------------------------------------------- /circuits/set/membership_if_enabled.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../../node_modules/circomlib/circuits/comparators.circom"; 4 | 5 | // Set membership gadget is handled with a multiplicative trick. 6 | // 7 | // For a given set of elements, a prover first computes the difference between 8 | // each element in the set and the element they are proving knowledge of. We 9 | // constrain this operation accordingly. We then multiply all differences and constrain 10 | // this value by zero. If the prover actually knows an element in the set then for that 11 | // element, it must hold that the difference is 0. Therefore, the product of 0 and 12 | // anything else should be 0. The prove can't lie by adding a zero into the diffs set 13 | // because we constrain those to match all elements in the set respectively. 14 | template ForceSetMembershipIfEnabled(length) { 15 | signal input element; 16 | signal input set[length]; 17 | signal input enabled; 18 | 19 | signal diffs[length]; 20 | signal product[length + 1]; 21 | 22 | product[0] <== 1; 23 | 24 | for (var i = 0; i < length; i++) { 25 | diffs[i] <== set[i] - element; 26 | product[i + 1] <== product[i] * diffs[i]; 27 | } 28 | 29 | product[length]*enabled === 0; 30 | } 31 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Webb Protocol Solidity development environment"; 3 | inputs = { 4 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 5 | flake-utils.url = "github:numtide/flake-utils"; 6 | foundry = { 7 | url = "github:shazow/foundry.nix"; 8 | inputs = { 9 | nixpkgs.follows = "nixpkgs"; 10 | flake-utils.follows = "flake-utils"; 11 | }; 12 | }; 13 | }; 14 | 15 | outputs = { self, nixpkgs, foundry, flake-utils }: 16 | flake-utils.lib.eachDefaultSystem (system: 17 | let 18 | overlays = [ foundry.overlay ]; 19 | pkgs = import nixpkgs { 20 | inherit system overlays; 21 | }; 22 | in 23 | { 24 | devShells.default = pkgs.mkShell { 25 | name = "protocol-solidity"; 26 | nativeBuildInputs = [ ]; 27 | buildInputs = [ 28 | # Nodejs for test suite 29 | pkgs.nodePackages.typescript-language-server 30 | pkgs.nodejs_18 31 | pkgs.nodePackages.yarn 32 | # Used for DVC 33 | pkgs.python311 34 | pkgs.python311Packages.pipx 35 | 36 | pkgs.foundry-bin 37 | ]; 38 | packages = [ ]; 39 | }; 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /packages/contracts/contracts/structs/SingleAssetExtData.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title SingleAssetExtData struct for encoding external data for single asset proofs 9 | /// @author Webb Technologies. 10 | /// @notice This contract is meant to be used to encode external data for hashing to verify proofs. 11 | 12 | /// @dev The SingleAssetExtData struct is used to store the external data for single asset proofs. 13 | /// @param recipient The recipient of the transaction 14 | /// @param extAmount The external amount being transferred 15 | /// @param relayer The relayer of the transaction 16 | /// @param fee The fee for the transaction 17 | /// @param refund The refund for the transaction 18 | /// @param token The token being wrapped/unwrapped or transferred if its the shielded pool token 19 | /// @param encryptedOutput1 The encrypted output 1 for the transaction 20 | /// @param encryptedOutput2 The encrypted output 2 for the transaction 21 | struct ExtData { 22 | address recipient; 23 | int256 extAmount; 24 | address relayer; 25 | uint256 fee; 26 | uint256 refund; 27 | address token; 28 | bytes encryptedOutput1; 29 | bytes encryptedOutput2; 30 | } 31 | -------------------------------------------------------------------------------- /circuits/merkle-tree/merkleTreeUpdater.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "./merkleTree.circom"; 4 | 5 | // inserts a leaf into a tree 6 | // checks that tree previously contained zero in the same position 7 | template MerkleTreeUpdater(levels, zeroLeaf) { 8 | signal input oldRoot; 9 | signal input newRoot; 10 | signal input leaf; 11 | signal input pathIndices; 12 | signal input pathElements[levels]; 13 | // Compute indexBits once for both trees 14 | // Since Num2Bits is non deterministic, 2 duplicate calls to it cannot be 15 | // optimized by circom compiler 16 | component indexBits = Num2Bits(levels); 17 | indexBits.in <== pathIndices; 18 | 19 | component treeBefore = RawMerkleTree(levels); 20 | for(var i = 0; i < levels; i++) { 21 | treeBefore.pathIndices[i] <== indexBits.out[i]; 22 | treeBefore.pathElements[i] <== pathElements[i]; 23 | } 24 | treeBefore.leaf <== zeroLeaf; 25 | treeBefore.root === oldRoot; 26 | 27 | component treeAfter = RawMerkleTree(levels); 28 | for(var i = 0; i < levels; i++) { 29 | treeAfter.pathIndices[i] <== indexBits.out[i]; 30 | treeAfter.pathElements[i] <== pathElements[i]; 31 | } 32 | treeAfter.leaf <== leaf; 33 | treeAfter.root === newRoot; 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: check 2 | 3 | on: 4 | push: 5 | branches: [ 'main' ] 6 | pull_request: 7 | types: [opened, synchronize, reopened, ready_for_review] 8 | branches: [ '**' ] 9 | paths-ignore: 10 | - 'README.md' 11 | 12 | workflow_dispatch: 13 | 14 | jobs: 15 | ts: 16 | concurrency: 17 | group: ts-${{ github.ref }} 18 | cancel-in-progress: true 19 | runs-on: ubuntu-latest 20 | strategy: 21 | matrix: 22 | node-version: [18.15.0] 23 | steps: 24 | - uses: actions/checkout@v3 25 | - name: Use Node.js ${{ matrix.node-version }} 26 | uses: actions/setup-node@v1 27 | with: 28 | node-version: ${{ matrix.node-version }} 29 | - name: Setup DVC 30 | uses: iterative/setup-dvc@v1 31 | 32 | - name: Fetch submodules 33 | run: git submodule update --init --recursive 34 | 35 | - name: Install dependencies 36 | run: yarn install --production=false 37 | 38 | - name: Populate fixtures 39 | run: yarn fetch:fixtures 40 | 41 | - name: clean 42 | run: yarn clean 43 | 44 | - name: Compile @webb-tools/contracts 45 | run: lerna run compile --scope=@webb-tools/contracts 46 | 47 | - name: Build packages 48 | run: lerna run build 49 | 50 | - name: ts-check 51 | run: yarn ts-check 52 | -------------------------------------------------------------------------------- /packages/contracts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webb-tools/contracts", 3 | "main": "./dist/index.js", 4 | "types": "./dist/index.d.ts", 5 | "license": "(MIT OR Apache-2.0)", 6 | "author": "Webb Developers ", 7 | "scripts": { 8 | "build:contracts": "npx hardhat compile", 9 | "build:library": "tsc -p tsconfig.build.json", 10 | "compile": "yarn compile:contracts && yarn build:library && yarn copy:declarations", 11 | "compile:contracts": "yarn run clean && yarn run build:contracts", 12 | "copy:declarations": "copyfiles -f ./typechain-types/*.d.ts ./dist", 13 | "build": "tsc -p tsconfig.build.json", 14 | "clean": "rimraf -rf ./dist && rimraf -rf ./typechain-types && rimraf -rf ./cache && rimraf -rf ./artifacts", 15 | "test": "npx hardhat test", 16 | "test:parallel": "npx hardhat test --parallel", 17 | "test:gas-reporter": "REPORT_GAS=true npx hardhat test --parallel" 18 | }, 19 | "publishConfig": { 20 | "access": "public" 21 | }, 22 | "repository": { 23 | "directory": "packages/contracts", 24 | "type": "git", 25 | "url": "git://github.com/webb-tools/protocol-solidity.git" 26 | }, 27 | "version": "1.1.1", 28 | "gitHead": "e1f3b300b6e004ac5a346dc0458bb1d303969d97", 29 | "dependencies": { 30 | "@ethersproject/abi": "^5.7.0", 31 | "@ethersproject/providers": "^5.7.2", 32 | "ethers": "^5.7.0", 33 | "typescript": "^5.0.4" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/publish-packages.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | # Only publish when changes are made to the following paths 8 | paths: 9 | - 'packages/**' 10 | - 'circuits/**' 11 | 12 | concurrency: ${{ github.workflow }}-${{ github.ref }} 13 | 14 | jobs: 15 | release: 16 | name: Packages 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout Repo 20 | uses: actions/checkout@v3 21 | 22 | - name: Setup Node.js 18.x 23 | uses: actions/setup-node@v3 24 | with: 25 | node-version: 18.15.x 26 | 27 | - name: Install Dependencies 28 | run: yarn 29 | 30 | - name: Publish to NPM registry 31 | id: changesets 32 | uses: changesets/action@v1 33 | with: 34 | # auto publishes PATCH version bump 35 | publish: yarn publish:ci 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.PA_GITHUB_TOKEN }} 38 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 39 | 40 | - name: Slack Notification 41 | if: steps.changesets.outputs.published == 'true' 42 | uses: rtCamp/action-slack-notify@v2 43 | env: 44 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} 45 | SLACK_USERNAME: 'Webb-Bot' 46 | SLACK_CHANNEL: '#webb-protocol-solidity' 47 | SLACK_MESSAGE: 'A new version of ${GITHUB_REPOSITORY} packages was published!' -------------------------------------------------------------------------------- /.github/workflows/publish-ts-docs.yml: -------------------------------------------------------------------------------- 1 | name: Publish Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | # Only publish when changes are made to the following paths 8 | paths: 9 | - 'packages/**' 10 | - 'circuits/**' 11 | 12 | pull_request: 13 | branches: 14 | - main 15 | # Only publish when changes are made to the following paths 16 | paths: 17 | - 'packages/**' 18 | - 'circuits/**' 19 | 20 | jobs: 21 | publish-docs: 22 | if: github.event_name == 'push' && github.event.ref == 'refs/heads/main' 23 | name: Publish Documentation 24 | runs-on: ubuntu-20.04 25 | steps: 26 | - uses: actions/checkout@v2 27 | 28 | - name: Setup Node.js 29 | uses: actions/setup-node@v2 30 | 31 | - name: Install dependencies 32 | - run: git submodule update --init --recursive 33 | - run: cd solidity-fixtures && dvc pull && cd .. 34 | - run: yarn install --production=false 35 | - run: yarn compile 36 | - run: yarn build:packages 37 | - run: cd ./packages/protocol-solidity && yarn install 38 | - name: Generate docs 39 | run: | 40 | cd ./packages/protocol-solidity && npx typedoc --out docs src/index.ts 41 | 42 | - name: Deploy docs 🚀 43 | uses: JamesIves/github-pages-deploy-action@4.1.4 44 | with: 45 | branch: gh-pages 46 | folder: ./packages/protocol-solidity/docs -------------------------------------------------------------------------------- /packages/tokens/src/erc/ERC721.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers'; 2 | import { ERC721Mintable as ERC721Contract, ERC721Mintable__factory } from '@webb-tools/contracts'; 3 | 4 | class ERC721 { 5 | contract: ERC721Contract; 6 | 7 | constructor(contract: ERC721Contract) { 8 | this.contract = contract; 9 | } 10 | 11 | public static async createERC721( 12 | name: string, 13 | symbol: string, 14 | deployer: ethers.Signer 15 | ): Promise { 16 | const factory = new ERC721Mintable__factory(deployer); 17 | const contract = await factory.deploy(name, symbol); 18 | await contract.deployed(); 19 | 20 | const handler = new ERC721(contract); 21 | return handler; 22 | } 23 | 24 | public static async connect(tokenAddress: string, signer: ethers.Signer) { 25 | const tokenContract = ERC721Mintable__factory.connect(tokenAddress, signer); 26 | const token = new ERC721(tokenContract); 27 | return token; 28 | } 29 | 30 | public async mint(to: string, tokenId: number) { 31 | const tx = await this.contract.mint(to, tokenId); 32 | await tx.wait(); 33 | } 34 | 35 | public async approve(to: string, tokenId: number) { 36 | const tx = await this.contract.approve(to, tokenId); 37 | await tx.wait(); 38 | } 39 | 40 | public async transferFrom(from: string, to: string, tokenId: number) { 41 | const tx = await this.contract.transferFrom(from, to, tokenId); 42 | await tx.wait(); 43 | } 44 | } 45 | 46 | export { ERC721 }; 47 | -------------------------------------------------------------------------------- /packages/interfaces/src/bridge/index.ts: -------------------------------------------------------------------------------- 1 | import { ethers, BaseContract } from 'ethers'; 2 | import { IVAnchor } from '..'; 3 | import { IBridgeSide } from '../IBridgeSide'; 4 | 5 | // Deployer config matches the chainId to the signer for that chain 6 | export type DeployerConfig = Record; 7 | 8 | // Initial Governor config the chainId to the initial governor for that chain 9 | export type GovernorWithNonce = { 10 | address: string; 11 | nonce: number; 12 | }; 13 | 14 | /** 15 | * The governor config is a record of chainId => governor eth address 16 | * or chainId => {governor: eth address, nonce: number}, where the nonce is the 17 | * nonce of the governor at the time of deployment. Nonce is zero if not specified. 18 | **/ 19 | export type GovernorConfig = Record; 20 | 21 | export type Proposal = { 22 | data: string; 23 | dataHash: string; 24 | resourceId: string; 25 | chainId: number; 26 | leafIndex: number; 27 | }; 28 | 29 | export type BridgeConfig = { 30 | // The addresses of tokens available to be transferred over this bridge config 31 | // chainId => FungibleTokenWrapperAddress 32 | webbTokenAddresses: Map; 33 | 34 | // The addresses of the anchors for the FungibleTokenWrapper 35 | // {anchorIdentifier} => anchorAddress 36 | anchors: Map>; 37 | 38 | // The addresses of the Bridge contracts (bridgeSides) to interact with 39 | bridgeSides: Map; 40 | }; 41 | -------------------------------------------------------------------------------- /packages/contracts/contracts/verifiers/TxProofVerifier.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | import "../interfaces/verifiers/IAnchorVerifier.sol"; 7 | import "../utils/ProofUtils.sol"; 8 | 9 | pragma solidity ^0.8.18; 10 | 11 | /// @title TxProofVerifier contract. 12 | /// @notice This contract is used to verify the zero knowledge proofs. 13 | contract TxProofVerifier is ProofUtils { 14 | IAnchorVerifier public verifier; 15 | 16 | constructor(IAnchorVerifier _verifier) { 17 | require( 18 | address(_verifier) != address(0), 19 | "TxProofVerifier: Cannot set verifier to 0 address" 20 | ); 21 | verifier = _verifier; 22 | } 23 | 24 | /// @notice Verifies a zero-knowledge proof of knowledge over the tree according 25 | /// to the underlying `Verifier` circuit this `AnchorBase` is using. 26 | /// @notice This aims to be as generic as currently needed to support our VAnchor (variable deposit) contracts. 27 | /// @param _proof The zero-knowledge proof bytes 28 | /// @param _input The public input packed bytes 29 | /// @return bool Whether the proof is valid 30 | function verify( 31 | bytes memory _proof, 32 | bytes memory _input, 33 | bool smallInputs, 34 | uint8 maxEdges 35 | ) internal view returns (bool) { 36 | uint256[8] memory p = abi.decode(_proof, (uint256[8])); 37 | (uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c) = unpackProof(p); 38 | bool r = verifier.verifyProof(a, b, c, _input, maxEdges, smallInputs); 39 | require(r, "Invalid withdraw proof"); 40 | return r; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /circuits/merkle-tree/manyMerkleProof.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../../node_modules/circomlib/circuits/bitify.circom"; 4 | include "../../node_modules/circomlib/circuits/poseidon.circom"; 5 | include "../../node_modules/circomlib/circuits/switcher.circom"; 6 | include "../set/membership_if_enabled.circom"; 7 | 8 | 9 | // Verifies that merkle proof is correct for given merkle root and a leaf 10 | // pathIndices bits is an array of 0/1 selectors telling whether given pathElement is on the left or right side of merkle path 11 | template ManyMerkleProof(levels, length) { 12 | signal input leaf; 13 | signal input pathElements[levels]; 14 | signal input pathIndices; 15 | signal input roots[length]; 16 | signal input isEnabled; 17 | 18 | component switcher[levels]; 19 | component hasher[levels]; 20 | 21 | component indexBits = Num2Bits(levels); 22 | indexBits.in <== pathIndices; 23 | 24 | for (var i = 0; i < levels; i++) { 25 | switcher[i] = Switcher(); 26 | switcher[i].L <== i == 0 ? leaf : hasher[i - 1].out; 27 | switcher[i].R <== pathElements[i]; 28 | switcher[i].sel <== indexBits.out[i]; 29 | 30 | hasher[i] = Poseidon(2); 31 | hasher[i].inputs[0] <== switcher[i].outL; 32 | hasher[i].inputs[1] <== switcher[i].outR; 33 | } 34 | 35 | // verify that the resultant hash (computed merkle root) 36 | // is in the set of roots 37 | component set = ForceSetMembershipIfEnabled(length); 38 | set.enabled <== isEnabled; 39 | for (var i = 0; i < length; i++) { 40 | set.set[i] <== roots[i]; 41 | } 42 | set.element <== hasher[levels - 1].out; 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/forge.yml: -------------------------------------------------------------------------------- 1 | name: forge-tests 2 | 3 | on: 4 | push: 5 | branches: [ 'main' ] 6 | pull_request: 7 | types: [opened, synchronize, reopened, ready_for_review] 8 | branches: [ '**' ] 9 | paths-ignore: 10 | - 'README.md' 11 | 12 | workflow_dispatch: 13 | 14 | jobs: 15 | forge-tests: 16 | runs-on: ubuntu-latest 17 | if: github.ref != 'refs/heads/main' && github.event.pull_request.draft == false 18 | strategy: 19 | matrix: 20 | node-version: [18.15.x] 21 | steps: 22 | - uses: actions/checkout@v3 23 | - uses: actions/setup-node@v3 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | cache: 'yarn' 27 | 28 | - name: Fetch submodules 29 | run: git submodule update --init --recursive 30 | 31 | - name: Install dependencies 32 | run: yarn install --production=false 33 | 34 | - name: "Install Foundry" 35 | uses: "foundry-rs/foundry-toolchain@v1" 36 | 37 | - name: "Show the Foundry config" 38 | run: "forge config" 39 | 40 | - name: "Generate a fuzz seed that changes weekly to avoid burning through RPC allowance" 41 | run: > 42 | echo "FOUNDRY_FUZZ_SEED=$( 43 | echo $(($EPOCHSECONDS - $EPOCHSECONDS % 604800)) 44 | )" >> $GITHUB_ENV 45 | 46 | - name: clean 47 | run: yarn clean 48 | 49 | - name: "Run the tests" 50 | run: | 51 | cd ./packages/contracts 52 | forge build 53 | forge test 54 | 55 | - name: "Add test summary" 56 | run: | 57 | echo "## Tests result" >> $GITHUB_STEP_SUMMARY 58 | echo "✅ Passed" >> $GITHUB_STEP_SUMMARY 59 | -------------------------------------------------------------------------------- /packages/interfaces/src/vanchor/index.ts: -------------------------------------------------------------------------------- 1 | import { BigNumberish, BigNumber } from 'ethers'; 2 | import { Keypair } from '@webb-tools/utils'; 3 | 4 | export interface IMerkleProofData { 5 | pathElements: BigNumberish[]; 6 | pathIndex: BigNumberish; 7 | merkleRoot: BigNumberish; 8 | } 9 | 10 | export interface IUTXOInput { 11 | chainId: BigNumber; 12 | amount: BigNumber; 13 | keypair: Keypair; 14 | blinding: BigNumber; 15 | index: number; 16 | } 17 | 18 | export interface IVariableAnchorPublicInputs { 19 | proof: string; 20 | roots: string; 21 | extensionRoots: string; 22 | inputNullifiers: BigNumber[]; 23 | outputCommitments: [BigNumber, BigNumber]; 24 | publicAmount: string; 25 | extDataHash: BigNumber; 26 | } 27 | 28 | export interface IVariableAnchorExtData { 29 | recipient: string; 30 | extAmount: string; 31 | relayer: string; 32 | fee: string; 33 | refund: string; 34 | token: string; 35 | encryptedOutput1: string; 36 | encryptedOutput2: string; 37 | } 38 | 39 | export interface IWitnessInput { 40 | input: { 41 | roots: BigNumberish[]; 42 | chainID: BigNumberish; 43 | inputNullifier: BigNumberish[]; 44 | outputCommitment: BigNumberish[]; 45 | publicAmount: BigNumberish; 46 | extDataHash: BigNumberish; 47 | 48 | // data for 2 transaction inputs 49 | inAmount: BigNumberish[]; 50 | inPrivateKey: string[]; 51 | inBlinding: BigNumberish[]; 52 | inPathIndices: BigNumberish[]; 53 | inPathElements: BigNumberish[][]; 54 | 55 | // data for 2 transaction outputs 56 | outChainID: BigNumberish[]; 57 | outAmount: BigNumberish[]; 58 | outBlinding: BigNumberish[]; 59 | outPubkey: BigNumberish[]; 60 | }; 61 | extData: IVariableAnchorExtData; 62 | } 63 | -------------------------------------------------------------------------------- /packages/contracts/hardhatAccounts.js: -------------------------------------------------------------------------------- 1 | exports.HARDHAT_PK_0 = '0000000000000000000000000000000000000000000000000000000000000010'; 2 | 3 | exports.HARDHAT_PK_1 = '0000000000000000000000000000000000000000000000000000000000000001'; 4 | exports.HARDHAT_PK_2 = '0000000000000000000000000000000000000000000000000000000000000002'; 5 | 6 | exports.HARDHAT_ACCOUNTS = [ 7 | { 8 | privateKey: '0000000000000000000000000000000000000000000000000000000000000010', 9 | balance: '1000000000000000000000', 10 | }, 11 | { 12 | privateKey: '0000000000000000000000000000000000000000000000000000000000000001', 13 | balance: '1000000000000000000000', 14 | }, 15 | { 16 | privateKey: '0000000000000000000000000000000000000000000000000000000000000002', 17 | balance: '1000000000000000000000', 18 | }, 19 | { 20 | privateKey: '0000000000000000000000000000000000000000000000000000000000000003', 21 | balance: '1000000000000000000000', 22 | }, 23 | { 24 | privateKey: '0000000000000000000000000000000000000000000000000000000000000004', 25 | balance: '1000000000000000000000', 26 | }, 27 | { 28 | privateKey: '0000000000000000000000000000000000000000000000000000000000000005', 29 | balance: '1000000000000000000000', 30 | }, 31 | { 32 | privateKey: '0000000000000000000000000000000000000000000000000000000000000006', 33 | balance: '1000000000000000000000', 34 | }, 35 | { 36 | privateKey: '0000000000000000000000000000000000000000000000000000000000000007', 37 | balance: '1000000000000000000000', 38 | }, 39 | { 40 | privateKey: '0000000000000000000000000000000000000000000000000000000000000008', 41 | balance: '1000000000000000000000', 42 | }, 43 | { 44 | privateKey: '0000000000000000000000000000000000000000000000000000000000000009', 45 | balance: '1000000000000000000000', 46 | }, 47 | ]; 48 | -------------------------------------------------------------------------------- /packages/contracts/contracts/mocks/LinkableAnchorMock.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | import "../vanchors/base/LinkableAnchor.sol"; 9 | import "../interfaces/verifiers/IAnchorVerifier.sol"; 10 | import "../interfaces/verifiers/ISetVerifier.sol"; 11 | import "../trees/MerkleTree.sol"; 12 | 13 | contract LinkableAnchorMock is MerkleTree, LinkableAnchor, ISetVerifier { 14 | constructor( 15 | address _handler, 16 | IAnchorVerifier _verifier, 17 | IHasher _hasher, 18 | uint32 _merkleTreeHeight, 19 | uint8 _maxEdges 20 | ) 21 | LinkableAnchor(_handler, _merkleTreeHeight, _maxEdges) 22 | MerkleTree(_merkleTreeHeight, _hasher) 23 | { 24 | require(address(_verifier) != address(0), "Verifier address cannot be 0"); 25 | return; 26 | } 27 | 28 | function initialize() external onlyUninitialized { 29 | super._initialize(); 30 | } 31 | 32 | function setHandler( 33 | address _handler, 34 | uint32 _nonce 35 | ) external override onlyHandler onlyIncrementingByOne(_nonce) { 36 | handler = _handler; 37 | return; 38 | } 39 | 40 | function setVerifier( 41 | address _verifier, 42 | uint32 _nonce 43 | ) external override onlyHandler onlyIncrementingByOne(_nonce) { 44 | _verifier = _verifier; 45 | return; 46 | } 47 | 48 | function configureMinimumWithdrawalLimit( 49 | uint256 _minimumWithdrawalAmount, 50 | uint32 _nonce 51 | ) external override onlyHandler onlyIncrementingByOne(_nonce) { 52 | _minimumWithdrawalAmount + _minimumWithdrawalAmount; 53 | return; 54 | } 55 | 56 | function configureMaximumDepositLimit( 57 | uint256 _maximumDepositAmount, 58 | uint32 _nonce 59 | ) external override onlyHandler onlyIncrementingByOne(_nonce) { 60 | _maximumDepositAmount + _maximumDepositAmount; 61 | return; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/contracts/contracts/structs/PublicInputs.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title Common structs for public inputs and shielded transactions. 9 | /// @author Webb Technologies. 10 | /// @notice These structs are meant to be used with the `VAnchor` contract. 11 | 12 | /// @notice Common external data for all transactions 13 | /// @param recipient The recipient of the transaction 14 | /// @param extAmount The external amount being transferred 15 | /// @param relayer The relayer of the transaction 16 | /// @param fee The fee for the transaction 17 | /// @param refund The refund for the transaction 18 | /// @param token The token being wrapped/unwrapped or transferred if its the shielded pool token 19 | struct CommonExtData { 20 | address recipient; 21 | int256 extAmount; 22 | address relayer; 23 | uint256 fee; 24 | uint256 refund; 25 | address token; 26 | } 27 | 28 | /// @notice Public input struct for VAnchor proofs 29 | /// @param roots The roots on the VAnchor commitment trees 30 | /// @param extensionRoots The extra roots for extension VAnchors such as IdentityVAnchor 31 | /// @param inputNullifiers The nullifiers of the UTXO records 32 | /// @param outputCommitments The 2 new commitments for the join/split UTXO transaction 33 | /// @param publicAmount The public amount being deposited to this VAnchor 34 | /// @param extDataHash The external data hash for the proof verification 35 | struct PublicInputs { 36 | bytes roots; 37 | bytes extensionRoots; 38 | uint256[] inputNullifiers; 39 | uint256[2] outputCommitments; 40 | uint256 publicAmount; 41 | uint256 extDataHash; 42 | } 43 | 44 | /// @notice External encryptions for new output commitments 45 | struct Encryptions { 46 | bytes encryptedOutput1; 47 | bytes encryptedOutput2; 48 | } 49 | -------------------------------------------------------------------------------- /packages/contracts/contracts/vanchors/extensions/ChainalysisVAnchor.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | import "../instances/VAnchorTree.sol"; 9 | import "../../utils/SanctionFilter.sol"; 10 | 11 | /// @title Chainalysis Variable Anchor contract 12 | /// @author Webb Technologies 13 | /// @notice The main addition here is a filter for sanctioned addresses on transactions. 14 | contract ChainalysisVAnchor is VAnchorTree, SanctionFilter { 15 | using SafeERC20 for IERC20; 16 | 17 | constructor( 18 | IAnchorVerifier _verifier, 19 | uint32 _merkleTreeLevels, 20 | IHasher _hasher, 21 | address _handler, 22 | address _token, 23 | uint8 _maxEdges 24 | ) VAnchorTree(_verifier, _merkleTreeLevels, _hasher, _handler, _token, _maxEdges) {} 25 | 26 | /// @inheritdoc ZKVAnchorBase 27 | function registerAndTransact( 28 | Account memory _account, 29 | bytes memory _proof, 30 | bytes memory _auxPublicInputs, 31 | CommonExtData memory _externalData, 32 | PublicInputs memory _publicInputs, 33 | Encryptions memory _encryptions 34 | ) public payable override isNotSanctioned(msg.sender) isNotSanctioned(_externalData.recipient) { 35 | super.registerAndTransact( 36 | _account, 37 | _proof, 38 | _auxPublicInputs, 39 | _externalData, 40 | _publicInputs, 41 | _encryptions 42 | ); 43 | } 44 | 45 | /// @inheritdoc ZKVAnchorBase 46 | function transact( 47 | bytes memory _proof, 48 | bytes memory _auxPublicInputs, 49 | CommonExtData memory _externalData, 50 | PublicInputs memory _publicInputs, 51 | Encryptions memory _encryptions 52 | ) public payable override isNotSanctioned(msg.sender) isNotSanctioned(_externalData.recipient) { 53 | super.transact(_proof, _auxPublicInputs, _externalData, _publicInputs, _encryptions); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/anchors/src/AnchorHandler.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers'; 2 | import { 3 | AnchorHandler as AnchorHandlerContract, 4 | AnchorHandler__factory, 5 | } from '@webb-tools/contracts'; 6 | import { Deployer } from '@webb-tools/create2-utils'; 7 | 8 | export class AnchorHandler { 9 | contract: AnchorHandlerContract; 10 | 11 | constructor(contract: AnchorHandlerContract) { 12 | this.contract = contract; 13 | } 14 | 15 | public static async createAnchorHandler( 16 | bridgeAddress: string, 17 | initResourceIds: string[], 18 | initContractAddresses: string[], 19 | deployer: ethers.Signer 20 | ) { 21 | const factory = new AnchorHandler__factory(deployer); 22 | const contract = await factory.deploy(bridgeAddress, initResourceIds, initContractAddresses); 23 | await contract.deployed(); 24 | 25 | const handler = new AnchorHandler(contract); 26 | return handler; 27 | } 28 | 29 | public static async create2AnchorHandler( 30 | bridgeAddress: string, 31 | initResourceIds: string[], 32 | initContractAddresses: string[], 33 | deployer: Deployer, 34 | saltHex: string, 35 | signer: ethers.Signer 36 | ) { 37 | const argTypes = ['address', 'bytes32[]', 'address[]']; 38 | const args = [bridgeAddress, initResourceIds, initContractAddresses]; 39 | const { contract: contract } = await deployer.deploy( 40 | AnchorHandler__factory, 41 | saltHex, 42 | signer, 43 | undefined, 44 | argTypes, 45 | args 46 | ); 47 | 48 | const handler = new AnchorHandler(contract); 49 | return handler; 50 | } 51 | 52 | public static async connect(handlerAddress: string, signer: ethers.Signer) { 53 | const handlerContract = AnchorHandler__factory.connect(handlerAddress, signer); 54 | const handler = new AnchorHandler(handlerContract); 55 | return handler; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/tokens/src/TreasuryHandler.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers'; 2 | import { 3 | TreasuryHandler as TreasuryHandlerContract, 4 | TreasuryHandler__factory, 5 | } from '@webb-tools/contracts'; 6 | import { Deployer } from '@webb-tools/create2-utils'; 7 | 8 | export class TreasuryHandler { 9 | contract: TreasuryHandlerContract; 10 | 11 | constructor(contract: TreasuryHandlerContract) { 12 | this.contract = contract; 13 | } 14 | 15 | public static async createTreasuryHandler( 16 | bridgeAddress: string, 17 | initResourceIds: string[], 18 | initContractAddresses: string[], 19 | deployer: ethers.Signer 20 | ) { 21 | const factory = new TreasuryHandler__factory(deployer); 22 | const contract = await factory.deploy(bridgeAddress, initResourceIds, initContractAddresses); 23 | await contract.deployed(); 24 | 25 | const handler = new TreasuryHandler(contract); 26 | return handler; 27 | } 28 | 29 | public static async create2TreasuryHandler( 30 | bridgeAddress: string, 31 | initResourceIds: string[], 32 | initContractAddresses: string[], 33 | deployer: Deployer, 34 | saltHex: string, 35 | sender: ethers.Signer 36 | ) { 37 | const argTypes = ['address', 'bytes32[]', 'address[]']; 38 | const args = [bridgeAddress, initResourceIds, initContractAddresses]; 39 | const { contract: contract } = await deployer.deploy( 40 | TreasuryHandler__factory, 41 | saltHex, 42 | sender, 43 | undefined, 44 | argTypes, 45 | args 46 | ); 47 | const handler = new TreasuryHandler(contract); 48 | return handler; 49 | } 50 | 51 | public static async connect(handlerAddress: string, signer: ethers.Signer) { 52 | const handlerContract = TreasuryHandler__factory.connect(handlerAddress, signer); 53 | const handler = new TreasuryHandler(handlerContract); 54 | return handler; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/tokens/src/TokenWrapperHandler.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers'; 2 | import { 3 | TokenWrapperHandler as TokenWrapperHandlerContract, 4 | TokenWrapperHandler__factory, 5 | } from '@webb-tools/contracts'; 6 | import { Deployer } from '@webb-tools/create2-utils'; 7 | 8 | export class TokenWrapperHandler { 9 | contract: TokenWrapperHandlerContract; 10 | 11 | constructor(contract: TokenWrapperHandlerContract) { 12 | this.contract = contract; 13 | } 14 | 15 | public static async createTokenWrapperHandler( 16 | bridgeAddress: string, 17 | initResourceIds: string[], 18 | initContractAddresses: string[], 19 | deployer: ethers.Signer 20 | ) { 21 | const factory = new TokenWrapperHandler__factory(deployer); 22 | const contract = await factory.deploy(bridgeAddress, initResourceIds, initContractAddresses); 23 | await contract.deployed(); 24 | 25 | const handler = new TokenWrapperHandler(contract); 26 | return handler; 27 | } 28 | 29 | public static async create2TokenWrapperHandler( 30 | bridgeAddress: string, 31 | initResourceIds: string[], 32 | initContractAddresses: string[], 33 | deployer: Deployer, 34 | saltHex: string, 35 | signer: ethers.Signer 36 | ) { 37 | const argTypes = ['address', 'bytes32[]', 'address[]']; 38 | const args = [bridgeAddress, initResourceIds, initContractAddresses]; 39 | const { contract: contract } = await deployer.deploy( 40 | TokenWrapperHandler__factory, 41 | saltHex, 42 | signer, 43 | undefined, 44 | argTypes, 45 | args 46 | ); 47 | const handler = new TokenWrapperHandler(contract); 48 | return handler; 49 | } 50 | 51 | public static async connect(handlerAddress: string, signer: ethers.Signer) { 52 | const handlerContract = TokenWrapperHandler__factory.connect(handlerAddress, signer); 53 | const handler = new TokenWrapperHandler(handlerContract); 54 | return handler; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /scripts/bash/build_circuits.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | compile () { 4 | local outdir="$1" circuit="$2" size="$3" 5 | mkdir -p build/$outdir 6 | mkdir -p build/$outdir/$size 7 | mkdir -p artifacts/circuits/$outdir 8 | echo "circuits/main/$circuit.circom" 9 | ~/.cargo/bin/circom --r1cs --wasm --sym \ 10 | -o artifacts/circuits/$outdir \ 11 | circuits/main/$circuit.circom 12 | echo -e "Done!\n" 13 | } 14 | 15 | copy_to_fixtures () { 16 | local outdir="$1" circuit="$2" size="$3" anchorType="$4" 17 | mkdir -p solidity-fixtures/solidity-fixtures/$anchorType 18 | mkdir -p solidity-fixtures/solidity-fixtures/$anchorType/$size 19 | cp artifacts/circuits/$outdir/$circuit.sym solidity-fixtures/solidity-fixtures/$anchorType/$size/$circuit.sym 20 | cp artifacts/circuits/$outdir/$circuit.r1cs solidity-fixtures/solidity-fixtures/$anchorType/$size/$circuit.r1cs 21 | cp artifacts/circuits/$outdir/$circuit\_js/$circuit.wasm solidity-fixtures/solidity-fixtures/$anchorType/$size/$circuit.wasm 22 | cp artifacts/circuits/$outdir/$circuit\_js/witness_calculator.js solidity-fixtures/solidity-fixtures/$anchorType/$size/witness_calculator.cjs 23 | } 24 | 25 | ## 26 | # WEBB VANCHORS 27 | ## 28 | 29 | echo "Compiling Webb style Poseidon vanchor 2 circuit w/ 2 inputs" 30 | compile vanchor_2 poseidon_vanchor_2_2 2 31 | copy_to_fixtures vanchor_2 poseidon_vanchor_2_2 2 vanchor_2 32 | 33 | echo "Compiling Webb style Poseidon vanchor 2 circuit w/ 16 inputs" 34 | compile vanchor_16 poseidon_vanchor_16_2 2 35 | copy_to_fixtures vanchor_16 poseidon_vanchor_16_2 2 vanchor_16 36 | 37 | echo "Compiling Webb style Poseidon vanchor 8 circuit w/ 2 inputs" 38 | compile vanchor_2 poseidon_vanchor_2_8 8 39 | copy_to_fixtures vanchor_2 poseidon_vanchor_2_8 8 vanchor_2 40 | 41 | echo "Compiling Webb style Poseidon vanchor 8 circuit w/ 16 inputs" 42 | compile vanchor_16 poseidon_vanchor_16_8 8 43 | copy_to_fixtures vanchor_16 poseidon_vanchor_16_8 8 vanchor_16 44 | 45 | 46 | -------------------------------------------------------------------------------- /packages/anchors/src/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2023 @webb-tools/ 2 | // File contains all the types used in the anchors package 3 | 4 | import { IVariableAnchorExtData, IVariableAnchorPublicInputs } from '@webb-tools/interfaces'; 5 | import { Keypair } from '@webb-tools/utils'; 6 | import { BigNumber, Overrides } from 'ethers'; 7 | 8 | export interface SetupTransactionResult { 9 | extAmount: BigNumber; 10 | extData: IVariableAnchorExtData; 11 | publicInputs: IVariableAnchorPublicInputs; 12 | } 13 | 14 | export enum TransactionState { 15 | GENERATE_ZK_PROOF = 'GENERATE_ZK_PROOF', 16 | INITIALIZE_TRANSACTION = 'INITIALIZE_TRANSACTION', 17 | WAITING_FOR_FINALIZATION = 'WAITING_FOR_FINALIZATION', 18 | FINALIZED = 'FINALIZED', 19 | } 20 | 21 | export interface TransactionStateUpdatePayload { 22 | [TransactionState.GENERATE_ZK_PROOF]: undefined; 23 | [TransactionState.INITIALIZE_TRANSACTION]: undefined; 24 | [TransactionState.WAITING_FOR_FINALIZATION]: string; 25 | [TransactionState.FINALIZED]: string; 26 | } 27 | 28 | /** 29 | * Options to be passed to the `setup` function. 30 | * 31 | * NOTE: MAKE SURE TO UPDATE THE `splitTransactionOptions` FUNCTION (IN `utils.ts`) IF YOU ADD A NEW PROPERTY HERE. 32 | */ 33 | export interface TransactionOptions { 34 | /** 35 | * For identityVAnchor 36 | */ 37 | keypair?: Keypair; // 38 | 39 | /** 40 | * For vanchorForest/IdentityVAnchor 41 | */ 42 | treeChainId?: string; 43 | 44 | /** 45 | * For vanchorForest 46 | */ 47 | externalLeaves?: Uint8Array[]; 48 | 49 | /** 50 | * The callback to update the transaction state 51 | * when the transanction progress and send 52 | */ 53 | onTransactionState?: ( 54 | state: T, 55 | payload: TransactionStateUpdatePayload[T] 56 | ) => void; 57 | } 58 | 59 | /** 60 | * Utility type to add the `from` property to an override type. 61 | */ 62 | export type OverridesWithFrom = T & { from?: string | Promise }; 63 | -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/ILinkableAnchor.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title ILinkableAnchor Interface 9 | /// @author Webb Technologies. 10 | /// @notice The interface supports updating edges for a graph-like functionality. 11 | /// It also supports setting handlers and verifiers for handling updates 12 | /// to the edge data of a LinkableAnchor as well as the verifier used in 13 | /// verifying proofs of knowledge of leaves in one-of-many merkle trees. 14 | /// @notice The ILinkableAnchor interface can also be used with the VAnchor system 15 | /// to control the minimal and maximum withdrawal and deposit limits respectively. 16 | interface ILinkableAnchor { 17 | /// @notice Sets the handler for updating edges and other contract state 18 | /// @param handler The new handler address 19 | /// @param nonce The nonce for tracking update counts 20 | function setHandler(address handler, uint32 nonce) external; 21 | 22 | /// @notice Sets the minimal withdrawal limit for the anchor 23 | /// @param minimumWithdrawalAmount The new minimal withdrawal limit 24 | function configureMinimumWithdrawalLimit( 25 | uint256 minimumWithdrawalAmount, 26 | uint32 nonce 27 | ) external; 28 | 29 | /// @notice Sets the maximal deposit limit for the anchor 30 | /// @param maximumDepositAmount The new maximal deposit limit 31 | function configureMaximumDepositLimit(uint256 maximumDepositAmount, uint32 nonce) external; 32 | 33 | /// @notice The function is used to update the edge data of a LinkableAnchor 34 | /// @param root The merkle root of the linked anchor on the `sourceChainID`'s chain 35 | /// @param latestLeafIndex The index of the leaf updating the merkle tree with root `root` 36 | /// @param srcResourceID The source resource ID of the linked anchor where the update originates from 37 | function updateEdge( 38 | uint256 root, 39 | uint32 latestLeafIndex, 40 | bytes32 srcResourceID 41 | ) external payable; 42 | } 43 | -------------------------------------------------------------------------------- /packages/contracts/hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import { HardhatUserConfig } from 'hardhat/types'; 2 | import { HARDHAT_ACCOUNTS } from './hardhatAccounts.js'; 3 | import 'hardhat-artifactor'; 4 | import 'hardhat-gas-reporter'; 5 | import '@typechain/hardhat'; 6 | 7 | import '@nomiclabs/hardhat-ethers'; 8 | import '@nomiclabs/hardhat-truffle5'; 9 | // import '@primitivefi/hardhat-dodoc'; 10 | import { subtask } from 'hardhat/config'; 11 | 12 | import poseidonContract from 'circomlibjs/src/poseidon_gencontract.js'; 13 | 14 | require('dotenv').config({ path: __dirname + '/.env' }); 15 | 16 | const buildPoseidon = async (numInputs: number) => { 17 | //@ts-ignore 18 | await overwriteArtifact(`PoseidonT${numInputs + 1}`, poseidonContract.createCode(numInputs)); 19 | }; 20 | 21 | subtask('typechain-generate-types', async (taskArgs, hre, runSuper) => { 22 | // overwrite the artifact before generating types 23 | await buildPoseidon(1); 24 | await buildPoseidon(2); 25 | await buildPoseidon(3); 26 | await buildPoseidon(4); 27 | await buildPoseidon(5); 28 | await runSuper(); 29 | }); 30 | 31 | const { TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } = require('hardhat/builtin-tasks/task-names'); 32 | 33 | subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction(async (_, __, runSuper) => 34 | (await runSuper()).filter((path) => !path.endsWith('.t.sol')) 35 | ); 36 | 37 | const config: HardhatUserConfig = { 38 | defaultNetwork: 'hardhat', 39 | networks: { 40 | hardhat: { 41 | allowUnlimitedContractSize: true, 42 | accounts: HARDHAT_ACCOUNTS, 43 | }, 44 | }, 45 | solidity: { 46 | compilers: [ 47 | { 48 | version: '0.8.18', 49 | settings: { 50 | optimizer: { 51 | enabled: true, 52 | runs: 200, 53 | }, 54 | }, 55 | }, 56 | ], 57 | }, 58 | mocha: { 59 | timeout: 100000, 60 | }, 61 | gasReporter: { 62 | enabled: process.env.REPORT_GAS ? true : false, 63 | currency: 'USD', 64 | gasPrice: 21, 65 | }, 66 | }; 67 | 68 | export default config; 69 | -------------------------------------------------------------------------------- /packages/utils/src/bytes/u8aToHex.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2022 @polkadot/util authors & contributors 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | type HexString = `0x${string}`; 5 | 6 | const U8 = new Array(256); 7 | const U16 = new Array(256 * 256); 8 | 9 | for (let n = 0; n < 256; n++) { 10 | U8[n] = n.toString(16).padStart(2, '0'); 11 | } 12 | 13 | for (let i = 0; i < 256; i++) { 14 | const s = i << 8; 15 | 16 | for (let j = 0; j < 256; j++) { 17 | U16[s | j] = U8[i] + U8[j]; 18 | } 19 | } 20 | 21 | /** @internal */ 22 | function hex(value: Uint8Array, result: HexString): HexString { 23 | const mod = value.length % 2 | 0; 24 | const length = (value.length - mod) | 0; 25 | 26 | for (let i = 0; i < length; i += 2) { 27 | // @ts-ignore 28 | result += U16[(value[i] << 8) | value[i + 1]]; 29 | } 30 | 31 | if (mod) { 32 | // @ts-ignore 33 | result += U8[value[length] | 0]; 34 | } 35 | 36 | return result; 37 | } 38 | 39 | /** 40 | * @name u8aToHex 41 | * @summary Creates a hex string from a Uint8Array object. 42 | * @description 43 | * `UInt8Array` input values return the actual hex string. `null` or `undefined` values returns an `0x` string. 44 | * @example 45 | *
46 | * 47 | * ```javascript 48 | * import { u8aToHex } from '@polkadot/util'; 49 | * 50 | * u8aToHex(new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0xf])); // 0x68656c0f 51 | * ``` 52 | */ 53 | export function u8aToHex(value?: Uint8Array | null, bitLength = -1, isPrefixed = true): HexString { 54 | // this is not 100% correct sinmce we support isPrefixed = false.... 55 | const empty = isPrefixed ? '0x' : ('' as HexString); 56 | 57 | if (!value || !value.length) { 58 | return empty; 59 | } else if (bitLength > 0) { 60 | const length = Math.ceil(bitLength / 8); 61 | 62 | if (value.length > length) { 63 | return `${hex(value.subarray(0, length / 2), empty)}…${hex( 64 | value.subarray(value.length - length / 2), 65 | '' as HexString 66 | )}`; 67 | } 68 | } 69 | 70 | return hex(value, empty); 71 | } 72 | -------------------------------------------------------------------------------- /packages/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webb-tools/utils", 3 | "main": "./dist/index.js", 4 | "types": "./dist/index.d.ts", 5 | "license": "(MIT OR Apache-2.0)", 6 | "author": "Webb Developers ", 7 | "scripts": { 8 | "build": "yarn run clean && yarn run compile", 9 | "clean": "rimraf -rf ./dist", 10 | "compile": "tsc -p tsconfig.build.json", 11 | "test": "mocha -r ts-node/register 'src/__test__/**/*.ts'" 12 | }, 13 | "dependencies": { 14 | "@metamask/eth-sig-util": "^6.0.0", 15 | "circomlibjs": "^0.0.8", 16 | "elliptic": "6.5.4", 17 | "ethers": "5.7.0", 18 | "snarkjs": "^0.7.2" 19 | }, 20 | "publishConfig": { 21 | "access": "public" 22 | }, 23 | "repository": { 24 | "directory": "packages/utils", 25 | "type": "git", 26 | "url": "git://github.com/webb-tools/protocol-solidity.git" 27 | }, 28 | "version": "1.1.1", 29 | "gitHead": "e1f3b300b6e004ac5a346dc0458bb1d303969d97", 30 | "devDependencies": { 31 | "@webb-tools/sdk-core": "0.1.4-126", 32 | "chai": "^4.3.7" 33 | }, 34 | "exports": { 35 | ".": { 36 | "types": "./dist/index.d.ts", 37 | "require": "./dist/index.js", 38 | "default": "./dist/index.js" 39 | }, 40 | "./bytes": { 41 | "types": "./dist/bytes/index.d.ts", 42 | "require": "./dist/bytes/index.js", 43 | "default": "./dist/bytes/index.js" 44 | }, 45 | "./proof": { 46 | "types": "./dist/proof/index.d.ts", 47 | "require": "./dist/proof/index.js", 48 | "default": "./dist/proof/index.js" 49 | }, 50 | "./protocol": { 51 | "types": "./dist/protocol/index.d.ts", 52 | "require": "./dist/protocol/index.js", 53 | "default": "./dist/protocol/index.js" 54 | }, 55 | "./fixtures": { 56 | "types": "./dist/fixtures.d.ts", 57 | "require": "./dist/fixtures.js", 58 | "default": "./dist/fixtures.js" 59 | }, 60 | "./utils": { 61 | "types": "./dist/utils.d.ts", 62 | "require": "./dist/utils.js", 63 | "default": "./dist/utils.js" 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | "compilerOptions": { 4 | "preserveSymlinks": true, 5 | "baseUrl": ".", 6 | "paths": { 7 | /** 8 | * Solidity contracts & Typechain 9 | */ 10 | "@webb-tools/contracts": [ 11 | "packages/contracts/typechain-types" 12 | ], 13 | "@webb-tools/contracts/*": [ 14 | "packages/contracts/typechain-types/*" 15 | ], 16 | "@webb-tools/protocol-solidity": [ 17 | "packages/contracts/contracts" 18 | ], 19 | "@webb-tools/protocol-solidity/*": [ 20 | "packages/contracts/contracts/*" 21 | ], 22 | 23 | /** 24 | * TypeScript packages 25 | */ 26 | "@webb-tools/anchors": [ 27 | "packages/anchors/src" 28 | ], 29 | "@webb-tools/anchors/*": [ 30 | "packages/anchors/src/*" 31 | ], 32 | "@webb-tools/evm-test-utils": [ 33 | "packages/evm-test-utils/src" 34 | ], 35 | "@webb-tools/evm-test-utils/*": [ 36 | "packages/evm-test-utils/src/*" 37 | ], 38 | "@webb-tools/create2-utils": [ 39 | "packages/create2-utils" 40 | ], 41 | "@webb-tools/create2-utils/*": [ 42 | "packages/create2-utils/*" 43 | ], 44 | "@webb-tools/interfaces": [ 45 | "packages/interfaces" 46 | ], 47 | "@webb-tools/interfaces/*": [ 48 | "packages/interfaces/*" 49 | ], 50 | "@webb-tools/proposals": [ 51 | "packages/proposals" 52 | ], 53 | "@webb-tools/proposals/*": [ 54 | "packages/proposals/*" 55 | ], 56 | "@webb-tools/tokens": [ 57 | "packages/tokens" 58 | ], 59 | "@webb-tools/tokens/*": [ 60 | "packages/tokens/*" 61 | ], 62 | "@webb-tools/utils": [ 63 | "packages/utils" 64 | ], 65 | "@webb-tools/utils/*": [ 66 | "packages/utils/*" 67 | ], 68 | "@webb-tools/vbridge": [ 69 | "packages/vbridge" 70 | ], 71 | "@webb-tools/vbridge/*": [ 72 | "packages/vbridge/*" 73 | ], 74 | }, 75 | "noEmit": true 76 | } 77 | } -------------------------------------------------------------------------------- /scripts/bash/plonk/phase2_circuit_plonk.sh: -------------------------------------------------------------------------------- 1 | compile_phase2 () { 2 | local outdir="$1" circuit="$2" pathToCircuitDir="$3" maxPhase1Constraints="$4" 3 | mkdir -p $1 4 | 5 | echo "Setting up Phase 2 ceremony for $2" 6 | echo "Outputting circuit_final.zkey and verifier.sol to $1" 7 | 8 | npx snarkjs plonk setup "$pathToCircuitDir/$circuit.r1cs" ./protocol-solidity-fixtures/ptau/pot$maxPhase1Constraints\_final.ptau "$outdir/circuit_final.zkey" 9 | npx snarkjs zkey export verificationkey "$outdir/circuit_final.zkey" "$outdir/verification_key.json" 10 | snarkjs zkey export solidityverifier "$outdir/circuit_final.zkey" $outdir/verifier.sol 11 | # npx snarkjs wtns calculate "$3/$2_js/$2.wasm" "$1/input.json" "$1/witness.wtns" 12 | #npx snarkjs wtns debug "$3/$2_js/$2.wasm" "$1/input.json" "$1/witness.wtns" "$3/$2_js/$2.sym" --trigger --get --set 13 | echo -e "Done!\n" 14 | } 15 | 16 | move_verifiers_and_metadata () { 17 | local outdir="$1" size="$2" anchorType="$3" 18 | if [[ ! -f contracts/verifiers/$anchorType/ ]]; then 19 | mkdir -p contracts/verifiers/$anchorType 20 | fi 21 | cp $outdir/verifier.sol contracts/verifiers/$anchorType/"Verifier$size.sol" 22 | # sed -i s/'pragma solidity ^0.8.18;'/'pragma solidity ^0.8.18;'/ contracts/verifiers/$anchorType/"Verifier$size.sol" 23 | sed -i s/"contract PlonkVerifier"/"contract PlonkVerifier$size"/ contracts/verifiers/$anchorType/"Verifier$size.sol" 24 | sed -i s/"uint16 constant n"/"uint32 constant n"/ contracts/verifiers/$anchorType/"Verifier$size.sol" 25 | } 26 | 27 | move_verifiers_and_metadata_vanchor () { 28 | local indir="$1" size="$2" anchorType="$3" nIns="$4" 29 | if [[ ! -f contracts/verifiers/$anchorType/ ]]; then 30 | mkdir -p contracts/verifiers/$anchorType 31 | fi 32 | 33 | cp $indir/verifier.sol contracts/verifiers/$anchorType/"Verifier$size\_$nIns.sol" 34 | sed -i s/"contract PlonkVerifier"/"contract Verifier$size\_$nIns"/ contracts/verifiers/$anchorType/"Verifier$size\_$nIns.sol" 35 | sed -i s/"uint16 constant n"/"uint32 constant n"/ contracts/verifiers/$anchorType/"Verifier$size\_$nIns.sol" 36 | 37 | } 38 | -------------------------------------------------------------------------------- /packages/utils/src/__test__/typed-chain-id.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2022-2023 Webb Technologies Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { expect } from 'chai'; 5 | 6 | import { 7 | byteArrayToNum, 8 | calculateTypedChainId, 9 | ChainType, 10 | numToByteArray, 11 | parseTypedChainId, 12 | TypedChainId, 13 | } from '../protocol/typed-chain-id'; 14 | 15 | describe('test various conversion functions', () => { 16 | it('byte array to num converts correctly', () => { 17 | const arr = [2, 0, 0, 0, 122, 105]; 18 | const result = 2199023286889; 19 | 20 | expect(byteArrayToNum(arr)).to.deep.equal(result); 21 | }); 22 | 23 | it('numToByteArray converts correctly', () => { 24 | const arrResult = [2, 0, 0, 0, 122, 105]; 25 | const number = 2199023286889; 26 | 27 | expect(numToByteArray(number, 4)).to.deep.equal(arrResult); 28 | }); 29 | 30 | it('numToByteArray converts hexstring values correctly', () => { 31 | const evmResult = [1, 0]; 32 | 33 | expect(numToByteArray(ChainType.EVM, 2)).to.deep.equal(evmResult); 34 | const kusamaParachainResult = [3, 17]; 35 | 36 | expect(numToByteArray(ChainType.KusamaParachain, 2)).to.deep.equal(kusamaParachainResult); 37 | }); 38 | 39 | it('numToByteArray maintains minimum size with leading zeroes', () => { 40 | const arrResult = [0, 0, 122, 105]; 41 | const number = 31337; 42 | 43 | expect(numToByteArray(number, 4)).to.deep.equal(arrResult); 44 | }); 45 | 46 | it('calculateTypedChainId converts correctly', () => { 47 | const chainType = ChainType.Substrate; 48 | const chainId = 31337; 49 | const chainIdTypeResult = 2199023286889; 50 | 51 | expect(calculateTypedChainId(chainType, chainId)).to.deep.equal(chainIdTypeResult); 52 | }); 53 | 54 | it('typeAndIdFromChainIdType converts correctly', () => { 55 | const chainIdType = 2199023286889; 56 | const chainTypeResult = ChainType.Substrate; 57 | const chainIdResult = 31337; 58 | 59 | const result: TypedChainId = { 60 | chainId: chainIdResult, 61 | chainType: chainTypeResult, 62 | }; 63 | 64 | expect(parseTypedChainId(chainIdType)).to.deep.equal(result); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /packages/utils/src/bytes/hexToU8a.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2022 @polkadot/util authors & contributors 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | type HexString = `0x${string}`; 5 | 6 | const CHR = '0123456789abcdef'; 7 | const U8 = new Array(256); 8 | const U16 = new Array(256 * 256); 9 | 10 | for (let i = 0; i < CHR.length; i++) { 11 | U8[CHR[i].charCodeAt(0) | 0] = i | 0; 12 | 13 | if (i > 9) { 14 | U8[CHR[i].toUpperCase().charCodeAt(0) | 0] = i | 0; 15 | } 16 | } 17 | 18 | for (let i = 0; i < 256; i++) { 19 | const s = i << 8; 20 | 21 | for (let j = 0; j < 256; j++) { 22 | U16[s | j] = (U8[i] << 4) | U8[j]; 23 | } 24 | } 25 | 26 | /** 27 | * @name hexToU8a 28 | * @summary Creates a Uint8Array object from a hex string. 29 | * @description 30 | * `null` inputs returns an empty `Uint8Array` result. Hex input values return the actual bytes value converted to a Uint8Array. Anything that is not a hex string (including the `0x` prefix) throws an error. 31 | * @example 32 | *
33 | * 34 | * ```javascript 35 | * import { hexToU8a } from '@polkadot/util'; 36 | * 37 | * hexToU8a('0x80001f'); // Uint8Array([0x80, 0x00, 0x1f]) 38 | * hexToU8a('0x80001f', 32); // Uint8Array([0x00, 0x80, 0x00, 0x1f]) 39 | * ``` 40 | */ 41 | export function hexToU8a(value?: HexString | string | null, bitLength = -1): Uint8Array { 42 | if (!value) { 43 | return new Uint8Array(); 44 | } 45 | 46 | let s = value.startsWith('0x') ? 2 : 0; 47 | 48 | const decLength = Math.ceil((value.length - s) / 2); 49 | const endLength = Math.ceil(bitLength === -1 ? decLength : bitLength / 8); 50 | const result = new Uint8Array(endLength); 51 | const offset = endLength > decLength ? endLength - decLength : 0; 52 | 53 | for (let i = offset; i < endLength; i++, s += 2) { 54 | // The big factor here is actually the string lookups. If we do 55 | // HEX_TO_U16[value.substring()] we get an 10x slowdown. In the 56 | // same vein using charCodeAt (as opposed to value[s] or value.charAt(s)) is 57 | // also the faster operation by at least 2x with the character map above 58 | result[i] = U16[(value.charCodeAt(s) << 8) | value.charCodeAt(s + 1)]; 59 | } 60 | 61 | return result; 62 | } 63 | -------------------------------------------------------------------------------- /packages/evm-test-utils/src/localTestnet.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Webb Technologies Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | import { getChainIdType } from '@webb-tools/utils'; 18 | import { ethers } from 'ethers'; 19 | import { GanacheAccounts, LocalEvmChain } from './'; 20 | 21 | // Describes chain info 22 | type LocalChainOpts = { 23 | name: string; 24 | port: number; 25 | chainId: number; 26 | populatedAccounts: GanacheAccounts[]; 27 | enableLogging?: boolean; 28 | }; 29 | 30 | export class LocalChain { 31 | private localEvmChain: LocalEvmChain; 32 | public readonly endpoint: string; 33 | private constructor(private readonly opts: LocalChainOpts, localEvmChain: LocalEvmChain) { 34 | this.localEvmChain = localEvmChain; 35 | this.endpoint = `http://127.0.0.1:${opts.port}`; 36 | } 37 | 38 | public static async init(opts: LocalChainOpts) { 39 | const evmChain = await LocalEvmChain.init(opts.name, opts.chainId, opts.populatedAccounts); 40 | const localChain = new LocalChain(opts, evmChain); 41 | 42 | return localChain; 43 | } 44 | 45 | public get name(): string { 46 | return this.opts.name; 47 | } 48 | 49 | public get chainId(): number { 50 | return getChainIdType(this.opts.chainId); 51 | } 52 | 53 | public get underlyingChainId(): number { 54 | return this.opts.chainId; 55 | } 56 | 57 | public provider(): ethers.providers.WebSocketProvider { 58 | return new ethers.providers.WebSocketProvider(this.endpoint, { 59 | chainId: this.underlyingChainId, 60 | name: this.opts.name, 61 | }); 62 | } 63 | 64 | public async stop() { 65 | await this.localEvmChain.stop(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /packages/contracts/contracts/verifiers/VAnchorVerifier.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | import "../interfaces/verifiers/IAnchorVerifier.sol"; 9 | import "../interfaces/verifiers/IVAnchorVerifier.sol"; 10 | 11 | /// @title VAnchorVerifier contract. 12 | /// @author Webb Technologies. 13 | /// @notice This contract is used to verify the proofs for the VAnchor. 14 | contract VAnchorVerifier is IAnchorVerifier { 15 | IVAnchorVerifier2_2 public v2_2; 16 | IVAnchorVerifier2_16 public v2_16; 17 | 18 | IVAnchorVerifier8_2 public v8_2; 19 | IVAnchorVerifier8_16 public v8_16; 20 | 21 | constructor( 22 | IVAnchorVerifier2_2 _verifier_2_2, 23 | IVAnchorVerifier2_16 _verifier_2_16, 24 | IVAnchorVerifier8_2 _verifier_8_2, 25 | IVAnchorVerifier8_16 _verifier_8_16 26 | ) { 27 | require( 28 | address(_verifier_2_2) != address(0) && 29 | address(_verifier_2_16) != address(0) && 30 | address(_verifier_8_2) != address(0) && 31 | address(_verifier_8_16) != address(0), 32 | "VAnchorVerifier: Cannot set verifier to 0 address" 33 | ); 34 | v2_2 = _verifier_2_2; 35 | v2_16 = _verifier_2_16; 36 | v8_2 = _verifier_8_2; 37 | v8_16 = _verifier_8_16; 38 | } 39 | 40 | function verifyProof( 41 | uint[2] memory a, 42 | uint[2][2] memory b, 43 | uint[2] memory c, 44 | bytes memory input, 45 | uint8 maxEdges, 46 | bool smallInputs 47 | ) external view override returns (bool r) { 48 | if (maxEdges == 1) { 49 | if (smallInputs) { 50 | uint256[9] memory _inputs = abi.decode(input, (uint256[9])); 51 | return v2_2.verifyProof(a, b, c, _inputs); 52 | } else { 53 | uint256[23] memory _inputs = abi.decode(input, (uint256[23])); 54 | return v2_16.verifyProof(a, b, c, _inputs); 55 | } 56 | } else if (maxEdges == 7) { 57 | if (smallInputs) { 58 | uint256[15] memory _inputs = abi.decode(input, (uint256[15])); 59 | return v8_2.verifyProof(a, b, c, _inputs); 60 | } else { 61 | uint256[29] memory _inputs = abi.decode(input, (uint256[29])); 62 | return v8_16.verifyProof(a, b, c, _inputs); 63 | } 64 | } else { 65 | require(false, "VAnchorVerifier: Invalid maxEdges"); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /packages/tokens/src/MintableToken.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber, BigNumberish, ContractTransaction, ethers } from 'ethers'; 2 | import { ERC20PresetMinterPauser, ERC20PresetMinterPauser__factory } from '@webb-tools/contracts'; 3 | 4 | class MintableToken { 5 | contract: ERC20PresetMinterPauser; 6 | signer: ethers.Signer; 7 | name: string; 8 | symbol: string; 9 | 10 | constructor( 11 | contract: ERC20PresetMinterPauser, 12 | name: string, 13 | symbol: string, 14 | signer: ethers.Signer 15 | ) { 16 | this.contract = contract; 17 | this.signer = signer; 18 | this.name = name; 19 | this.symbol = symbol; 20 | } 21 | 22 | public static async createToken(name: string, symbol: string, creator: ethers.Signer) { 23 | const factory = new ERC20PresetMinterPauser__factory(creator); 24 | const token = await factory.deploy(name, symbol); 25 | await token.deployed(); 26 | return new MintableToken(token, name, symbol, creator); 27 | } 28 | 29 | public static async tokenFromAddress( 30 | contract: string, 31 | signer: ethers.Signer 32 | ): Promise { 33 | const token = ERC20PresetMinterPauser__factory.connect(contract, signer); 34 | const name = await token.name(); 35 | const symbol = await token.symbol(); 36 | return new MintableToken(token, name, symbol, signer); 37 | } 38 | 39 | public getAllowance(owner: string, spender: string): Promise { 40 | return this.contract.allowance(owner, spender); 41 | } 42 | 43 | public getBalance(address: string): Promise { 44 | return this.contract.balanceOf(address); 45 | } 46 | 47 | public async approveSpending(spender: string, amount: BigNumber): Promise { 48 | const tx = await this.contract.approve(spender, amount); 49 | await tx.wait(); 50 | return tx; 51 | } 52 | 53 | public async mintTokens(address: string, amount: BigNumberish) { 54 | const tx = await this.contract.mint(address, amount); 55 | await tx.wait(); 56 | return; 57 | } 58 | 59 | public grantMinterRole(address: string) { 60 | const MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes('MINTER_ROLE')); 61 | return this.contract.grantRole(MINTER_ROLE, address); 62 | } 63 | } 64 | 65 | export { MintableToken }; 66 | -------------------------------------------------------------------------------- /circuits/merkle-tree/merkleTree.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | include "../../node_modules/circomlib/circuits/poseidon.circom"; 3 | include "../../node_modules/circomlib/circuits/bitify.circom"; 4 | 5 | // Computes Poseidon([left, right]) 6 | template HashLeftRight() { 7 | signal input left; 8 | signal input right; 9 | signal output hash; 10 | 11 | component hasher = Poseidon(2); 12 | hasher.inputs[0] <== left; 13 | hasher.inputs[1] <== right; 14 | hash <== hasher.out; 15 | } 16 | 17 | // if s == 0 returns [in[0], in[1]] 18 | // if s == 1 returns [in[1], in[0]] 19 | template DualMux() { 20 | signal input in[2]; 21 | signal input s; 22 | signal output out[2]; 23 | 24 | s * (1 - s) === 0; 25 | out[0] <== (in[1] - in[0])*s + in[0]; 26 | out[1] <== (in[0] - in[1])*s + in[1]; 27 | } 28 | 29 | // Computes and outputs a merkle root based on the provided merkle proof. 30 | // pathIndices input is an array of 0/1 selectors telling whether given pathElement is on the left or right side of merkle path 31 | template RawMerkleTree(levels) { 32 | signal input leaf; 33 | signal input pathElements[levels]; 34 | signal input pathIndices[levels]; 35 | 36 | signal output root; 37 | 38 | component selectors[levels]; 39 | component hashers[levels]; 40 | 41 | for (var i = 0; i < levels; i++) { 42 | selectors[i] = DualMux(); 43 | selectors[i].in[0] <== i == 0 ? leaf : hashers[i - 1].hash; 44 | selectors[i].in[1] <== pathElements[i]; 45 | selectors[i].s <== pathIndices[i]; 46 | 47 | hashers[i] = HashLeftRight(); 48 | hashers[i].left <== selectors[i].out[0]; 49 | hashers[i].right <== selectors[i].out[1]; 50 | } 51 | 52 | root <== hashers[levels - 1].hash; 53 | } 54 | 55 | template MerkleTree(levels) { 56 | signal input leaf; 57 | signal input pathElements[levels]; 58 | signal input pathIndices; 59 | signal output root; 60 | 61 | component indexBits = Num2Bits(levels); 62 | indexBits.in <== pathIndices; 63 | 64 | component tree = RawMerkleTree(levels); 65 | tree.leaf <== leaf; 66 | for (var i = 0; i < levels; i++) { 67 | tree.pathIndices[i] <== indexBits.out[i]; 68 | tree.pathElements[i] <== pathElements[i]; 69 | } 70 | 71 | root <== tree.root; 72 | } 73 | -------------------------------------------------------------------------------- /packages/contracts/contracts/handlers/HandlerHelpers.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | import "../interfaces/IExecutor.sol"; 9 | 10 | /// @title Function used across handler contracts. 11 | /// @author Webb Technologies, adapted from ChainSafe Systems. 12 | /// @notice This contract is intended to be used with the Bridge contract. 13 | abstract contract HandlerHelpers is IExecutor { 14 | address public _bridgeAddress; 15 | 16 | /// resourceID => token contract address 17 | mapping(bytes32 => address) public _resourceIDToContractAddress; 18 | 19 | /// Execution contract address => resourceID 20 | mapping(address => bytes32) public _contractAddressToResourceID; 21 | 22 | /// Execution contract address => is whitelisted 23 | mapping(address => bool) public _contractWhitelist; 24 | 25 | modifier onlyBridge() { 26 | _onlyBridge(); 27 | _; 28 | } 29 | 30 | function _onlyBridge() private view { 31 | require(msg.sender == _bridgeAddress, "HandlerHelpers: sender must be bridge contract"); 32 | } 33 | 34 | /// @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and 35 | /// {_contractAddressToResourceID}[{contractAddress}] are not already set, 36 | /// then sets {_resourceIDToContractAddress} with {contractAddress}, 37 | /// {_contractAddressToResourceID} with {resourceID}, 38 | /// and {_contractWhitelist} to true for {contractAddress}. 39 | /// @param resourceID ResourceID to be used when executing proposals. 40 | /// @param contractAddress Address of contract to be called when a proposal is signed and submitted for execution. 41 | function setResource(bytes32 resourceID, address contractAddress) external override onlyBridge { 42 | _setResource(resourceID, contractAddress); 43 | } 44 | 45 | function _setResource(bytes32 resourceID, address contractAddress) internal { 46 | _resourceIDToContractAddress[resourceID] = contractAddress; 47 | _contractAddressToResourceID[contractAddress] = resourceID; 48 | 49 | _contractWhitelist[contractAddress] = true; 50 | } 51 | 52 | function migrateBridge(address newBridge) external override onlyBridge { 53 | require(newBridge != address(0), "HandlerHelpers: Bridge address can't be 0"); 54 | _bridgeAddress = newBridge; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/contracts/contracts/utils/ChainIdWithType.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title ChainIdWithType abstract contract 9 | abstract contract ChainIdWithType { 10 | bytes2 public constant EVM_CHAIN_ID_TYPE = 0x0100; 11 | 12 | /// @notice Gets the chain id using the chain id opcode 13 | function getChainId() public view returns (uint) { 14 | uint chainId; 15 | assembly { 16 | chainId := chainid() 17 | } 18 | return chainId; 19 | } 20 | 21 | /// @notice Computes the modified chain id using the underlying chain type (EVM) 22 | function getChainIdType() public view returns (uint48) { 23 | // The chain ID and type pair is 6 bytes in length 24 | // The first 2 bytes are reserved for the chain type. 25 | // The last 4 bytes are reserved for a u32 (uint32) chain ID. 26 | bytes4 chainID = bytes4(uint32(getChainId())); 27 | bytes2 chainType = EVM_CHAIN_ID_TYPE; 28 | // We encode the chain ID and type pair into packed bytes which 29 | // should be 6 bytes using the encode packed method. We will 30 | // cast this as a bytes32 in order to encode as a uint256 for zkp verification. 31 | bytes memory chainIdWithType = abi.encodePacked(chainType, chainID); 32 | return uint48(bytes6(chainIdWithType)); 33 | } 34 | 35 | /// @notice Parses the typed chain ID out from a 32-byte resource ID 36 | function parseChainIdFromResourceId(bytes32 _resourceId) public pure returns (uint64) { 37 | return uint64(uint48(bytes6(_resourceId << (26 * 8)))); 38 | } 39 | 40 | /// @notice Verifies that the current chain matches the chain ID from the resource ID 41 | /// @param resourceID The resource ID to verify 42 | function isCorrectExecutionChain(bytes32 resourceID) public view returns (bool) { 43 | uint64 executionChainId = parseChainIdFromResourceId(resourceID); 44 | // Verify current chain matches chain ID from resource ID 45 | return uint256(getChainIdType()) == uint256(executionChainId); 46 | } 47 | 48 | /// @notice Verifies that the current execution context matches the execution context from the resource ID 49 | /// @param resourceId The resource ID to verify 50 | function isCorrectExecutionContext(bytes32 resourceId) public view returns (bool) { 51 | return address(bytes20(resourceId << (6 * 8))) == address(this); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/contracts/contracts/vanchors/instances/VAnchorTree.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | import "../base/VAnchor.sol"; 9 | import "../../trees/MerkleTree.sol"; 10 | 11 | /// @title Variable Anchor Forest contract 12 | /// @author Webb Technologies 13 | /// @notice The Variable Anchor Forest is the same as a VAnchor system but with 14 | /// many merkle trees for commitment storage. 15 | contract VAnchorTree is VAnchor, MerkleTree { 16 | using SafeERC20 for IERC20; 17 | 18 | /// @notice The VAnchorTree constructor 19 | /// @param _verifier The address of SNARK verifier for this contract 20 | /// @param _merkleTreeLevels The height/# of levels of underlying Merkle Tree 21 | /// @param _hasher The address of hash contract 22 | /// @param _handler The address of AnchorHandler for this contract 23 | /// @param _token The address of the token that is used to pay the deposit 24 | /// @param _maxEdges The maximum number of edges in the LinkableAnchor + Verifier supports. 25 | /// @notice The `_maxEdges` is zero-knowledge circuit dependent, meaning the 26 | /// `_verifier` ONLY supports a certain maximum # of edges. Therefore we need to 27 | /// limit the size of the LinkableAnchor with this parameter. 28 | constructor( 29 | IAnchorVerifier _verifier, 30 | uint32 _merkleTreeLevels, 31 | IHasher _hasher, 32 | address _handler, 33 | address _token, 34 | uint8 _maxEdges 35 | ) 36 | VAnchor(_verifier, _merkleTreeLevels, _handler, _token, _maxEdges) 37 | MerkleTree(_merkleTreeLevels, _hasher) 38 | {} 39 | 40 | /// @inheritdoc ZKVAnchorBase 41 | function _executeInsertions( 42 | PublicInputs memory _publicInputs, 43 | Encryptions memory _encryptions 44 | ) internal override { 45 | insertTwo(_publicInputs.outputCommitments[0], _publicInputs.outputCommitments[1]); 46 | emit NewCommitment( 47 | _publicInputs.outputCommitments[0], 48 | 0, 49 | this.getNextIndex() - 2, 50 | _encryptions.encryptedOutput1 51 | ); 52 | emit NewCommitment( 53 | _publicInputs.outputCommitments[1], 54 | 0, 55 | this.getNextIndex() - 1, 56 | _encryptions.encryptedOutput2 57 | ); 58 | for (uint256 i = 0; i < _publicInputs.inputNullifiers.length; i++) { 59 | emit NewNullifier(_publicInputs.inputNullifiers[i]); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/proposals/src/ProposalHeader.ts: -------------------------------------------------------------------------------- 1 | import { u8aToHex } from '@webb-tools/utils'; 2 | import { BE } from './'; 3 | import { IResourceId, ResourceId } from './ResourceId'; 4 | 5 | /** 6 | * Proposal Header is the first 40 bytes of any proposal and it contains the following information: 7 | * - resource id (32 bytes) 8 | * - target function signature (4 bytes) 9 | * - nonce (4 bytes). 10 | */ 11 | export interface IProposalHeader { 12 | /** 13 | * 32 bytes ResourceId 14 | */ 15 | readonly resourceId: IResourceId; 16 | /** 17 | * 4 bytes function signature / function identifier 18 | */ 19 | readonly functionSignature: Uint8Array; 20 | /** 21 | * 4 bytes Hex-encoded string of the `nonce` for this proposal. 22 | */ 23 | readonly nonce: number; 24 | } 25 | 26 | /** 27 | * Proposal Header class 28 | */ 29 | export class ProposalHeader implements IProposalHeader { 30 | resourceId: IResourceId; 31 | functionSignature: Uint8Array; 32 | nonce: number; 33 | 34 | constructor(resourceId: IResourceId, functionSignature: Uint8Array, nonce: number) { 35 | this.resourceId = resourceId; 36 | this.functionSignature = functionSignature; 37 | this.nonce = nonce; 38 | } 39 | 40 | /** 41 | * Converts a 40-byte Uint8Array into a proposal header. 42 | */ 43 | static fromBytes(bytes: Uint8Array): ProposalHeader { 44 | if (bytes.length !== 40) { 45 | throw new Error('bytes must be 40 bytes'); 46 | } 47 | 48 | const resourceId = ResourceId.fromBytes(bytes.slice(0, 32)); 49 | const functionSignature = bytes.slice(32, 36); 50 | const nonce = new DataView(bytes.buffer).getUint32(36, BE); 51 | 52 | return new ProposalHeader(resourceId, functionSignature, nonce); 53 | } 54 | 55 | /** 56 | * Converts the proposal header into a 40-byte Uint8Array. 57 | */ 58 | toU8a(): Uint8Array { 59 | const proposalHeader = new Uint8Array(40); 60 | 61 | proposalHeader.set(this.resourceId.toU8a(), 0); 62 | proposalHeader.set(this.functionSignature.slice(0, 4), 32); 63 | const buf = Buffer.allocUnsafe(4); 64 | 65 | buf.writeUInt32BE(this.nonce, 0); 66 | 67 | proposalHeader.set(buf, 36); 68 | 69 | return proposalHeader; 70 | } 71 | 72 | /** 73 | * Converts the proposal header into a 40-byte Hex-encoded string. 74 | */ 75 | toString(): string { 76 | return u8aToHex(this.toU8a()); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /packages/utils/src/proof/index.ts: -------------------------------------------------------------------------------- 1 | export * from './variable-anchor'; 2 | export * from './build-variable-witness'; 3 | 4 | import { ethers } from 'ethers'; 5 | import { p256 } from '../utils'; 6 | 7 | export type Proof = { 8 | pi_a: string[3]; 9 | pi_b: Array; 10 | pi_c: string[3]; 11 | protocol: string; 12 | curve: string; 13 | }; 14 | 15 | export type VAnchorProofInputs = { 16 | roots: string[]; 17 | chainID: string; 18 | inputNullifier: string[]; 19 | outputCommitment: string[]; 20 | publicAmount: string; 21 | extDataHash: string; 22 | 23 | // data for 2 transaction inputs 24 | inAmount: string[]; 25 | inPrivateKey: string[]; 26 | inBlinding: string[]; 27 | inPathIndices: number[][]; 28 | inPathElements: number[][]; 29 | 30 | // data for 2 transaction outputs 31 | outChainID: string; 32 | outAmount: string[]; 33 | outPubkey: string[]; 34 | outBlinding: string[]; 35 | }; 36 | 37 | export function groth16ExportSolidityCallData(proof: any, pub: any) { 38 | let inputs = ''; 39 | 40 | for (let i = 0; i < pub.length; i++) { 41 | if (inputs !== '') { 42 | inputs = inputs + ','; 43 | } 44 | 45 | inputs = inputs + p256(pub[i]); 46 | } 47 | 48 | const S = 49 | `[${p256(proof.pi_a[0])}, ${p256(proof.pi_a[1])}],` + 50 | `[[${p256(proof.pi_b[0][1])}, ${p256(proof.pi_b[0][0])}],[${p256(proof.pi_b[1][1])}, ${p256( 51 | proof.pi_b[1][0] 52 | )}]],` + 53 | `[${p256(proof.pi_c[0])}, ${p256(proof.pi_c[1])}],` + 54 | `[${inputs}]`; 55 | 56 | return S; 57 | } 58 | 59 | export function generateWithdrawProofCallData(proof: any, publicSignals: any) { 60 | const result = groth16ExportSolidityCallData(proof, publicSignals); 61 | const fullProof = JSON.parse('[' + result + ']'); 62 | const pi_a = fullProof[0]; 63 | const pi_b = fullProof[1]; 64 | const pi_c = fullProof[2]; 65 | 66 | const proofEncoded = [ 67 | pi_a[0], 68 | pi_a[1], 69 | pi_b[0][0], 70 | pi_b[0][1], 71 | pi_b[1][0], 72 | pi_b[1][1], 73 | pi_c[0], 74 | pi_c[1], 75 | ] 76 | .map((elt) => elt.substr(2)) 77 | .join(''); 78 | 79 | return proofEncoded; 80 | } 81 | 82 | export const generateFunctionSigHash = (functionSignature: string): string => { 83 | return ethers.utils 84 | .keccak256(ethers.utils.toUtf8Bytes(functionSignature)) 85 | .slice(0, 10) 86 | .padEnd(10, '0'); 87 | }; 88 | -------------------------------------------------------------------------------- /.github/workflows/test-check.yml: -------------------------------------------------------------------------------- 1 | name: run-test-suite 2 | 3 | on: 4 | push: 5 | branches: [ 'main' ] 6 | pull_request: 7 | types: [opened, synchronize, reopened, ready_for_review] 8 | branches: [ '**' ] 9 | paths-ignore: 10 | - 'README.md' 11 | 12 | workflow_dispatch: 13 | 14 | jobs: 15 | # sets up build artifacts for other jobs to use 16 | setup-build: 17 | runs-on: ubuntu-latest 18 | strategy: 19 | matrix: 20 | node-version: [18.15.0] 21 | steps: 22 | - uses: actions/checkout@v3 23 | - uses: actions/setup-node@v3 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | 27 | - name: Install dependencies 28 | run: yarn install --production=false 29 | 30 | - name: clean 31 | run: yarn clean 32 | 33 | - name: Compile @webb-tools/contracts 34 | run: lerna run compile --scope=@webb-tools/contracts 35 | 36 | - name: Build packages 37 | run: lerna run build 38 | 39 | - name: Upload build artifacts 40 | uses: actions/upload-artifact@v2 41 | with: 42 | name: build-artifacts 43 | path: | 44 | packages/**/dist 45 | !packages/**/node_modules 46 | 47 | test: 48 | needs: setup-build 49 | concurrency: 50 | group: test-${{ github.ref }} 51 | cancel-in-progress: true 52 | runs-on: ubuntu-latest 53 | if: github.ref != 'refs/heads/main' && github.event.pull_request.draft == false 54 | strategy: 55 | matrix: 56 | node-version: [18.15.0] 57 | steps: 58 | - uses: actions/checkout@v3 59 | - name: Download build artifacts 60 | uses: actions/download-artifact@v2 61 | with: 62 | name: build-artifacts 63 | path: packages 64 | 65 | - uses: actions/setup-node@v3 66 | with: 67 | node-version: ${{ matrix.node-version }} 68 | 69 | - name: Setup DVC 70 | uses: iterative/setup-dvc@v1 71 | 72 | - name: Fetch submodules 73 | run: git submodule update --init --recursive 74 | 75 | - name: Install dependencies 76 | run: yarn install --production=false 77 | 78 | - name: Populate fixtures 79 | run: yarn fetch:fixtures 80 | 81 | - name: Run test suite 82 | env: 83 | INFURA_API_KEY: ${{ secrets.INFURA_API_KEY }} 84 | run: yarn test -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1681202837, 9 | "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "cfacdce06f30d2b68473a46042957675eebb3401", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "foundry": { 22 | "inputs": { 23 | "flake-utils": [ 24 | "flake-utils" 25 | ], 26 | "nixpkgs": [ 27 | "nixpkgs" 28 | ] 29 | }, 30 | "locked": { 31 | "lastModified": 1683882555, 32 | "narHash": "sha256-oYHUqNcJSXHP1UuGY9LYxUfEOXubCziFQX70LNFO3yQ=", 33 | "owner": "shazow", 34 | "repo": "foundry.nix", 35 | "rev": "33293bb20a2848ed56a945f5049a3678844fa2a7", 36 | "type": "github" 37 | }, 38 | "original": { 39 | "owner": "shazow", 40 | "repo": "foundry.nix", 41 | "type": "github" 42 | } 43 | }, 44 | "nixpkgs": { 45 | "locked": { 46 | "lastModified": 1683777345, 47 | "narHash": "sha256-V2p/A4RpEGqEZussOnHYMU6XglxBJGCODdzoyvcwig8=", 48 | "owner": "NixOS", 49 | "repo": "nixpkgs", 50 | "rev": "635a306fc8ede2e34cb3dd0d6d0a5d49362150ed", 51 | "type": "github" 52 | }, 53 | "original": { 54 | "owner": "NixOS", 55 | "ref": "nixpkgs-unstable", 56 | "repo": "nixpkgs", 57 | "type": "github" 58 | } 59 | }, 60 | "root": { 61 | "inputs": { 62 | "flake-utils": "flake-utils", 63 | "foundry": "foundry", 64 | "nixpkgs": "nixpkgs" 65 | } 66 | }, 67 | "systems": { 68 | "locked": { 69 | "lastModified": 1681028828, 70 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 71 | "owner": "nix-systems", 72 | "repo": "default", 73 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 74 | "type": "github" 75 | }, 76 | "original": { 77 | "owner": "nix-systems", 78 | "repo": "default", 79 | "type": "github" 80 | } 81 | } 82 | }, 83 | "root": "root", 84 | "version": 7 85 | } 86 | -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/tokens/IFungibleTokenWrapper.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title Interface for Token Wrapper contract. 9 | /// @author Webb Technologies. 10 | /// @notice This contract is meant to be used with the `TokenWrapper` contract. 11 | interface IFungibleTokenWrapper { 12 | /// @notice Adds a token at `_tokenAddress` to the FungibleTokenWrapper's wrapping list 13 | /// @param _tokenAddress The address of the token to be added 14 | /// @param _nonce The nonce tracking updates to this contract 15 | /// @notice Only the handler can call this function 16 | function add(address _tokenAddress, uint32 _nonce) external; 17 | 18 | /// @notice Removes a token at `_tokenAddress` from the FungibleTokenWrapper's wrapping list 19 | /// @param _tokenAddress The address of the token to be removed 20 | /// @param _nonce The nonce tracking updates to this contract 21 | /// @notice Only the handler can call this function 22 | function remove(address _tokenAddress, uint32 _nonce) external; 23 | 24 | /// @notice Sets a new `_feePercentage` for the FungibleTokenWrapper 25 | /// @param _feePercentage The new fee percentage 26 | /// @param _nonce The nonce tracking updates to this contract 27 | /// @notice Only the handler can call this function 28 | function setFee(uint16 _feePercentage, uint32 _nonce) external; 29 | 30 | /// @notice Sets a new `_feeRecipient` for the FungibleTokenWrapper 31 | /// @param _feeRecipient The new fee recipient 32 | /// @param _nonce The nonce tracking updates to this contract 33 | /// @notice Only the handler can call this function 34 | function setFeeRecipient(address payable _feeRecipient, uint32 _nonce) external; 35 | 36 | /// @notice Sets native allowed wrapping for the FungibleTokenWrapper 37 | /// @param _nativeAllowed The new native allowed wrapping 38 | /// @param _nonce The nonce tracking updates to this contract 39 | /// @notice Only the handler can call this function 40 | function setNativeAllowed(bool _nativeAllowed, uint32 _nonce) external; 41 | 42 | /// @notice Sets a new `_handler` for the FungibleTokenWrapper 43 | /// @param _handler The new handler 44 | /// @param _nonce The nonce tracking updates to this contract 45 | /// @notice Only the handler can call this function 46 | function setHandler(address _handler, uint32 _nonce) external; 47 | } 48 | -------------------------------------------------------------------------------- /packages/contracts/contracts/interfaces/verifiers/IVAnchorVerifier.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title IVAnchorVerifier join/split verifier interface with 2 edges 9 | /// @author Webb Technologies. 10 | /// and 2 inputs to 2 outputs. 11 | /// @notice The X_Y (2_2) identifiers designate the following: 12 | /// - X is the # of edges supported on this VAnchor (i.e. 2) 13 | /// - Y is the # of inputs to the join/split transaction (i.e. 2) 14 | interface IVAnchorVerifier2_2 { 15 | function verifyProof( 16 | uint[2] memory a, 17 | uint[2][2] memory b, 18 | uint[2] memory c, 19 | uint256[9] memory input 20 | ) external view returns (bool r); 21 | } 22 | 23 | /// @title IVAnchorVerifier join/split verifier interface with 2 edges 24 | /// @author Webb Technologies. 25 | /// and 16 inputs to 2 outputs. 26 | /// @notice The X_Y (2_16) identifiers designate the following: 27 | /// - X is the # of edges supported on this VAnchor (i.e. 2) 28 | /// - Y is the # of inputs to the join/split transaction (i.e. 16) 29 | interface IVAnchorVerifier2_16 { 30 | function verifyProof( 31 | uint[2] memory a, 32 | uint[2][2] memory b, 33 | uint[2] memory c, 34 | uint256[23] memory input 35 | ) external view returns (bool r); 36 | } 37 | 38 | /// @title IVAnchorVerifier join/split verifier interface with 8 edges 39 | /// @author Webb Technologies. 40 | /// and 2 inputs to 2 outputs. 41 | /// @notice The X_Y (8_2) identifiers designate the following: 42 | /// - X is the # of edges supported on this VAnchor (i.e. 8) 43 | /// - Y is the # of inputs to the join/split transaction (i.e. 2) 44 | interface IVAnchorVerifier8_2 { 45 | function verifyProof( 46 | uint[2] memory a, 47 | uint[2][2] memory b, 48 | uint[2] memory c, 49 | uint256[15] memory input 50 | ) external view returns (bool r); 51 | } 52 | 53 | /// @title IVAnchorVerifier join/split verifier interface with 2 edges 54 | /// @author Webb Technologies. 55 | /// and 2 inputs to 2 outputs. 56 | /// @notice The X_Y (8_16) identifiers designate the following: 57 | /// - X is the # of edges supported on this VAnchor (i.e. 8) 58 | /// - Y is the # of inputs to the join/split transaction (i.e. 16) 59 | interface IVAnchorVerifier8_16 { 60 | function verifyProof( 61 | uint[2] memory a, 62 | uint[2][2] memory b, 63 | uint[2] memory c, 64 | uint256[29] memory input 65 | ) external view returns (bool r); 66 | } 67 | -------------------------------------------------------------------------------- /packages/contracts/test/token/FungibleTokenWrapper.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | const assert = require('assert'); 6 | import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; 7 | import { ethers } from 'hardhat'; 8 | 9 | import { 10 | ERC20 as ERC20Class, 11 | FungibleTokenWrapper as FungibleTokenWrapperClass, 12 | } from '@webb-tools/tokens'; 13 | 14 | describe('FungibleTokenWrapper', () => { 15 | let token: ERC20Class; 16 | let wrappedToken: FungibleTokenWrapperClass; 17 | let tokenDenomination = '1000000000000000000'; // 1 ether 18 | let sender: SignerWithAddress; 19 | const tokenName = 'Token'; 20 | const tokenSymbol = 'TKN'; 21 | const wrappedTokenName = 'Wrapped Token'; 22 | const wrappedTokenSymbol = 'wTKN'; 23 | 24 | beforeEach(async () => { 25 | const signers = await ethers.getSigners(); 26 | const wallet = signers[0]; 27 | sender = wallet; 28 | 29 | token = await ERC20Class.createERC20PresetMinterPauser(tokenName, tokenSymbol, wallet); 30 | const dummyFeeRecipient = '0x0000000000010000000010000000000000000000'; 31 | wrappedToken = await FungibleTokenWrapperClass.createFungibleTokenWrapper( 32 | wrappedTokenName, 33 | wrappedTokenSymbol, 34 | 0, 35 | dummyFeeRecipient, 36 | sender.address, 37 | tokenDenomination, 38 | false, 39 | wallet 40 | ); 41 | }); 42 | 43 | describe('#constructor', () => { 44 | it('should initialize', async () => { 45 | assert.strictEqual(await wrappedToken.contract.name(), wrappedTokenName); 46 | assert.strictEqual(await wrappedToken.contract.symbol(), wrappedTokenSymbol); 47 | assert.strictEqual(await wrappedToken.contract.handler(), sender.address); 48 | assert.strictEqual( 49 | (await wrappedToken.contract.wrappingLimit()).toString(), 50 | tokenDenomination 51 | ); 52 | assert.strictEqual((await wrappedToken.contract.totalSupply()).toString(), '0'); 53 | }); 54 | 55 | it('should properly calculate amountToWrap', async () => { 56 | const webbWrappedTokenContract = wrappedToken.contract; 57 | let tx = await webbWrappedTokenContract.setFee(1, 1); 58 | await tx.wait(); 59 | let amountToWrap = await webbWrappedTokenContract.getAmountToWrap( 60 | ethers.utils.parseEther('1') 61 | ); 62 | 63 | assert.strictEqual( 64 | amountToWrap.toString(), 65 | ethers.BigNumber.from('1000100010001000100').toString() 66 | ); 67 | }); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /packages/contracts/contracts/test/TreasuryHandler.t.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | pragma solidity >=0.8.19 <0.9.0; 6 | 7 | import { console2 } from "forge-std/console2.sol"; 8 | import { StdCheats } from "forge-std/StdCheats.sol"; 9 | 10 | import { Deployer } from "./Deployer.t.sol"; 11 | 12 | contract TreasuryHandlerTest is Deployer { 13 | function setUp() public virtual override { 14 | super.setUp(); 15 | } 16 | 17 | function test_deployTreasuryHandler() public { 18 | assertEq(treasury.handler(), address(treasuryHandler)); 19 | assertEq(bridge._resourceIdToHandlerAddress(treasuryResourceId), address(treasuryHandler)); 20 | assertEq(treasuryHandler._bridgeAddress(), address(bridge)); 21 | 22 | assertEq( 23 | treasuryHandler._resourceIDToContractAddress(treasuryResourceId), 24 | address(treasury) 25 | ); 26 | assertEq( 27 | treasuryHandler._contractAddressToResourceID(address(treasury)), 28 | treasuryResourceId 29 | ); 30 | } 31 | 32 | function test_executeRescueTokensProposal() public { 33 | // First send a bunch of ETH to the treasury 34 | uint256 ethAmount = 100 ether; 35 | vm.deal(address(treasury), ethAmount); 36 | // Now let's rescue this ETH and send to a random address. 37 | uint256 balanceBefore = vm.addr(2).balance; 38 | uint256 rescuedAmount = 50 ether; 39 | this.executeRescueTokensProposal( 40 | treasuryResourceId, 41 | uint32(treasury.proposalNonce()) + 1, 42 | address(0), 43 | vm.addr(2), 44 | rescuedAmount 45 | ); 46 | // Verify the amount was rescued 47 | assertEq(address(treasury).balance, ethAmount - rescuedAmount); 48 | assertEq(vm.addr(2).balance, balanceBefore + rescuedAmount); 49 | } 50 | 51 | function test_executeRescueTokensProposalShouldFailFromNotHandler() public { 52 | address tokenToRescue = address(0); 53 | address payable recipient = payable(vm.addr(2)); 54 | uint256 amountToRescue = 50 ether; 55 | uint32 nonce = uint32(treasury.proposalNonce() + 1); 56 | vm.deal(address(treasury), 100 ether); 57 | vm.expectRevert("Treasury: Function can only be called by treasury handler"); 58 | treasury.rescueTokens(tokenToRescue, recipient, amountToRescue, nonce); 59 | } 60 | 61 | function test_setHandlerProposal(address newHandler) public { 62 | vm.assume(newHandler != address(treasuryHandler)); 63 | vm.assume(newHandler != address(0)); 64 | this.executeSetHandlerProposal( 65 | treasuryResourceId, 66 | uint32(treasury.proposalNonce()) + 1, 67 | newHandler 68 | ); 69 | assertEq(treasury.handler(), newHandler); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /circuits/merkle-tree/merkleForest.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../../node_modules/circomlib/circuits/bitify.circom"; 4 | include "../../node_modules/circomlib/circuits/poseidon.circom"; 5 | include "../../node_modules/circomlib/circuits/switcher.circom"; 6 | include "../set/membership_if_enabled.circom"; 7 | 8 | 9 | // Verifies that merkle proof is correct for given merkle root and a leaf 10 | // pathIndices bits is an array of 0/1 selectors telling whether given pathElement is on the left or right side of merkle path 11 | template GetMerkleRoot(levels) { 12 | signal input leaf; 13 | signal input pathElements[levels]; 14 | signal input pathIndices; 15 | signal output root; 16 | 17 | component switcher[levels]; 18 | component hasher[levels]; 19 | 20 | component indexBits = Num2Bits(levels); 21 | indexBits.in <== pathIndices; 22 | 23 | for (var i = 0; i < levels; i++) { 24 | switcher[i] = Switcher(); 25 | switcher[i].L <== i == 0 ? leaf : hasher[i - 1].out; 26 | switcher[i].R <== pathElements[i]; 27 | switcher[i].sel <== indexBits.out[i]; 28 | 29 | hasher[i] = Poseidon(2); 30 | hasher[i].inputs[0] <== switcher[i].outL; 31 | hasher[i].inputs[1] <== switcher[i].outR; 32 | } 33 | 34 | // verify that the resultant hash (computed merkle root) 35 | // is in the set of roots 36 | root <== hasher[levels - 1].out; 37 | } 38 | 39 | template MerkleForest(groupLevels, subtreeLevels, length) { 40 | signal input leaf; 41 | signal input pathElements[groupLevels]; 42 | signal input pathIndices; 43 | signal input subtreePathElements[subtreeLevels]; 44 | signal input subtreePathIndices; 45 | signal input roots[length]; 46 | signal input isEnabled; 47 | 48 | component getSubtreeMerkleRoot = GetMerkleRoot(subtreeLevels); 49 | getSubtreeMerkleRoot.leaf <== leaf; 50 | getSubtreeMerkleRoot.pathIndices <== subtreePathIndices; 51 | for (var i = 0; i < subtreeLevels; i++) { 52 | getSubtreeMerkleRoot.pathElements[i] <== subtreePathElements[i]; 53 | } 54 | component getMerkleRoot = GetMerkleRoot(groupLevels); 55 | getMerkleRoot.leaf <== getSubtreeMerkleRoot.root; 56 | getMerkleRoot.pathIndices <== pathIndices; 57 | for (var i = 0; i < groupLevels; i++) { 58 | getMerkleRoot.pathElements[i] <== pathElements[i]; 59 | } 60 | 61 | component set = ForceSetMembershipIfEnabled(length); 62 | set.enabled <== isEnabled; 63 | for (var i = 0; i < length; i++) { 64 | set.set[i] <== roots[i]; 65 | } 66 | set.element <== getMerkleRoot.root; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /packages/contracts/contracts/Treasury.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | pragma experimental ABIEncoderV2; 8 | 9 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 10 | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 11 | import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 12 | import "./interfaces/ITreasury.sol"; 13 | import "./utils/ProposalNonceTracker.sol"; 14 | 15 | /// @title Treasury contract 16 | /// @author Webb Technologies. 17 | /// @notice This contract is used to store funds and recover them. 18 | contract Treasury is ITreasury, ProposalNonceTracker, ReentrancyGuard { 19 | using SafeERC20 for IERC20; 20 | address public handler; 21 | 22 | event TreasuryHandlerUpdated(address _handler); 23 | 24 | constructor(address _treasuryHandler) { 25 | require(_treasuryHandler != address(0), "Treasury: Treasury Handler can't be 0"); 26 | handler = _treasuryHandler; 27 | } 28 | 29 | modifier onlyHandler() { 30 | require(msg.sender == handler, "Treasury: Function can only be called by treasury handler"); 31 | _; 32 | } 33 | 34 | function rescueTokens( 35 | address tokenAddress, 36 | address payable to, 37 | uint256 amountToRescue, 38 | uint32 nonce 39 | ) external override nonReentrant onlyHandler onlyIncrementingByOne(nonce) { 40 | require(to != address(0), "Treasury: Cannot send liquidity to zero address"); 41 | require(tokenAddress != address(this), "Treasury: Cannot rescue wrapped asset"); 42 | 43 | if (tokenAddress == address(0)) { 44 | // Native Ether 45 | uint256 ethBalance = address(this).balance; 46 | if (ethBalance >= amountToRescue) { 47 | (bool success, ) = payable(to).call{ value: amountToRescue }(""); 48 | require(success, "Treasury: Failed to refund"); 49 | } else { 50 | (bool success, ) = payable(to).call{ value: ethBalance }(""); 51 | require(success, "Treasury: Failed to refund"); 52 | } 53 | } else { 54 | // ERC20 Token 55 | uint256 erc20Balance = IERC20(tokenAddress).balanceOf(address(this)); 56 | if (erc20Balance >= amountToRescue) { 57 | IERC20(tokenAddress).safeTransfer(to, amountToRescue); 58 | } else { 59 | IERC20(tokenAddress).safeTransfer(to, erc20Balance); 60 | } 61 | } 62 | } 63 | 64 | function setHandler( 65 | address newHandler, 66 | uint32 nonce 67 | ) external override onlyHandler onlyIncrementingByOne(nonce) { 68 | require(newHandler != address(0), "Treasury: Handler cannot be 0"); 69 | handler = newHandler; 70 | emit TreasuryHandlerUpdated(handler); 71 | } 72 | 73 | receive() external payable {} 74 | } 75 | -------------------------------------------------------------------------------- /packages/utils/src/__test__/keypair.spec.ts: -------------------------------------------------------------------------------- 1 | import { getEncryptionPublicKey } from '@metamask/eth-sig-util'; 2 | import assert from 'assert'; 3 | import { poseidon } from 'circomlibjs'; 4 | import { Keypair } from '../protocol/keypair'; 5 | import { toFixedHex } from '../utils'; 6 | 7 | describe('Keypair constructor tests', () => { 8 | it('Should create a Keypair when using the constructor with a private key', async function () { 9 | const testPrivateKey = '0x0000000000000000000000000000000000000000000000000000000000000001'; 10 | const keypair = new Keypair(testPrivateKey); 11 | 12 | const expectedPubkey = poseidon([testPrivateKey]); 13 | const expectedEncryptionKey = 14 | '0x' + Buffer.from(getEncryptionPublicKey(testPrivateKey.slice(2)), 'base64').toString('hex'); 15 | 16 | assert(keypair.getPubKey() === toFixedHex(expectedPubkey)); 17 | assert(keypair.getEncryptionKey() === expectedEncryptionKey); 18 | 19 | const encryptedValue = keypair.encrypt(Buffer.from('hello')); 20 | const decryptedValue = keypair.decrypt(encryptedValue); 21 | 22 | assert(Buffer.from('hello').toString() === decryptedValue.toString()); 23 | }); 24 | 25 | it('Should create a Keypair consisting of just the public key', async function () { 26 | const testPublicKey = '0x0000000000000000000000000000000000000000000000000000000000000001'; 27 | const keypair = Keypair.fromString(testPublicKey); 28 | 29 | assert(keypair.getPubKey() === toFixedHex(testPublicKey)); 30 | assert(keypair.privkey === undefined); 31 | assert(keypair.getEncryptionKey() === undefined); 32 | assert.throws(() => keypair.encrypt(Buffer.from('hi'))); 33 | }); 34 | 35 | it('Should create a Keypair consisting of public key and encryption key', async function () { 36 | const testPublicKey = '0x0000000000000000000000000000000000000000000000000000000000000001'; 37 | const testEncryptionKey = '0x0000000000000000000000000000000000000000000000000000000000000002'; 38 | const testPublicData = testPublicKey + testEncryptionKey.slice(2); 39 | const keypair = Keypair.fromString(testPublicData); 40 | 41 | assert(keypair.getPubKey() === toFixedHex(testPublicKey), 'public keys not equal'); 42 | assert(keypair.toString() === testPublicData, 'serialize and deserialize the same values'); 43 | assert(keypair.getEncryptionKey() === testEncryptionKey, 'encryption keys not equal'); 44 | // make a call to encrypt and ensure the function does not throw. 45 | const encryptedValue = keypair.encrypt(Buffer.from('hello')); 46 | 47 | // make a call to decrypt and ensure the function throws 48 | assert.throws(() => keypair.decrypt(encryptedValue)); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /packages/contracts/contracts/tokens/AaveTokenWrapper.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | import "./FungibleTokenWrapper.sol"; 9 | import "../interfaces/tokens/IAaveTokenWrapper.sol"; 10 | import "../interfaces/external/aave/IAaveLendingPool.sol"; 11 | 12 | /// @title An AaveTokenWrapper system that deposits/withdraws into Aave lending pools 13 | /// @author Webb Technologies. 14 | /// @notice This contract is meant to be used over the `FungibleTokenWrapper` contract. 15 | contract AaveTokenWrapper is FungibleTokenWrapper, IAaveTokenWrapper { 16 | IAaveLendingPool public aaveLendingPool; 17 | 18 | /// @notice AaveTokenWrapper constructor 19 | /// @param _name The name of the ERC20 TokenWrapper 20 | /// @param _symbol The symbol of the ERC20 TokenWrapper 21 | constructor( 22 | string memory _name, 23 | string memory _symbol, 24 | address _aaveLendingPool 25 | ) FungibleTokenWrapper(_name, _symbol) {} 26 | 27 | /// @notice AaveTokenWrapper initializer 28 | /// @param _feePercentage The fee percentage for wrapping 29 | /// @param _feeRecipient The recipient for fees from wrapping. 30 | /// @param _handler The address of the handler 31 | /// @param _limit The maximum amount of tokens that can be wrapped 32 | /// @param _isNativeAllowed Whether or not native tokens are allowed to be wrapped 33 | /// @param _admin The address of the admin who will receive minting rights and admin role 34 | /// @param _aaveLendingPool The address of the Aave lending pool 35 | function initialize( 36 | uint16 _feePercentage, 37 | address _feeRecipient, 38 | address _handler, 39 | uint256 _limit, 40 | bool _isNativeAllowed, 41 | address _admin, 42 | address _aaveLendingPool 43 | ) public onlyUninitialized { 44 | super.initialize(_feePercentage, _feeRecipient, _handler, _limit, _isNativeAllowed, _admin); 45 | aaveLendingPool = IAaveLendingPool(_aaveLendingPool); 46 | } 47 | 48 | /// @inheritdoc IAaveTokenWrapper 49 | function deposit(address _tokenAddress, uint256 _amount) external override onlyInitialized { 50 | IERC20(_tokenAddress).approve(address(aaveLendingPool), _amount); 51 | aaveLendingPool.deposit(_tokenAddress, _amount, address(this), 0); 52 | } 53 | 54 | /// @inheritdoc IAaveTokenWrapper 55 | function withdraw(address _tokenAddress, uint256 _amount) external override onlyInitialized { 56 | uint256 tokenBalance = IERC20(_tokenAddress).balanceOf(address(this)); 57 | aaveLendingPool.withdraw(_tokenAddress, _amount, address(this)); 58 | uint256 redeemed = IERC20(_tokenAddress).balanceOf(address(this)) - tokenBalance; 59 | require(redeemed >= _amount, "Invalid withdraw"); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '35 15 * * 6' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v2 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v2 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v2 72 | -------------------------------------------------------------------------------- /scripts/bash/generate_phase1_ptau.sh: -------------------------------------------------------------------------------- 1 | # Make necessary directories if they don't exist 2 | compile_phase1 () { 3 | # ask for max circuit size 4 | # 5 | 6 | echo -n "Enter maximum constraints size (integer between 16 and 28 exclusive)" 7 | 8 | read max_constraints 9 | 10 | if [ $max_constraints -ge 16 ] || [ $max_constraints -le 28 ]; then 11 | 12 | mkdir -p solidity-fixtures/ptau 13 | 14 | # Start a new powers of tau ceremony 15 | if [ ! -f solidity-fixtures/ptau/pot"$max_constraints"_0000.ptau ]; then 16 | echo "snarkjs powersoftau new bn128 $max_constraints solidity-fixtures/ptau/pot$max_constraints""_0000.ptau -v\n" 17 | snarkjs powersoftau new bn128 $max_constraints solidity-fixtures/ptau/pot"$max_constraints"_0000.ptau -v & wait $! 18 | fi 19 | 20 | # make a contribution (enter some random text) 21 | if [ ! -f solidity-fixtures/ptau/pot"$max_constraints"_0001.ptau ]; then 22 | echo "echo 'test' | snarkjs powersoftau contribute solidity-fixtures/ptau/pot$max_constraints""_0000.ptau solidity-fixtures/ptau/pot$max_constraints""_0001.ptau --name="First contribution" -v\n" 23 | echo 'test' | snarkjs powersoftau contribute solidity-fixtures/ptau/pot"$max_constraints"_0000.ptau solidity-fixtures/ptau/pot"$max_constraints"_0001.ptau --name="First contribution" -v & wait $! 24 | fi 25 | 26 | # Verify phase 1 27 | echo "snarkjs powersoftau verify solidity-fixtures/ptau/pot$max_constraints""_0001.ptau\n" 28 | snarkjs powersoftau verify solidity-fixtures/ptau/pot"$max_constraints"_0001.ptau & wait $! 29 | 30 | # Apply random beacon 31 | if [ ! -f solidity-fixtures/ptau/pot"$max_constraints"_beacon.ptau ]; then 32 | echo "snarkjs powersoftau beacon solidity-fixtures/ptau/pot$max_constraints""_0001.ptau solidity-fixtures/ptau/pot$max_constraints""_beacon.ptau 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 10 -n="Final Beacon"\n" 33 | snarkjs powersoftau beacon solidity-fixtures/ptau/pot"$max_constraints"_0001.ptau solidity-fixtures/ptau/pot"$max_constraints"_beacon.ptau 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 10 -n="Final Beacon" & wait $! 34 | fi 35 | 36 | # Prapare phase 2 37 | if [ ! -f solidity-fixtures/ptau/pot"$max_constraints"_final.ptau ]; then 38 | echo "snarkjs powersoftau prepare phase2 solidity-fixtures/ptau/pot$max_constraints""_0001.ptau pot$max_constraints""_final.ptau -v\n" 39 | snarkjs powersoftau prepare phase2 solidity-fixtures/ptau/pot"$max_constraints"_0001.ptau solidity-fixtures/ptau/pot"$max_constraints"_final.ptau -v & wait $! 40 | fi 41 | fi 42 | } 43 | 44 | compile_phase1 45 | -------------------------------------------------------------------------------- /packages/contracts/contracts/vanchors/instances/VAnchorForest.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | import "../base/VAnchor.sol"; 9 | import "../../trees/MerkleForest.sol"; 10 | 11 | /// @title Variable Anchor Forest contract 12 | /// @author Webb Technologies 13 | /// @notice The Variable Anchor Forest is the same as a VAnchor system but with 14 | /// many merkle trees for commitment storage. 15 | contract VAnchorForest is VAnchor, MerkleForest { 16 | using SafeERC20 for IERC20; 17 | 18 | /// @notice The VAnchor Forest constructor 19 | /// @param _verifier The address of SNARK verifier for this contract 20 | /// @param _forestLevels The height/# of levels of underlying Merkle Forest 21 | /// @param _subtreeLevels The height/# of levels of underlying Merkle Trees in the forest 22 | /// @param _hasher The address of hash contract 23 | /// @param _handler The address of AnchorHandler for this contract 24 | /// @param _token The address of the token that is used to pay the deposit 25 | /// @param _maxEdges The maximum number of edges in the LinkableAnchor + Verifier supports. 26 | /// @notice The `_maxEdges` is zero-knowledge circuit dependent, meaning the 27 | /// `_verifier` ONLY supports a certain maximum # of edges. Therefore we need to 28 | /// limit the size of the LinkableAnchor with this parameter. 29 | constructor( 30 | IAnchorVerifier _verifier, 31 | uint32 _forestLevels, 32 | uint32 _subtreeLevels, 33 | IHasher _hasher, 34 | address _handler, 35 | address _token, 36 | uint8 _maxEdges 37 | ) 38 | VAnchor(_verifier, _forestLevels, _handler, _token, _maxEdges) 39 | MerkleForest(_forestLevels, _subtreeLevels, _hasher) 40 | {} 41 | 42 | /// @inheritdoc ZKVAnchorBase 43 | function _executeInsertions( 44 | PublicInputs memory _publicInputs, 45 | Encryptions memory _encryptions 46 | ) internal override { 47 | uint beforeInsertSubtreeIdx = currSubtreeIndex; 48 | insertTwo(_publicInputs.outputCommitments[0], _publicInputs.outputCommitments[1]); 49 | uint afterInsertSubtreeIdx = currSubtreeIndex; 50 | uint leafIndex = numSubtreeElements; 51 | if (beforeInsertSubtreeIdx != afterInsertSubtreeIdx) { 52 | afterInsertSubtreeIdx -= 1; 53 | if (leafIndex <= 1) { 54 | leafIndex = 2 ** subtreeLevels; 55 | } 56 | } 57 | emit NewCommitment( 58 | _publicInputs.outputCommitments[0], 59 | afterInsertSubtreeIdx, 60 | leafIndex - 2, 61 | _encryptions.encryptedOutput1 62 | ); 63 | emit NewCommitment( 64 | _publicInputs.outputCommitments[1], 65 | afterInsertSubtreeIdx, 66 | leafIndex - 1, 67 | _encryptions.encryptedOutput2 68 | ); 69 | for (uint256 i = 0; i < _publicInputs.inputNullifiers.length; i++) { 70 | emit NewNullifier(_publicInputs.inputNullifiers[i]); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/contracts/contracts/DeterministicDeployFactory.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021-2023 Webb Technologies 3 | * SPDX-License-Identifier: MIT OR Apache-2.0 4 | */ 5 | 6 | pragma solidity ^0.8.18; 7 | 8 | /// @title DeterministicDeployFactory contract. 9 | /// @notice This contract is used to deploy contracts deterministically w/ create2. 10 | /// @notice zkSync requires that any bytecode passed into deploy can be determined statically. 11 | /// This means that this contract cannot be deployed properly on zkSync (V-WBT-VUL-026: Create2 Compatibility Problems). 12 | contract DeterministicDeployFactory { 13 | event Deploy(address addr); 14 | 15 | function deploy(bytes memory bytecode, uint _salt) public returns (address) { 16 | address addr; 17 | assembly { 18 | addr := create2(0, add(bytecode, 0x20), mload(bytecode), _salt) 19 | if iszero(extcodesize(addr)) { 20 | revert(0, 0) 21 | } 22 | } 23 | 24 | emit Deploy(addr); 25 | return addr; 26 | } 27 | 28 | /// @notice Deploy a fungible token 29 | /// @param bytecode The bytecode of the contract 30 | /// @param _salt The salt for the contract 31 | /// @param _feePercentage The fee percentage for wrapping 32 | /// @param _feeRecipient The recipient for fees from wrapping. 33 | /// @param _handler The address of the handler 34 | /// @param _limit The maximum amount of tokens that can be wrapped 35 | /// @param _isNativeAllowed Whether or not native tokens are allowed to be wrapped 36 | function deployFungibleToken( 37 | bytes memory bytecode, 38 | uint _salt, 39 | uint16 _feePercentage, 40 | address _feeRecipient, 41 | address _handler, 42 | uint256 _limit, 43 | bool _isNativeAllowed 44 | ) external { 45 | address c = deploy(bytecode, _salt); 46 | // delegate call initialize the contract created with the msg.sender 47 | (bool success, bytes memory data) = c.call( 48 | abi.encodeWithSignature( 49 | "initialize(uint16,address,address,uint256,bool)", 50 | _feePercentage, 51 | _feeRecipient, 52 | _handler, 53 | _limit, 54 | _isNativeAllowed 55 | ) 56 | ); 57 | require(success, string(data)); 58 | } 59 | 60 | /// @notice Deploy a VAnchor 61 | /// @param bytecode The bytecode of the contract 62 | /// @param _salt The salt for the contract 63 | /// @param _minimumWithdrawalAmount The minimal withdrawal amount 64 | /// @param _maximumDepositAmount The maximum deposit amount 65 | function deployVAnchor( 66 | bytes memory bytecode, 67 | uint _salt, 68 | uint256 _minimumWithdrawalAmount, 69 | uint256 _maximumDepositAmount 70 | ) external { 71 | address c = deploy(bytecode, _salt); 72 | // delegate call initialize the contract created with the msg.sender 73 | (bool success, bytes memory data) = c.call( 74 | abi.encodeWithSignature( 75 | "initialize(uint256,uint256)", 76 | _minimumWithdrawalAmount, 77 | _maximumDepositAmount 78 | ) 79 | ); 80 | require(success, string(data)); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /packages/utils/src/protocol/typed-chain-id.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2022-2023 Webb Technologies Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Each ChainType has its own namespace of ChainIDs. 5 | export enum ChainType { 6 | None = 0x0000, 7 | EVM = 0x0100, 8 | Substrate = 0x0200, 9 | SubstrateDevelopment = 0x0250, 10 | PolkadotRelayChain = 0x0301, 11 | KusamaRelayChain = 0x0302, 12 | PolkadotParachain = 0x0310, 13 | KusamaParachain = 0x0311, 14 | Cosmos = 0x0400, 15 | Solana = 0x0500, 16 | } 17 | 18 | export function castToChainType(v: number): ChainType { 19 | switch (v) { 20 | case 0x0100: 21 | return ChainType.EVM; 22 | case 0x0200: 23 | return ChainType.Substrate; 24 | case 0x0301: 25 | return ChainType.PolkadotRelayChain; 26 | case 0x0302: 27 | return ChainType.KusamaRelayChain; 28 | case 0x0310: 29 | return ChainType.PolkadotParachain; 30 | case 0x0311: 31 | return ChainType.KusamaParachain; 32 | case 0x0400: 33 | return ChainType.Cosmos; 34 | case 0x0500: 35 | return ChainType.Solana; 36 | default: 37 | return ChainType.None; 38 | } 39 | } 40 | 41 | export type TypedChainId = { 42 | chainType: ChainType; 43 | chainId: number; 44 | }; 45 | 46 | /** 47 | * @param num - the number to be converted 48 | * @param min - the minimum bytes the array should hold (in the case of requiring empty bytes to match rust values) 49 | * @returns 50 | */ 51 | export const numToByteArray = (num: number, min: number): number[] => { 52 | let arr = []; 53 | 54 | while (num > 0) { 55 | arr.push(num % 256); 56 | num = Math.floor(num / 256); 57 | } 58 | 59 | arr.reverse(); 60 | 61 | // maintain minimum number of bytes 62 | while (arr.length < min) { 63 | arr = [0, ...arr]; 64 | } 65 | 66 | return arr; 67 | }; 68 | 69 | export const byteArrayToNum = (arr: number[]): number => { 70 | let n = 0; 71 | 72 | for (const i of arr) { 73 | n = n * 256 + i; 74 | } 75 | 76 | return n; 77 | }; 78 | 79 | export const calculateTypedChainId = (chainType: ChainType, chainId: number): number => { 80 | const chainTypeArray = numToByteArray(chainType, 2); 81 | const chainIdArray = numToByteArray(chainId, 4); 82 | const fullArray = [...chainTypeArray, ...chainIdArray]; 83 | 84 | return byteArrayToNum(fullArray); 85 | }; 86 | 87 | export const calculateTypedChainIdBytes = (typedChainId: number): string => { 88 | // Return big endian 8 bytes (64 bits) representation of typedChainId as a string 89 | const bytes = new Uint8Array(numToByteArray(typedChainId, 8)); 90 | return Buffer.from(bytes).toString('hex'); 91 | }; 92 | 93 | export const parseTypedChainId = (chainIdType: number): TypedChainId => { 94 | const byteArray = numToByteArray(chainIdType, 4); 95 | const chainType = byteArrayToNum(byteArray.slice(0, 2)); 96 | const chainId = byteArrayToNum(byteArray.slice(2)); 97 | 98 | return { chainId, chainType }; 99 | }; 100 | -------------------------------------------------------------------------------- /scripts/bash/groth16/phase2_circuit_groth16.sh: -------------------------------------------------------------------------------- 1 | PTAU_PATH=./powersOfTau28_hez_final_22.ptau 2 | compile_phase2 () { 3 | local outdir="$1" circuit="$2" pathToCircuitDir="$3" 4 | echo $outdir; 5 | mkdir -p $outdir; 6 | 7 | echo "Setting up Phase 2 ceremony for $circuit" 8 | echo "Outputting circuit_final.zkey and verifier.sol to $outdir" 9 | 10 | npx snarkjs groth16 setup "$pathToCircuitDir/$circuit.r1cs" $PTAU_PATH "$outdir/circuit_0000.zkey" 11 | echo "test" | npx snarkjs zkey contribute "$outdir/circuit_0000.zkey" "$outdir/circuit_0001.zkey" --name"1st Contributor name" -v 12 | npx snarkjs zkey verify "$pathToCircuitDir/$circuit.r1cs" $PTAU_PATH "$outdir/circuit_0001.zkey" 13 | npx snarkjs zkey beacon "$outdir/circuit_0001.zkey" "$outdir/circuit_final.zkey" 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 10 -n="Final Beacon phase2" 14 | npx snarkjs zkey verify "$pathToCircuitDir/$circuit.r1cs" $PTAU_PATH "$outdir/circuit_final.zkey" 15 | npx snarkjs zkey export verificationkey "$outdir/circuit_final.zkey" "$outdir/verification_key.json" 16 | 17 | npx snarkjs zkey export solidityverifier "$outdir/circuit_final.zkey" $outdir/verifier.sol 18 | echo "Done!\n" 19 | } 20 | 21 | move_verifiers_and_metadata () { 22 | local outdir="$1" size="$2" anchorType="$3" 23 | if [[ ! -f contracts/verifiers/$anchorType/ ]]; then 24 | mkdir -p contracts/verifiers/$anchorType 25 | fi 26 | cp $outdir/circuit_final.zkey solidity-fixtures/solidity-fixtures/$anchorType/$size/circuit_final.zkey 27 | cp $outdir/verifier.sol contracts/verifiers/$anchorType/"Verifier$size.sol" 28 | } 29 | 30 | move_verifiers_and_metadata_vanchor () { 31 | local indir="$1" size="$2" anchorType="$3" nIns="$4" 32 | cp $indir/circuit_final.zkey solidity-fixtures/solidity-fixtures/$anchorType/$size/circuit_final.zkey 33 | 34 | mkdir -p packages/contracts/contracts/verifiers/$anchorType 35 | cp $indir/verifier.sol packages/contracts/contracts/verifiers/$anchorType/Verifier"$size"_"$nIns".sol 36 | sed -i 's/contract Verifier/contract Verifier'$size'_'$nIns'/g' packages/contracts/contracts/verifiers/$anchorType/Verifier"$size"_"$nIns".sol 37 | sed -i 's/pragma solidity ^0.6.11;/pragma solidity ^0.8.18;/g' packages/contracts/contracts/verifiers/$anchorType/Verifier"$size"_"$nIns".sol 38 | } 39 | 40 | move_verifiers_and_metadata_vanchor_forest () { 41 | local indir="$1" size="$2" anchorType="$3" nIns="$4" 42 | cp $indir/circuit_final.zkey solidity-fixtures/solidity-fixtures/$anchorType/$size/circuit_final.zkey 43 | 44 | mkdir -p packages/contracts/contracts/verifiers/$anchorType 45 | cp $indir/verifier.sol packages/contracts/contracts/verifiers/$anchorType/VerifierF"$size"_"$nIns".sol 46 | sed -i 's/contract Verifier/contract VerifierF'$size'_'$nIns'/g' packages/contracts/contracts/verifiers/$anchorType/VerifierF"$size"_"$nIns".sol 47 | sed -i 's/pragma solidity ^0.6.11;/pragma solidity ^0.8.18;/g' packages/contracts/contracts/verifiers/$anchorType/VerifierF"$size"_"$nIns".sol 48 | } 49 | -------------------------------------------------------------------------------- /circuits/merkle-tree/treeUpdateArgsHasher.circom: -------------------------------------------------------------------------------- 1 | pragma circom 2.0.0; 2 | 3 | include "../../node_modules/circomlib/circuits/bitify.circom"; 4 | include "../../node_modules/circomlib/circuits/sha256/sha256.circom"; 5 | 6 | // Computes a SHA256 hash of all inputs packed into a byte array 7 | // Field elements are padded to 256 bits with zeroes 8 | template TreeUpdateArgsHasher(nLeaves) { 9 | signal input oldRoot; 10 | signal input newRoot; 11 | signal input pathIndices; 12 | /* signal input instances[nLeaves]; */ 13 | signal input leaves[nLeaves]; 14 | /* signal input blocks[nLeaves]; */ 15 | signal output out; 16 | 17 | var header = 256 + 256 + 32; 18 | var bitsPerLeaf = 256; // + 160 + 32; 19 | component hasher = Sha256(header + nLeaves * bitsPerLeaf); 20 | 21 | // the range check on old root is optional, it's enforced by smart contract anyway 22 | component bitsOldRoot = Num2Bits_strict(); 23 | component bitsNewRoot = Num2Bits_strict(); 24 | component bitsPathIndices = Num2Bits(32); 25 | component bitsInstance[nLeaves]; 26 | component bitsHash[nLeaves]; 27 | component bitsBlock[nLeaves]; 28 | 29 | bitsOldRoot.in <== oldRoot; 30 | bitsNewRoot.in <== newRoot; 31 | bitsPathIndices.in <== pathIndices; 32 | 33 | var index = 0; 34 | 35 | hasher.in[index] <== 0; 36 | index += 1; 37 | hasher.in[index] <== 0; 38 | index += 1; 39 | for(var i = 0; i < 254; i++) { 40 | hasher.in[index] <== bitsOldRoot.out[253 - i]; 41 | index += 1; 42 | } 43 | hasher.in[index] <== 0; 44 | index += 1; 45 | hasher.in[index] <== 0; 46 | index += 1; 47 | for(var i = 0; i < 254; i++) { 48 | hasher.in[index] <== bitsNewRoot.out[253 - i]; 49 | index += 1; 50 | } 51 | for(var i = 0; i < 32; i++) { 52 | hasher.in[index] <== bitsPathIndices.out[31 - i]; 53 | index += 1; 54 | } 55 | for(var leaf = 0; leaf < nLeaves; leaf++) { 56 | // the range check on hash is optional, it's enforced by the smart contract anyway 57 | bitsHash[leaf] = Num2Bits_strict(); 58 | /* bitsInstance[leaf] = Num2Bits(160); */ 59 | /* bitsBlock[leaf] = Num2Bits(32); */ 60 | bitsHash[leaf].in <== leaves[leaf]; 61 | /* bitsInstance[leaf].in <== instances[leaf]; */ 62 | /* bitsBlock[leaf].in <== blocks[leaf]; */ 63 | hasher.in[index] <== 0; 64 | index += 1; 65 | hasher.in[index] <== 0; 66 | index += 1; 67 | for(var i = 0; i < 254; i++) { 68 | hasher.in[index] <== bitsHash[leaf].out[253 - i]; 69 | index += 1; 70 | } 71 | /* for(var i = 0; i < 160; i++) { */ 72 | /* hasher.in[index++] <== bitsInstance[leaf].out[159 - i]; */ 73 | /* } */ 74 | /* for(var i = 0; i < 32; i++) { */ 75 | /* hasher.in[index++] <== bitsBlock[leaf].out[31 - i]; */ 76 | /* } */ 77 | } 78 | component b2n = Bits2Num(256); 79 | for (var i = 0; i < 256; i++) { 80 | b2n.in[i] <== hasher.out[255 - i]; 81 | } 82 | out <== b2n.out; 83 | } 84 | -------------------------------------------------------------------------------- /packages/utils/src/proof/variable-anchor.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable camelcase */ 2 | /* eslint-disable sort-keys */ 3 | import { BigNumber, BigNumberish, ethers } from 'ethers'; 4 | 5 | import { u8aToHex } from '@polkadot/util'; 6 | 7 | import { toFixedHex } from '../utils'; 8 | import { FIELD_SIZE } from '../protocol'; 9 | import { Utxo } from '../protocol/utxo'; 10 | import { MerkleProof, MerkleTree } from '../protocol/merkle-tree'; 11 | 12 | export function getVAnchorExtDataHash( 13 | encryptedOutput1: string, 14 | encryptedOutput2: string, 15 | extAmount: string, 16 | fee: string, 17 | recipient: string, 18 | relayer: string, 19 | refund: string, 20 | token: string 21 | ): BigNumberish { 22 | const abi = new ethers.utils.AbiCoder(); 23 | const encodedData = abi.encode( 24 | [ 25 | 'tuple(address recipient,int256 extAmount,address relayer,uint256 fee,uint256 refund,address token,bytes encryptedOutput1,bytes encryptedOutput2)', 26 | ], 27 | [ 28 | { 29 | recipient: toFixedHex(recipient, 20), 30 | extAmount: toFixedHex(extAmount), 31 | relayer: toFixedHex(relayer, 20), 32 | fee: toFixedHex(fee), 33 | refund: toFixedHex(refund), 34 | token: toFixedHex(token, 20), 35 | encryptedOutput1, 36 | encryptedOutput2, 37 | }, 38 | ] 39 | ); 40 | 41 | const hash = ethers.utils.keccak256(encodedData); 42 | 43 | return BigNumber.from(hash).mod(FIELD_SIZE); 44 | } 45 | 46 | export function generateVariableWitnessInput( 47 | roots: BigNumberish[], 48 | chainId: BigNumberish, 49 | inputs: Utxo[], 50 | outputs: Utxo[], 51 | extAmount: BigNumberish, 52 | fee: BigNumberish, 53 | extDataHash: BigNumberish, 54 | externalMerkleProofs: MerkleProof[] 55 | ): any { 56 | const vanchorMerkleProofs = externalMerkleProofs.map((proof) => ({ 57 | pathIndex: MerkleTree.calculateIndexFromPathIndices(proof.pathIndices), 58 | pathElements: proof.pathElements, 59 | })); 60 | 61 | const input = { 62 | roots: roots.map((x) => x.toString()), 63 | chainID: chainId.toString(), 64 | inputNullifier: inputs.map((x) => '0x' + x.nullifier), 65 | outputCommitment: outputs.map((x) => BigNumber.from(u8aToHex(x.commitment)).toString()), 66 | publicAmount: BigNumber.from(extAmount).sub(fee).add(FIELD_SIZE).mod(FIELD_SIZE).toString(), 67 | extDataHash: extDataHash.toString(), 68 | 69 | // data for 2 transaction inputs 70 | inAmount: inputs.map((x) => x.amount.toString()), 71 | inPrivateKey: inputs.map((x) => '0x' + x.secret_key), 72 | inBlinding: inputs.map((x) => BigNumber.from('0x' + x.blinding).toString()), 73 | inPathIndices: vanchorMerkleProofs.map((x) => x.pathIndex), 74 | inPathElements: vanchorMerkleProofs.map((x) => x.pathElements), 75 | 76 | // data for 2 transaction outputs 77 | outChainID: outputs.map((x) => x.chainId), 78 | outAmount: outputs.map((x) => x.amount.toString()), 79 | outPubkey: outputs.map((x) => BigNumber.from(x.getKeypair().getPubKey()).toString()), 80 | outBlinding: outputs.map((x) => BigNumber.from('0x' + x.blinding).toString()), 81 | }; 82 | 83 | return input; 84 | } 85 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "protocol-solidity", 3 | "repository": "git://github.com/webb-tools/protocol-solidity.git", 4 | "author": "Webb Developers ", 5 | "license": "(MIT OR Apache-2.0)", 6 | "private": true, 7 | "workspaces": { 8 | "packages": [ 9 | "packages/*" 10 | ], 11 | "nohoist": [ 12 | "**/@openzeppelin/**" 13 | ] 14 | }, 15 | "engines": { 16 | "node": "18.x.x" 17 | }, 18 | "scripts": { 19 | "compile": "lerna run compile --scope=@webb-tools/contracts", 20 | "build": "yarn compile && yarn build:packages", 21 | "setup": "yarn compile && yarn build:circuits && yarn build:ptau", 22 | "test": "lerna run test", 23 | "fast": "yarn workspace @webb-tools/contracts run test:parallel", 24 | "build:circuits": "./scripts/bash/build_circuits.sh", 25 | "build:packages": "lerna run build", 26 | "build:ptau": "./scripts/bash/generate_phase1_ptau.sh", 27 | "clean": "rm -rf artifacts typechain-types && yarn clean:packages", 28 | "clean:packages": "lerna run clean", 29 | "fetch:fixtures": "cd solidity-fixtures && dvc pull && cd ../", 30 | "prettier": "prettier -c .", 31 | "publish:packages": "lerna run compile && lerna publish", 32 | "publish:ci": "lerna run compile && lerna publish patch --yes --message 'chore: release new versions' ", 33 | "setup:groth16:vanchor2": "./scripts/bash/groth16/vanchor/phase2_poseidon_vanchor2.sh", 34 | "setup:groth16:vanchor8": "./scripts/bash/groth16/vanchor/phase2_poseidon_vanchor8.sh", 35 | "setup:plonk:vanchor2": "./scripts/bash/plonk/vanchor/phase2_poseidon_vanchor2.sh", 36 | "setup:plonk:vanchor8": "./scripts/bash/plonk/vanchor/phase2_poseidon_vanchor8.sh", 37 | "ts-check": "tsc --noEmit -p ./tsconfig.json", 38 | "format": "prettier -w ." 39 | }, 40 | "devDependencies": { 41 | "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", 42 | "@nomicfoundation/hardhat-network-helpers": "^1.0.8", 43 | "@nomiclabs/hardhat-ethers": "^2.2.3", 44 | "@nomiclabs/hardhat-truffle5": "^2.0.7", 45 | "@nomiclabs/hardhat-web3": "^2.0.0", 46 | "@openzeppelin/contracts": "^4.8.3", 47 | "@typechain/ethers-v5": "^10.2.0", 48 | "@typechain/hardhat": "^6.1.5", 49 | "@types/chai": "^4.3.4", 50 | "@types/mocha": "^10.0.1", 51 | "@webb-tools/test-utils": "0.1.4-126", 52 | "chai": "^4.3.7", 53 | "circomlibjs": "^0.0.8", 54 | "copyfiles": "^2.4.1", 55 | "dotenv": "^16.0.3", 56 | "elliptic": "^6.5.4", 57 | "ethers": "^5.7.0", 58 | "hardhat": "^2.14.0", 59 | "hardhat-artifactor": "^0.2.0", 60 | "hardhat-gas-reporter": "^1.0.9", 61 | "hardhat-preprocessor": "^0.1.5", 62 | "itertools": "^2.1.1", 63 | "lerna": "^6.6.1", 64 | "mocha": "^10.2.0", 65 | "nx": "^15.9.2", 66 | "prettier-plugin-solidity": "^1.1.3", 67 | "rimraf": "^5.0.0", 68 | "snarkjs": "^0.7.2", 69 | "solidity-coverage": "^0.8.2", 70 | "tomlify-j0.4": "^3.0.0", 71 | "truffle-assertions": "^0.9.2", 72 | "ts-node": "^10.9.1", 73 | "typechain": "^8.1.1" 74 | }, 75 | "dependencies": { 76 | "circomlib": "^2.0.5", 77 | "typescript": "^5.0.4" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /packages/anchors/src/extensions/ChainalysisVAnchor.ts: -------------------------------------------------------------------------------- 1 | import { ZkComponents } from '@webb-tools/utils'; 2 | import { BigNumberish, ethers, BigNumber } from 'ethers'; 3 | import { VAnchorEncodeInputs__factory, ChainalysisVAnchor__factory } from '@webb-tools/contracts'; 4 | import VAnchor from '../VAnchor'; 5 | import { Deployer } from '@webb-tools/create2-utils'; 6 | 7 | export class ChainalysisVAnchor extends VAnchor { 8 | public static async create2VAnchor( 9 | deployer: Deployer, 10 | saltHex: string, 11 | verifier: string, 12 | levels: BigNumberish, 13 | hasher: string, 14 | handler: string, 15 | token: string, 16 | maxEdges: number, 17 | smallCircuitZkComponents: ZkComponents, 18 | largeCircuitZkComponents: ZkComponents, 19 | signer: ethers.Signer 20 | ) { 21 | const { contract: libraryContract } = await deployer.deploy( 22 | VAnchorEncodeInputs__factory, 23 | saltHex, 24 | signer 25 | ); 26 | 27 | let libraryAddresses = { 28 | ['contracts/libs/VAnchorEncodeInputs.sol:VAnchorEncodeInputs']: libraryContract.address, 29 | }; 30 | 31 | const argTypes = ['address', 'uint32', 'address', 'address', 'address', 'uint8']; 32 | const args = [verifier, levels, hasher, handler, token, maxEdges]; 33 | const { contract: vanchor, receipt } = await deployer.deploy( 34 | ChainalysisVAnchor__factory, 35 | saltHex, 36 | signer, 37 | libraryAddresses, 38 | argTypes, 39 | args 40 | ); 41 | const createdVAnchor = new VAnchor( 42 | vanchor, 43 | signer, 44 | Number(levels), 45 | maxEdges, 46 | smallCircuitZkComponents, 47 | largeCircuitZkComponents 48 | ); 49 | createdVAnchor.latestSyncedBlock = receipt.blockNumber!; 50 | createdVAnchor.token = token; 51 | return createdVAnchor; 52 | } 53 | 54 | public static async createVAnchor( 55 | verifier: string, 56 | levels: BigNumberish, 57 | hasher: string, 58 | handler: string, 59 | token: string, 60 | maxEdges: number, 61 | smallCircuitZkComponents: ZkComponents, 62 | largeCircuitZkComponents: ZkComponents, 63 | signer: ethers.Signer 64 | ) { 65 | const encodeLibraryFactory = new VAnchorEncodeInputs__factory(signer); 66 | const encodeLibrary = await encodeLibraryFactory.deploy(); 67 | await encodeLibrary.deployed(); 68 | const factory = new ChainalysisVAnchor__factory( 69 | { ['contracts/libs/VAnchorEncodeInputs.sol:VAnchorEncodeInputs']: encodeLibrary.address }, 70 | signer 71 | ); 72 | const vAnchor = await factory.deploy(verifier, levels, hasher, handler, token, maxEdges, {}); 73 | await vAnchor.deployed(); 74 | const createdVAnchor = new ChainalysisVAnchor( 75 | vAnchor, 76 | signer, 77 | Number(levels), 78 | maxEdges, 79 | smallCircuitZkComponents, 80 | largeCircuitZkComponents 81 | ); 82 | createdVAnchor.latestSyncedBlock = vAnchor.deployTransaction.blockNumber!; 83 | createdVAnchor.token = token; 84 | const tx = await createdVAnchor.contract.initialize( 85 | BigNumber.from('1'), 86 | BigNumber.from(2).pow(256).sub(1) 87 | ); 88 | await tx.wait(); 89 | return createdVAnchor; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /packages/create2-utils/src/Deployer.ts: -------------------------------------------------------------------------------- 1 | import { Signer, ethers } from 'ethers'; 2 | import { DeterministicDeployFactory as DeterministicDeployFactoryContract } from '@webb-tools/contracts'; 3 | import { ParamType } from 'ethers/lib/utils'; 4 | 5 | export class Deployer { 6 | signer: ethers.Signer; 7 | contract: DeterministicDeployFactoryContract; 8 | 9 | constructor(contract: DeterministicDeployFactoryContract) { 10 | this.contract = contract; 11 | } 12 | 13 | get address(): string { 14 | return this.contract.address; 15 | } 16 | 17 | public static encode(types: ReadonlyArray, values: ReadonlyArray) { 18 | const abiCoder = ethers.utils.defaultAbiCoder; 19 | const encodedParams = abiCoder.encode(types, values); 20 | return encodedParams.slice(2); 21 | } 22 | 23 | public static create2Address( 24 | factoryAddress: string, 25 | saltHex: string, 26 | initCode: ethers.utils.BytesLike 27 | ) { 28 | const create2Addr = ethers.utils.getCreate2Address( 29 | factoryAddress, 30 | saltHex, 31 | ethers.utils.keccak256(initCode) 32 | ); 33 | return create2Addr; 34 | } 35 | 36 | public async deploy( 37 | factory: any, 38 | saltHex: string, 39 | signer: Signer, 40 | libraryAddresses?: any, 41 | argTypes?: string[], 42 | args?: any[] 43 | ) { 44 | let verifierFactory; 45 | if (libraryAddresses === undefined) { 46 | verifierFactory = new factory(signer); 47 | } else { 48 | verifierFactory = new factory(libraryAddresses, signer); 49 | } 50 | const verifierBytecode = verifierFactory['bytecode']; 51 | let initCode: string; 52 | if (argTypes && args) { 53 | const encodedParams = Deployer.encode(argTypes, args); 54 | initCode = verifierBytecode + encodedParams; 55 | } else { 56 | initCode = verifierBytecode + Deployer.encode([], []); 57 | } 58 | const verifierCreate2Addr = Deployer.create2Address(this.contract.address, saltHex, initCode); 59 | const tx = await this.contract.deploy(initCode, saltHex); 60 | const receipt = await tx.wait(); 61 | if (!receipt.events) { 62 | throw new Error('no events in receipt'); 63 | } 64 | 65 | const deployEventIdx = receipt.events.length - 1; 66 | const deployEvent = receipt.events[deployEventIdx]; 67 | if (deployEvent.args?.[0] !== verifierCreate2Addr) { 68 | throw new Error('create2 address mismatch'); 69 | } 70 | 71 | const contract = await verifierFactory.attach(deployEvent.args[0]); 72 | return { contract, receipt }; 73 | } 74 | 75 | public async deployInitCode(saltHex: string, signer: Signer, initCode: any) { 76 | const verifierCreate2Addr = Deployer.create2Address(this.contract.address, saltHex, initCode); 77 | const tx = await this.contract.deploy(initCode, saltHex); 78 | const receipt = await tx.wait(); 79 | 80 | if (!receipt.events) { 81 | throw new Error('no events in receipt'); 82 | } 83 | 84 | const deployEventIdx = receipt.events.length - 1; 85 | const deployEvent = receipt.events[deployEventIdx]; 86 | if (deployEvent.args?.[0] !== verifierCreate2Addr) { 87 | throw new Error('create2 address mismatch'); 88 | } 89 | let address = deployEvent.args[0]; 90 | return { address }; 91 | } 92 | } 93 | export default Deployer; 94 | -------------------------------------------------------------------------------- /scripts/bash/build_circuits_plonk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | compile () { 4 | local outdir="$1" circuit="$2" size="$3" 5 | mkdir -p build/$outdir 6 | mkdir -p build/$outdir/$size 7 | echo "circuits/main/$circuit.circom" 8 | ~/.cargo/bin/circom --r1cs --wasm --sym \ 9 | -o artifacts/circuits/$outdir \ 10 | circuits/main/$circuit.circom 11 | echo -e "Done!\n" 12 | } 13 | 14 | copy_to_fixtures () { 15 | local outdir="$1" circuit="$2" size="$3" anchorType="$4" 16 | mkdir -p solidity-fixtures/solidity-fixtures/$anchorType 17 | mkdir -p solidity-fixtures/solidity-fixtures/$anchorType/$size 18 | cp artifacts/circuits/$outdir/$circuit.sym solidity-fixtures/solidity-fixtures/$anchorType/$size/$circuit.sym 19 | cp artifacts/circuits/$outdir/$circuit.r1cs solidity-fixtures/solidity-fixtures/$anchorType/$size/$circuit.r1cs 20 | cp artifacts/circuits/$outdir/$circuit\_js/$circuit.wasm solidity-fixtures/solidity-fixtures/$anchorType/$size/$circuit.wasm 21 | cp artifacts/circuits/$outdir/$circuit\_js/witness_calculator.js solidity-fixtures/solidity-fixtures/$anchorType/$size/witness_calculator.cjs 22 | } 23 | 24 | # ### 25 | # # TORNADO TORNADOS 26 | # ### 27 | 28 | # echo "Compiling Tornado style Poseidon anchor withdrawal circuit..." 29 | # compile anchor anchor_withdraw_30 30 | 31 | ### 32 | # WEBB ANCHORS 33 | ### 34 | 35 | echo "Compiling Webb style Poseidon anchor 2 withdrawal circuit..." 36 | compile anchor poseidon_anchor_2 2 37 | copy_to_fixtures anchor poseidon_anchor_2 2 anchor 38 | 39 | echo "Compiling Webb style Poseidon anchor 3 withdrawal circuit..." 40 | compile anchor poseidon_anchor_3 3 41 | copy_to_fixtures anchor poseidon_anchor_3 3 anchor 42 | 43 | echo "Compiling Webb style Poseidon anchor 4 withdrawal circuit..." 44 | compile anchor poseidon_anchor_4 4 45 | copy_to_fixtures anchor poseidon_anchor_4 4 anchor 46 | 47 | echo "Compiling Webb style Poseidon anchor 5 withdrawal circuit..." 48 | compile anchor poseidon_anchor_5 5 49 | copy_to_fixtures anchor poseidon_anchor_5 5 anchor 50 | 51 | echo "Compiling Webb style Poseidon anchor 6 withdrawal circuit..." 52 | compile anchor poseidon_anchor_6 6 53 | copy_to_fixtures anchor poseidon_anchor_6 6 anchor 54 | 55 | echo "Compiling Webb style Poseidon anchor 32 withdrawal circuit..." 56 | compile anchor poseidon_anchor_32 32 57 | copy_to_fixtures anchor poseidon_anchor_32 32 anchor 58 | 59 | ### 60 | # WEBB VANCHORS 61 | ### 62 | 63 | echo "Compiling Webb style variable Poseidon vanchor 2 circuit w/ 2 inputs" 64 | compile vanchor_2 poseidon_vanchor_2_2 2 65 | copy_to_fixtures vanchor_2 poseidon_vanchor_2_2 2 vanchor_2 66 | 67 | echo "Compiling Webb style variable Poseidon vanchor 2 circuit w/ 16 inputs" 68 | compile vanchor_16 poseidon_vanchor_16_2 2 69 | copy_to_fixtures vanchor_16 poseidon_vanchor_16_2 2 vanchor_16 70 | 71 | echo "Compiling Webb style variable Poseidon vanchor 8 circuit w/ 2 inputs" 72 | compile vanchor_2 poseidon_vanchor_2_8 8 73 | copy_to_fixtures vanchor_2 poseidon_vanchor_2_8 8 vanchor_2 74 | 75 | echo "Compiling Webb style variable Poseidon vanchor 8 circuit w/ 16 inputs" 76 | compile vanchor_16 poseidon_vanchor_16_8 8 77 | copy_to_fixtures vanchor_16 poseidon_vanchor_16_8 8 vanchor_16 78 | 79 | # Keypair Circuits 80 | 81 | # echo "Compiling Keypair Circuit" 82 | # compile keypair keypair_test 0 83 | # copy_to_fixtures keypair keypair_test 0 none 84 | --------------------------------------------------------------------------------