{"id":31528448,"url":"https://github.com/0xsequence/catapult","last_synced_at":"2025-10-31T18:02:43.188Z","repository":{"id":311834501,"uuid":"1028460879","full_name":"0xsequence/catapult","owner":"0xsequence","description":"Ethereum contract deployment and management framework","archived":false,"fork":false,"pushed_at":"2025-09-30T19:03:18.000Z","size":509,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-03T23:44:21.540Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0xsequence.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-29T15:03:54.000Z","updated_at":"2025-09-30T19:03:17.000Z","dependencies_parsed_at":"2025-08-27T07:08:09.750Z","dependency_job_id":"aa518705-3770-4dd2-9241-61b475d1a492","html_url":"https://github.com/0xsequence/catapult","commit_stats":null,"previous_names":["0xsequence/catapult"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/0xsequence/catapult","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xsequence%2Fcatapult","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xsequence%2Fcatapult/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xsequence%2Fcatapult/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xsequence%2Fcatapult/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0xsequence","download_url":"https://codeload.github.com/0xsequence/catapult/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xsequence%2Fcatapult/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":282033061,"owners_count":26602642,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-31T02:00:07.401Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-03T23:41:10.006Z","updated_at":"2025-10-31T18:02:43.173Z","avatar_url":"https://github.com/0xsequence.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Catapult\n\n[![CI](https://github.com/0xsequence/catapult/actions/workflows/ci.yml/badge.svg)](https://github.com/0xsequence/catapult/actions/workflows/ci.yml)\n\n**Catapult** is a powerful Ethereum contract deployment and management framework designed to simplify the orchestration of complex contract deployments across multiple blockchain networks. Built with TypeScript and Node.js, it provides a declarative YAML-based approach to defining deployment jobs, templates, and dependencies.\n\n## Overview\n\nCatapult addresses the challenge of managing complex contract deployment scenarios where multiple contracts need to be deployed in a specific order, with dependencies between them, across multiple blockchain networks. Instead of writing custom deployment scripts for each scenario, you define your deployment logic declaratively using YAML files.\n\n### Key Features\n\n- **🔄 Declarative Deployment Jobs**: Define complex deployment workflows using YAML configuration files\n- **📋 Template System**: Create reusable deployment templates that can be shared across projects\n- **🔗 Dependency Management**: Automatic resolution of deployment dependencies and execution ordering\n- **🌐 Multi-Network Support**: Deploy to multiple blockchain networks simultaneously\n- **⚡ Built-in Actions**: Comprehensive set of built-in actions for common deployment tasks\n- **🧮 Value Resolvers**: Powerful system for computing values, encoding data, and performing calculations\n- **✅ Skip Conditions**: Smart conditional logic to avoid redundant deployments\n- **🔍 Validation \u0026 Dry Run**: Validate configurations and preview deployment plans without execution\n- **📊 Event System**: Rich event system for monitoring deployment progress and debugging\n- **🧾 Multi-platform Verification**: Verify on Etherscan v2 and Sourcify (tries all configured platforms by default)\n\n## Installation\n\n### From npm (recommended)\n\nAvailable on npm as `@0xsequence/catapult`.\n\nGlobal install (provides the `catapult` CLI on your PATH):\n\n```bash\nnpm install -g @0xsequence/catapult\n# or\nyarn global add @0xsequence/catapult\n# or\npnpm add -g @0xsequence/catapult\n```\n\nProject-local install (use via npx or package.json scripts):\n\n```bash\nnpm install -D @0xsequence/catapult\n# or\nyarn add -D @0xsequence/catapult\n# or\npnpm add -D @0xsequence/catapult\n\n# then run\nnpx catapult --help\n```\n\n### From Source\n\n```bash\ngit clone \u003crepository-url\u003e\ncd catapult\nnpm install\nnpm run build\nnpm link\n```\n\n### Global Installation (from npm)\n\n```bash\nnpm install -g @0xsequence/catapult\n```\n\n## Project Structure\n\nA Catapult project follows this structure:\n\n```\nmy-deployment-project/\n├── networks.yaml              # Network configurations\n├── jobs/                      # Deployment job definitions\n│   ├── core-contracts.yaml\n│   ├── factory-setup.yaml\n│   └── token-deployment.yaml\n├── templates/                 # Custom template definitions\n│   ├── erc20-factory.yaml\n│   └── proxy-deployment.yaml\n├── artifacts/                 # Contract build artifacts\n│   ├── MyContract.json\n│   └── Factory.json\n└── output/                    # Generated deployment results\n```\n\n## Configuration\n\n### Networks Configuration\n\nCreate a `networks.yaml` file in your project root to define target networks:\n\n```yaml\n- name: \"Ethereum Mainnet\"\n  chainId: 1\n  rpcUrl: \"https://mainnet.infura.io/v3/YOUR_PROJECT_ID\"\n\n- name: \"Arbitrum One\"\n  chainId: 42161\n  rpcUrl: \"https://arb1.arbitrum.io/rpc\"\n\n- name: \"Polygon\"\n  chainId: 137\n  rpcUrl: \"https://polygon-rpc.com\"\n  supports: [\"etherscan_v2\"]  # Optional: verification platforms supported\n  gasLimit: 500000            # Optional: gas limit for all transactions on this network\n  testnet: true               # Optional: mark as test network\n  evmVersion: \"cancun\"        # Optional: network EVM hardfork (e.g., london, paris, shanghai, cancun)\n```\n\nThe `supports` field is optional and specifies which verification platforms are available for the network. Currently supported platforms:\n\n- `etherscan_v2`: Etherscan v2 verification API (supports Ethereum, Polygon, Arbitrum, BSC, etc.)\n- `sourcify`: Sourcify verification (no API key required)\n\nIf `supports` is omitted, all built-in platforms are allowed for that network. Etherscan requires an API key to be considered “configured”; Sourcify requires no configuration. The `gasLimit` field is optional and specifies a fixed gas limit to use for all transactions on this network. If not specified, the system will use ethers.js default gas estimation.\n\n### Constants\n\nYou can define reusable values in constants files or directly within a job.\n\n- Top-level constants are discovered anywhere under your project root by adding YAML files with `type: \"constants\"`.\n- Keys must be unique across all constants files; duplicates will fail the load.\n- Within jobs/templates, reference constants using bare placeholders like `{{MY_CONSTANT}}`.\n- Job-level constants override top-level constants when names collide.\n\nExample top-level constants file (can be placed anywhere, e.g., `constants.yaml`):\n\n```yaml\ntype: \"constants\"\n\nconstants:\n  address-zero: \"0x0000000000000000000000000000000000000000\"\n  salt-zero: \"0x0000000000000000000000000000000000000000000000000000000000000000\"\n  developer-multisig-01: \"0x007a47e6BF40C1e0ed5c01aE42fDC75879140bc4\"\n  entrypoint-4337-07: \"0x0000000071727de22e5e9d8baf0edac6f37da032\"\n```\n\nJob-level constants example (defined at the top of a job):\n\n```yaml\nname: \"job-with-constants\"\nversion: \"1\"\nconstants:\n  FEE: \"1000\"\n  ADMIN: \"0x0000000000000000000000000000000000000001\"\nactions:\n  - name: \"example\"\n    template: \"some-template\"\n    arguments:\n      admin: \"{{ADMIN}}\"      # resolves to job-level constant\n      defaultSalt: \"{{salt-zero}}\"  # resolves to top-level constant\n```\n\nTip: Use `catapult list constants` to see discovered top-level constants and any job-level constants.\n\n#### RPC URL tokens via environment variables\n\nYou can inject secrets (like access tokens) into `rpcUrl` using placeholders of the form `{{RPC_...}}`. At load time, any placeholder whose name starts with `RPC` will be replaced with the value of the corresponding environment variable. Placeholders not starting with `RPC` are left as-is.\n\nExample `networks.yaml`:\n\n```yaml\n- name: \"MyNet\"\n  chainId: 999\n  rpcUrl: \"https://node.url/something/{{RPC_URL_TOKEN}}\"\n```\n\nWith an environment variable:\n\n```bash\nexport RPC_URL_TOKEN=\"my-secret-token\"\n```\n\nResulting `rpcUrl` at runtime:\n\n```\nhttps://node.url/something/my-secret-token\n```\n\nNotes:\n- If an `{{RPC_*}}` placeholder is present and the corresponding environment variable is not set, it now defaults to an empty string. This allows templates like `https://node.url/{{RPC_TOKEN}}` to collapse gracefully to `https://node.url/` without failing the load.\n- Multiple RPC tokens in one URL are supported, and whitespace inside the token delimiters is ignored (e.g., `{{  RPC_TOKEN  }}`).\n\n### Job Definitions\n\nJobs are the core deployment units. Create YAML files in the `jobs/` directory:\n\n```yaml\n# jobs/core-contracts.yaml\nname: \"core-contracts\"\nversion: \"1.0.0\"\ndescription: \"Deploy core system contracts\"\n\nactions:\n  - name: \"deploy-factory\"\n    template: \"sequence-universal-deployer-2\"\n    arguments:\n      creationCode: \"{{Contract(MyFactory).creationCode}}\"\n      salt: \"0\"\n\n  - name: \"deploy-implementation\"\n    template: \"sequence-universal-deployer-2\"\n    depends_on: [\"deploy-factory\"]\n    arguments:\n      creationCode:\n        type: \"constructor-encode\"\n        arguments:\n          creationCode: \"{{Contract(MyImplementation).creationCode}}\"\n          types: [\"address\"]\n          values: [\"{{deploy-factory.address}}\"]\n      salt: \"0\"\n```\n\n#### Per-job network filters\n\nJobs run on all selected networks by default. You can restrict or exclude networks for a specific job by chain ID:\n\n```yaml\nname: \"token-deployment\"\nversion: \"1.0.0\"\n\n# Run only on these networks (takes precedence if present)\nonly_networks: [1, 42161]\n\n# Or, skip these networks (used only if only_networks is not set)\n# skip_networks: [137]\n\nactions:\n  - name: \"deploy\"\n    template: \"erc-2470\"\n    arguments: { /* ... */ }\n```\n\nRules:\n- If `only_networks` is set and non-empty, the job runs only on those chain IDs.\n- Else, if `skip_networks` is set and non-empty, the job is skipped on those chain IDs.\n- Otherwise, the job runs on all networks selected for the run (via `networks.yaml` or `--network`).\n\n#### Minimum EVM version per job\n\nJobs can declare a minimum EVM hardfork they require. When a network’s `evmVersion` is older than the job’s `min_evm_version`, the job is skipped on that network.\n\n```yaml\nname: \"post-shanghai-feature\"\nversion: \"1.0.0\"\nmin_evm_version: \"shanghai\"\n\nactions:\n  - name: \"deploy\"\n    template: \"erc-2470\"\n    arguments: { /* ... */ }\n```\n\nSupported identifiers include: `frontier`, `homestead`, `tangerine`, `spuriousdragon`, `byzantium`, `constantinople`, `petersburg`, `istanbul`, `berlin`, `london`, `paris` (The Merge), `shanghai`, `cancun`, `prague`.\n\n#### Deprecating jobs\n\nMark a job as deprecated to opt it out of normal runs without deleting it:\n\n```yaml\nname: \"legacy-seed\"\nversion: \"1.2.3\"\ndeprecated: true\nactions:\n  - name: \"noop\"\n    type: \"static\"\n    arguments: { value: null }\n```\n\nBehavior:\n- Deprecated jobs are skipped by default when running without specifying job names.\n- Explicitly targeting a deprecated job on the CLI will run it even without extra flags: `catapult run legacy-seed -k $PRIVATE_KEY`.\n- To include all deprecated jobs in a normal run, pass `--run-deprecated`: `catapult run --run-deprecated -k $PRIVATE_KEY`.\n- If a non-deprecated job depends on a deprecated job, that deprecated dependency is ALWAYS included automatically to satisfy dependencies (even without `--run-deprecated`).\n\n### Template Definitions\n\nTemplates are reusable deployment patterns. Create them in the `templates/` directory:\n\n```yaml\n# templates/proxy-factory.yaml\nname: \"proxy-factory\"\ntype: \"template\"\n\narguments:\n  implementation:\n    type: \"address\"\n  salt:\n    type: \"bytes32\"\n\nreturns:\n  address:\n    type: \"address\"\n\nsetup:\n  - type: \"job-completed\"\n    arguments:\n      job: \"core-contracts\"\n\nactions:\n  - type: \"send-transaction\"\n    arguments:\n      to: \"{{core-contracts.deploy-factory.address}}\"\n      data:\n        type: \"abi-encode\"\n        arguments:\n          signature: \"createProxy(address,bytes32)\"\n          values:\n            - \"{{implementation}}\"\n            - \"{{salt}}\"\n\nskip_condition:\n  - type: \"contract-exists\"\n    arguments:\n      address:\n        type: \"compute-create2\"\n        arguments:\n          deployerAddress: \"{{core-contracts.deploy-factory.address}}\"\n          salt: \"{{salt}}\"\n          initCode:\n            type: \"constructor-encode\"\n            arguments:\n              creationCode: \"{{Contract(ProxyBytecode).creationCode}}\"\n              types: [\"address\"]\n              values: [\"{{implementation}}\"]\n\noutputs:\n  address:\n    type: \"compute-create2\"\n    arguments:\n      deployerAddress: \"{{core-contracts.deploy-factory.address}}\"\n      salt: \"{{salt}}\"\n      initCode:\n        type: \"constructor-encode\"\n        arguments:\n          creationCode: \"{{Contract(ProxyBytecode).creationCode}}\"\n          types: [\"address\"]\n          values: [\"{{implementation}}\"]\n```\n\nNotes about template files:\n- The `type: \"template\"` discriminator is optional but recommended for clarity. If provided, it must be exactly `template`.\n- Templates are auto-discovered from your project `templates/` folder and any `templates/` subfolders under `jobs/`.\n\n## Usage\n\n### Running Deployments\n\nDeploy all jobs to all configured networks:\n\n```bash\ncatapult run --private-key YOUR_PRIVATE_KEY\n```\n\nDeploy specific jobs:\n\n```bash\ncatapult run core-contracts token-setup --private-key YOUR_PRIVATE_KEY\n```\n\nDeploy multiple jobs using wildcards (matches job names, including nested names like `sequence_v3/beta_4`):\n\n```bash\n# Run all jobs whose name starts with \"sequence_\"\ncatapult run sequence_* -k $PRIVATE_KEY\n\n# Run all jobs under a namespace/folder-like prefix\ncatapult run \"sequence_v3/*\" -k $PRIVATE_KEY\n\n# Combine patterns and exact names; duplicates are de-duplicated\ncatapult run job1 job? -k $PRIVATE_KEY\n```\n\nDeploy to specific networks:\n\n```bash\n# Comma-separated, supports chain IDs and network names (name matches include all networks with that name)\ncatapult run --network 1,42161 --private-key YOUR_PRIVATE_KEY\ncatapult run --network mainnet --private-key YOUR_PRIVATE_KEY       # all networks named \"Mainnet\"\ncatapult run --network mainnet,polygon -k $PRIVATE_KEY core-contracts\n```\n\nCommon options (run):\n\n- `-p, --project \u003cpath\u003e`: Project root directory (defaults to current directory)\n- `--dotenv \u003cpath\u003e`: Load environment variables from a custom .env file (run command only)\n- `-n, --network \u003cselectors\u003e`: Comma-separated selectors by chain ID or network name\n- `--rpc-url \u003curl\u003e`: Run against a single custom RPC; chain ID is auto-detected (no networks.yaml required)\n- `-k, --private-key \u003ckey\u003e`: EOA private key (or set `PRIVATE_KEY`)\n- `--etherscan-api-key \u003ckey\u003e`: Etherscan API key (or set `ETHERSCAN_API_KEY`)\n- `--fail-early`: Stop as soon as any job fails\n- `--ignore-verify-errors`: Convert verification errors to warnings and show complete report at end (instead of exiting with error code)\n- `--no-post-check-conditions`: Skip post-execution evaluation of skip conditions\n- `--flat-output`: Write outputs in a single flat `output/` directory (do not mirror `jobs/` structure)\n- `--no-summary`: Hide the end-of-run summary\n- `--run-deprecated`: Allow running jobs marked `deprecated: true` (otherwise skipped unless explicitly targeted)\n- `--no-std`: Do not load built-in standard templates\n- `-v, --verbose` (repeatable): Increase logging verbosity (`-v`, `-vv`, `-vvv`)\n\nExamples:\n\n- Using a custom RPC (no networks.yaml needed):\n\n```bash\ncatapult run --rpc-url http://127.0.0.1:8545 -k $PRIVATE_KEY\n```\n\n- Write outputs flat instead of mirroring `jobs/` folders:\n\n```bash\ncatapult run --flat-output -k $PRIVATE_KEY\n```\n\n- Run a deprecated job explicitly:\n  - Without flag (explicit targeting runs it):\n    ```bash\n    catapult run legacy-job -k $PRIVATE_KEY\n    ```\n  - Or include all deprecated jobs in the plan:\n    ```bash\n    catapult run --run-deprecated -k $PRIVATE_KEY\n    ```\n\n### Validation and Dry Run\n\nValidate your configuration without executing transactions:\n\n```bash\ncatapult dry-run\n```\n\nValidate specific jobs:\n\n```bash\ncatapult dry-run core-contracts --network 1\ncatapult dry-run core-contracts --network polygon\ncatapult dry-run core-contracts --network mainnet,42161\n```\n\n### Listing Resources\n\nList available jobs:\n\n```bash\ncatapult list jobs\n```\n\nList detected contracts:\n\n```bash\ncatapult list contracts\n```\n\nList available templates:\n\n```bash\ncatapult list templates\n```\n\nList configured networks:\n\n```bash\ncatapult list networks\n```\n\nList only test networks:\n\n```bash\ncatapult list networks --only-testnets\n```\n\nList only non-test networks:\n\n```bash\ncatapult list networks --only-non-testnets\n```\n\nList constants (top-level and per-job):\n\n```bash\ncatapult list constants\n```\n\nSimple outputs for scripting:\n\n```bash\n# Names only, one per line\ncatapult list networks --simple\n\n# Chain IDs only, one per line\ncatapult list networks --simple-chain-ids\n```\n\nUtilities:\n\n```bash\n# Convert chain ID to network name\ncatapult utils chain-id-to-name 42161 -p ./my-project\n```\n\nEtherscan helpers:\n\n```bash\n# Fetch ABI from Etherscan v2\ncatapult etherscan abi -n 1 -a 0xdAC17F958D2ee523a2206206994597C13D831ec7 --etherscan-api-key $ETHERSCAN_API_KEY\ncatapult etherscan abi -n mainnet -a 0xdAC17F... --etherscan-api-key $ETHERSCAN_API_KEY\n\n# Fetch source (standard-json or flattened) from Etherscan v2\ncatapult etherscan source -n 1 -a 0xdAC17F958D2ee523a2206206994597C13D831ec7 --etherscan-api-key $ETHERSCAN_API_KEY\ncatapult etherscan source -n mainnet -a 0xdAC17F... --etherscan-api-key $ETHERSCAN_API_KEY\n```\n\n## Built-in Actions\n\nCatapult provides several built-in primitive actions:\n\n### `send-transaction`\nSend a transaction to the blockchain:\n\n```yaml\n- type: \"send-transaction\"\n  arguments:\n    to: \"0x742...\"\n    value: \"1000000000000000000\"  # 1 ETH in wei\n    data: \"0x...\"\n    gasMultiplier: 1.5  # Optional: multiply gas limit by this factor\n```\n\nThe `gasMultiplier` parameter is optional and allows you to tune the gas limit before sending the transaction:\n- If a network gas limit is configured, it will be multiplied by this factor\n- If no network gas limit is set, gas will be estimated first, then multiplied by this factor\n- Must be a positive number (e.g., 1.5 for 50% more gas, 0.8 for 20% less gas)\n\n### `send-signed-transaction`\nBroadcast a pre-signed transaction:\n\n```yaml\n- type: \"send-signed-transaction\"\n  arguments:\n    transaction: \"0x...\"  # Raw signed transaction\n```\n\n### `static`\nSets a static value that can be referenced in subsequent steps. Useful for defining constants or passing data between actions.\n\n```yaml\n- type: \"static\"\n  name: \"my-value\"\n  arguments:\n    value: \"hello world\"\n```\n\nThe `name` field is optional. When provided, the value is stored under [`name.value`](src/lib/core/engine.ts:560) in the context. If omitted, the value is computed but not stored. Supports all JSON data types including strings, numbers, booleans, objects, and arrays.\n\nExample with complex data:\n\n```yaml\n- type: \"static\"\n  name: \"config\"\n  arguments:\n    value:\n      endpoint: \"https://api.example.com\"\n      timeout: 5000\n      enabled: true\n```\n\nThis makes `config.value.endpoint`, `config.value.timeout`, and `config.value.enabled` available for use in subsequent actions.\n\n### `create-contract`\nCreate a contract by sending its creation bytecode (and optional value):\n\n```yaml\n- type: \"create-contract\"\n  name: \"deploy-foo\"\n  arguments:\n    data: \"{{Contract(Foo).creationCode}}\"\n    gasMultiplier: 1.2\n```\n\n### `json-request`\nMake an HTTP JSON request and use the result downstream:\n\n```yaml\n- type: \"json-request\"\n  name: \"get-config\"\n  arguments:\n    url: \"https://example.com/config.json\"\n    method: \"GET\"\n```\n\n## Value Resolvers\n\nCatapult includes powerful value resolvers for computing complex values:\n\n### `abi-encode`\nABI-encode function call data:\n\n```yaml\ndata:\n  type: \"abi-encode\"\n  arguments:\n    signature: \"transfer(address,uint256)\"\n    values:\n      - \"0x742...\"\n      - \"1000000000000000000\"\n```\n\n### `constructor-encode`\nEncode constructor parameters with bytecode:\n\n```yaml\ncreationCode:\n  type: \"constructor-encode\"\n  arguments:\n    creationCode: \"{{Contract(MyContract).creationCode}}\"\n    types: [\"address\", \"uint256\"]\n    values: [\"{{factory.address}}\", \"100\"]\n```\n\n### `abi-pack`\nPack values per ABI types into bytes:\n\n```yaml\npayload:\n  type: \"abi-pack\"\n  arguments:\n    types: [\"address\", \"uint256\"]\n    values: [\"{{recipient}}\", \"{{amount}}\"]\n```\n\n### `compute-create2`\nCompute CREATE2 addresses:\n\n```yaml\naddress:\n  type: \"compute-create2\"\n  arguments:\n    deployerAddress: \"{{factory.address}}\"\n    salt: \"{{salt}}\"\n    initCode: \"{{creationCode}}\"\n```\n\n### `basic-arithmetic`\nPerform mathematical operations:\n\n```yaml\namount:\n  type: \"basic-arithmetic\"\n  arguments:\n    operation: \"add\"\n    values: [\"{{current_balance}}\", \"1000000000000000000\"]\n```\n\n### `read-balance`\nRead account balance:\n\n```yaml\nbalance:\n  type: \"read-balance\"\n  arguments:\n    address: \"{{deployer_address}}\"\n```\n\n### `call`\nMake view/pure function calls:\n\n```yaml\nresult:\n  type: \"call\"\n  arguments:\n    to: \"{{contract.address}}\"\n    signature: \"getName()\"\n    values: []\n```\n\n### `verify-contract`\n### `read-json`\nRead a value from a JSON object at a given path:\n\n```yaml\ntokenAddress:\n  type: \"read-json\"\n  arguments:\n    json: \"{{get-config.response}}\"\n    path: \"tokens.usdc.address\"\n```\nVerify deployed contracts on block explorers:\n\n```yaml\n- type: \"verify-contract\"\n  arguments:\n    address: \"{{deploy-factory.address}}\"\n    contract: \"{{Contract(MyContract)}}\"  # Reference to the contract to verify\n    constructorArguments: \"0x000000000000000000000000...\"  # Optional hex-encoded args\n    platform: \"etherscan_v2\"  # Optional, defaults to \"all\" (tries all configured platforms)\n```\n\n#### Verification Error Handling\n\nBy default, verification failures will cause the deployment to exit with an error code. To continue deployment even when verification fails and receive a comprehensive warning report at the end, use the `--ignore-verify-errors` flag:\n\n```bash\ncatapult run --ignore-verify-errors\n```\n\nThis is useful when:\n- You want to complete all deployments even if some contract verifications fail\n- Working with networks where verification platforms may be unreliable\n- Running in CI/CD environments where you prefer warnings over hard failures for verification issues\n\nWhen enabled, verification errors are converted to warnings and a detailed report is shown at the end of the deployment with all verification failures.\n\n## Skip Conditions\n\nAvoid redundant operations with skip conditions:\n\n### `contract-exists`\nSkip if contract exists at address:\n\n```yaml\nskip_condition:\n  - type: \"contract-exists\"\n    arguments:\n      address: \"{{computed_address}}\"\n```\n\n### `job-completed`\nSkip if another job is completed:\n\n```yaml\nskip_condition:\n  - type: \"job-completed\"\n    arguments:\n      job: \"prerequisite-job\"\n```\n\n## Standard Templates\n\nCatapult includes several standard templates:\n\n- **`sequence-universal-deployer-2`**: Deploy contracts using Sequence's Universal Deployer v2\n- **`nano-universal-deployer`**: Deploy contracts using the Nano Universal Deployer\n- **`erc-2470`** and raw variant: CREATE2 Deployer (singleton factory)\n- **`assured-deployment`**: Helper to ensure a contract is deployed at a specific address\n- **`min-balance`**: Ensure minimum balance for any given address\n- Raw building blocks: `raw-sequence-universal-deployer-2`, `raw-nano-universal-deployer`, `raw-erc-2470`\n\n## Contract Resolution\n\nCatapult automatically discovers and indexes contract artifacts in your project. It supports:\n\n- **JSON artifacts** (Hardhat, Truffle, Foundry)\n- **Nested directory structures**\n- **Hash-based contract references**\n- **Path-based contract references**\n- **Name-based contract references**\n\nReference contracts in your YAML using the new unified Contract() syntax:\n\n```yaml\ncreationCode: \"{{Contract(path/to/MyContract).creationCode}}\"\n# or\ncreationCode: \"{{Contract(0x1234...hash).creationCode}}\"\n```\n\n## Output Format\n\nAfter successful deployment, Catapult generates JSON files in the `output/` directory for each job. The output format is optimized to reduce repetition:\n\n### Success Grouping\n\nNetworks with identical deployment outputs are grouped together:\n\n```json\n{\n  \"jobName\": \"core-contracts\",\n  \"jobVersion\": \"1.0.0\",\n  \"lastRun\": \"2025-01-15T10:30:45.123Z\",\n  \"networks\": [\n    {\n      \"status\": \"success\",\n      \"chainIds\": [\"1\", \"42161\", \"137\"],\n      \"outputs\": {\n        \"deploy-factory.address\": \"0x742d35Cc6ab8b3c7B3d4B8b3aB4c8f9e9C8e8aB6\",\n        \"deploy-factory.txHash\": \"0xabc123...\",\n        \"deploy-implementation.address\": \"0x123abc...\"\n      }\n    }\n  ]\n}\n```\n\n### Error Handling\n\nWhen deployments fail on specific networks, each failure is recorded separately:\n\n```json\n{\n  \"jobName\": \"core-contracts\", \n  \"jobVersion\": \"1.0.0\",\n  \"lastRun\": \"2025-01-15T10:30:45.123Z\",\n  \"networks\": [\n    {\n      \"status\": \"success\",\n      \"chainIds\": [\"1\", \"42161\"],\n      \"outputs\": {\n        \"deploy-factory.address\": \"0x742d35Cc6ab8b3c7B3d4B8b3aB4c8f9e9C8e8aB6\"\n      }\n    },\n    {\n      \"status\": \"error\",\n      \"chainId\": \"137\",\n      \"error\": \"Transaction failed: insufficient funds\"\n    }\n  ]\n}\n```\n\nThis format ensures:\n- **Minimal repetition**: Successful deployments with identical outputs across multiple networks are grouped together\n- **Clear error tracking**: Individual network failures are clearly documented\n- **Scalability**: The format remains readable even with deployments across dozens of networks\n\nOutput layout and selection:\n\n- By default, output files mirror the structure under `jobs/` (e.g., `jobs/core/job.yaml` -\u003e `output/core/job.json`). Use `--flat-output` to write all job JSON files directly under `output/`.\n- You can control which action outputs are persisted per job using the `output` flag on actions:\n  - `output: true` to include all outputs for that action\n  - `output: false` to exclude outputs for that action\n  - `output: { key1: true, key2: true }` to include only specific keys from that action (e.g., `txHash`, `address`)\n\n## Environment Variables\n\n- `PRIVATE_KEY`: Signer private key (alternative to `--private-key`)\n- `ETHERSCAN_API_KEY`: API key for Etherscan v2 verification (alternative to `--etherscan-api-key`)\n\nYou can load environment variables from a file using `--dotenv \u003cpath\u003e` on the `run` command (defaults to `.env` in the current directory when provided).\n\n## Development\n\n### Prerequisites\n- Node.js \u003e= 16.0.0\n- npm or yarn\n\n### Setup\n```bash\n# Install dependencies\nnpm install\n\n# Build the project\nnpm run build\n\n# Run in development mode\nnpm run dev\n\n# Watch for changes\nnpm run watch\n```\n\n### Scripts\n- `npm run build` - Compile TypeScript to JavaScript\n- `npm run dev` - Run the CLI in development mode with ts-node\n- `npm run watch` - Watch for changes\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xsequence%2Fcatapult","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0xsequence%2Fcatapult","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xsequence%2Fcatapult/lists"}