{"id":51270018,"url":"https://github.com/halaprix/clanker-gate","last_synced_at":"2026-06-29T17:01:13.839Z","repository":{"id":361708033,"uuid":"1241773247","full_name":"halaprix/clanker-gate","owner":"halaprix","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-31T22:28:59.000Z","size":782,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-01T00:06:49.522Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://clanker-gate-policy-builder.vercel.app","language":"Solidity","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/halaprix.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":"2026-05-17T19:51:37.000Z","updated_at":"2026-05-31T22:29:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/halaprix/clanker-gate","commit_stats":null,"previous_names":["halaprix/clanker-gate"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/halaprix/clanker-gate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halaprix%2Fclanker-gate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halaprix%2Fclanker-gate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halaprix%2Fclanker-gate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halaprix%2Fclanker-gate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/halaprix","download_url":"https://codeload.github.com/halaprix/clanker-gate/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halaprix%2Fclanker-gate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34935530,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"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":"2026-06-29T17:01:11.308Z","updated_at":"2026-06-29T17:01:13.828Z","avatar_url":"https://github.com/halaprix.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"```\n________            __             ______      __     \n  / ____/ /___ _____  / /_____  _____/ ____/___ _/ /____ \n / /   / / __ `/ __ \\/ //_/ _ \\/ ___/ / __/ __ `/ __/ _ \\\n/ /___/ / /_/ / / / / ,\u003c /  __/ /  / /_/ / /_/ / /_/  __/\n\\____/_/\\__,_/_/ /_/_/|_|\\___/_/   \\____/\\__,_/\\__/\\___/ \n```\n\n**Stateful Transaction Validator for Smart Accounts**\n\nClankerGate is a validation module that enables defining granular transaction policies without giving external executors full private key access. It acts as a \"guard\" for various types of Smart Accounts, verifying on-chain whether operations fall within defined boundaries.\n\n## Implementations\n\n| Contract | Standard | Description |\n|----------|----------|-------------|\n| **ClankerGateCore** | Library | Shared validation logic (Merkle proof, calldata rules, OP_IN) |\n| **ClankerGate4337** | ERC-4337 | For Account Abstraction (UserOperation validation) |\n| **ClankerGateSafe** | Gnosis Safe | Safe Module with execTransaction |\n| **ClankerGate7579** | ERC-7579 | Modular accounts (ZeroDev, Biconomy, Rhinestone) |\n\n## How It Works\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│  OFF-CHAIN                                                      │\n│                                                                 │\n│  1. Developer defines policy via TypeScript SDK:                │\n│     policy.allow().to(ROUTER).fn(\"exactInput\")                 │\n│            .where(\"params.amountIn\").lte(1 ETH)                 │\n│                                                                 │\n│  2. Policy Compiler: ABI → selectors → offsets → Permission     │\n│                                                                 │\n│  3. Merkle Tree Builder: Permission → root + proof              │\n│                                                                 │\n│  4. Single transaction setPolicyRoot(root) on-chain             │\n└─────────────────────────────────────────────────────────────────┘\n                              │\n                              ▼\n┌─────────────────────────────────────────────────────────────────┐\n│  ON-CHAIN                                                       │\n│                                                                 │\n│  validateUserOp() / execTransaction():                          │\n│    1. Merkle Proof - verify policy is in tree                   │\n│    2. Calldata Rules - calldataload(offset) vs rules            │\n│    3. ECDSA Signature - verify owner signed                     │\n│    4. Time validation - validAfter / validUntil                 │\n│    5. Chain validation - chainId check                          │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n## Key Features\n\n| Feature | Description |\n|---------|-------------|\n| **Gas-efficient** | ~800 gas / rule (vs 20k-50k for ABI decode) |\n| **Stateful** | Stores policyRoots, nonces, usedPermissionHashes, and caller authorizations |\n| **Upgrade-proof** | On-chain contract never needs upgrade |\n| **Protocol-agnostic** | Any protocol - just provide ABI |\n| **Type-safe SDK** | viem + TypeScript with full typing |\n| **Multi-standard** | ERC-4337, Gnosis Safe, ERC-7579 |\n\n## Project Structure\n\n```\nclanker-gate/\n├── src/                              # Solidity smart contracts\n│   ├── ClankerGateCore.sol          # Shared logic (library)\n│   ├── ClankerGate4337.sol          # ERC-4337 validator\n│   ├── ClankerGateSafe.sol          # Gnosis Safe module\n│   ├── ClankerGate7579.sol          # ERC-7579 validator module\n│   └── interfaces/\n│       ├── IERC4337.sol             # ERC-4337 interfaces\n│       └── IERC7579.sol             # ERC-7579 interfaces\n├── test/                             # Foundry tests\n│   ├── ClankerGateCore.t.sol        # 26 tests (core logic + OP_IN)\n│   ├── ClankerGate4337.t.sol        # 21 tests (ERC-4337 + OP_IN)\n│   ├── ClankerGateSafe.t.sol        # 39 tests (Safe module + OP_IN)\n│   └── ClankerGate7579.t.sol        # 22 tests (ERC-7579)\n├── test/                             # Additional tests\n│   ├── GasBenchmark.t.sol            # 11 tests (gas benchmarks)\n│   ├── e2e/UniV3Swap.t.sol          # 4 tests (E2E integration)\n│   └── invariant/ClankerGateInvariant.t.sol # 8 tests\n├── sdk/                              # TypeScript SDK\n│   └── src/\n│       ├── types/                    # TypeScript types\n│       ├── domain/                   # Clean Architecture entities\n│       ├── abi-registry/             # ABI registry (Uniswap V3)\n│       ├── policy-compiler/          # Policy compiler\n│       ├── builder/                  # Merkle tree builder\n│       ├── simulator/                # Off-chain validation\n│       ├── clients/                  # Clients for each contract\n│       │   ├── ClankerGate4337Client.ts\n│       │   ├── ClankerGateSafeClient.ts\n│       │   └── ClankerGate7579Client.ts\n│       └── __tests__/                # 156 SDK tests\n├── ARCHITECTURE.md                   # Detailed architecture docs\n```\n\n## Quick Start\n\n### Smart Contract (Foundry)\n\n```bash\n# Build\nforge build\n\n# Test\nforge test --summary\n\n# Test specific contract\nforge test --match-path \"test/ClankerGate4337.t.sol\"\nforge test --match-path \"test/ClankerGate7579.t.sol\"\n```\n\n### SDK (TypeScript)\n\n```bash\ncd sdk\n\n# Install\npnpm install\n\n# Build\npnpm build\n\n# Test\npnpm test\n```\n\n## SDK Usage\n\n### Basic Policy\n\n```typescript\nimport { ClankerGate, UNISWAP_V3_ROUTER_ABI, OP } from '@clanker/gate-client';\n\n// Fluent API\nconst permission = ClankerGate.policy(UNISWAP_V3_ROUTER_ABI)\n  .allow()\n  .to('0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45') // Uniswap V3 Router\n  .fn('exactInput')\n  .where('params.amountIn')\n  .lte(BigInt('1000000000000000000')) // Max 1 ETH\n  .build();\n\n// Shorthand\nimport { permission } from '@clanker/gate-client';\n\nconst perm = permission(\n  UNISWAP_V3_ROUTER_ABI,\n  '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45',\n  'exactInput',\n  [\n    { paramPath: 'params.amountIn', op: OP.LTE, value: BigInt('1e18') }\n  ]\n);\n```\n\n### Comparison Operators\n\n| Operator | Description | Example |\n|----------|-------------|---------|\n| `eq(value)` | Equal | `.eq(BigInt(100))` |\n| `gt(value)` | Greater than | `.gt(BigInt(100))` |\n| `lt(value)` | Less than | `.lt(BigInt(100))` |\n| `gte(value)` | Greater than or equal | `.gte(BigInt(100))` |\n| `lte(value)` | Less than or equal | `.lte(BigInt(100))` |\n| `in(values[])` | Value in set | `.in([addr1, addr2, addr3])` |\n\n### OP_IN - Multiple Allowed Values\n\n```typescript\nimport { OP } from '@clanker/gate-client';\n\n// Allow 3 specific recipient addresses\nconst permission = ClankerGate.policy(TOKEN_ABI)\n  .allow()\n  .to(tokenAddress)\n  .fn('transfer')\n  .where('to')\n  .in([\n    BigInt('0x1234...'),  // address 1\n    BigInt('0x5678...'),  // address 2\n    BigInt('0xabcd...'),  // address 3\n  ])\n  .build();\n```\n\n### Merkle Tree and Proof\n\n```typescript\nconst builder = ClankerGate.merkleTree();\n\n// Add multiple policies\nbuilder.addPermission(permission1);\nbuilder.addPermission(permission2);\nbuilder.addPermission(permission3);\n\n// Build tree\nconst { root, leaves } = builder.build();\n\n// Generate proof for specific policy\nconst proof = builder.getProof(permission1);\n\nconsole.log({\n  root: proof.root,        // Save on-chain via setPolicyRoot()\n  proof: proof.proof,      // Include in guardData\n  leaf: proof.leaf         // Policy hash\n});\n```\n\n### Off-chain Simulator\n\n```typescript\nimport { simulator } from '@clanker/gate-client';\n\n// Test policy without deployment\nconst result = simulator.validate(permission, calldata);\n\nif (result.valid) {\n  console.log('Policy allows this operation');\n} else {\n  console.log('Rule violation:', result.violation);\n}\n```\n\n## Integration\n\n### ERC-4337 (ClankerGate4337)\n\n```typescript\nimport { createClankerGate4337Client } from '@clanker/gate-client';\n\nconst client = createClankerGate4337Client({\n  address: '0x...',\n  publicClient,\n  walletClient,\n});\n\n// Set policy\nawait client.setPolicyRoot({ account, root });\n\n// Get current root\nconst root = await client.getPolicyRoot(accountAddress);\n```\n\n```solidity\n// In Smart Account\nfunction validateUserOp(\n    UserOperation calldata userOp,\n    bytes32 userOpHash,\n    bytes calldata guardData  // (proof, permission, signature)\n) external returns (uint256) {\n    return clankerGate.validateUserOp(userOp, userOpHash, guardData);\n}\n```\n\n### Gnosis Safe (ClankerGateSafe)\n\n```typescript\nimport { createClankerGateSafeClient } from '@clanker/gate-client';\n\nconst client = createClankerGateSafeClient({\n  address: '0x...',\n  publicClient,\n  walletClient,\n});\n\n// Authorize executor\nawait client.authorizeCaller({ safe, caller, account });\n\n// Execute transaction with proof\nawait client.execTransaction({\n  safe,\n  to: targetAddress,\n  value: 0n,\n  data: callData,\n  operation: 0,\n  proof,\n  permission,\n  account,\n});\n```\n\n```solidity\n// In Safe - enable module\nsafe.enableModule(address(clankerGateSafe));\n\n// Executor executes transaction\nclankerGateSafe.execTransaction(\n    safe,\n    to,\n    value,\n    data,\n    operation,\n    proof,\n    permission\n);\n```\n\n### ERC-7579 (ClankerGate7579)\n\n```typescript\nimport { createClankerGate7579Client } from '@clanker/gate-client';\n\nconst client = createClankerGate7579Client({\n  address: '0x...',\n  publicClient,\n  walletClient,\n});\n\n// Encode installation data\nconst initData = client.encodeOnInstall(\n  ownerAddress,\n  initialRoot,\n  signatureValidator  // address(0) = use account.owner()\n);\n\n// In account contract:\n// account.installModule(MODULE_TYPE_VALIDATOR, gateAddress, initData);\n```\n\n```solidity\n// initData format\nabi.encode(\n    initOwner,           // Address that can update policy\n    initPolicyRoot,      // Initial Merkle root (0 = disabled)\n    signatureValidator   // Contract for signature validation (0 = account.owner())\n)\n```\n\n## ParamRule Struct\n\n```solidity\nstruct ParamRule {\n    uint256 offset;      // Offset in calldata (after selector)\n    uint8 op;            // Operator (0=EQ, 1=GT, 2=LT, 3=GTE, 4=LTE, 5=IN, 6=SGT, 7=SLT)\n    bytes32 value;       // Value for EQ/GT/LT/GTE/LTE/SGT/SLT\n    bytes32[] values;    // Array of values for OP_IN\n}\n```\n\n## Permission Struct\n\n```solidity\nstruct Permission {\n    address target;      // Target contract (0 = any)\n    bytes4 selector;     // Function selector\n    ParamRule[] rules;   // Validation rules\n    uint48 validAfter;   // Timestamp when valid (0 = always)\n    uint48 validUntil;   // Timestamp until valid (0 = always)\n    uint256 chainId;     // Chain ID (0 = all chains)\n}\n```\n\n## Security\n\n### Risks Addressed by ClankerGate\n\n| Risk | Mitigation |\n|------|------------|\n| Executor gets full key | Executor operates within policy bounds |\n| No operation trace | On-chain verification, immutable result |\n| One adapter per protocol | Single contract for all |\n| High gas cost | ~800 gas/rule vs 20k-50k |\n| Cross-chain replay | chainId in Permission struct |\n| Time-based attacks | validAfter / validUntil validation |\n\n### Failure Modes\n\n| Condition | Result |\n|-----------|--------|\n| `root == 0` | All transactions blocked (fail-safe) |\n| Invalid proof | Transaction rejected |\n| Rule violation | Transaction rejected with `RuleViolation` or `ValueNotInSet` |\n| Invalid signer | Transaction rejected with `UnauthorizedSigner` |\n| Permission expired | Transaction rejected with `PermissionExpired` |\n| ChainId mismatch | Transaction rejected with `ChainIdMismatch` |\n\n## Tech Stack\n\n| Layer | Technology |\n|-------|------------|\n| Smart Contract | Solidity ^0.8.20 |\n| Libraries | OpenZeppelin (MerkleProof, ECDSA, MessageHashUtils) |\n| Test Framework | Foundry |\n| TS Client | viem + merkletreejs |\n| Test Runner | Vitest |\n| Architecture | Clean Architecture (domain/use-cases/infrastructure) |\n\n## Tests\n\n```bash\n# Foundry (Solidity)\nforge test --summary\n# 148 tests passing\n\n# SDK (TypeScript)\ncd sdk \u0026\u0026 pnpm test\n# 156 tests passing\n\n# Total: 282 tests\n```\n\n### Test Coverage\n\n| Component | Tests | Description |\n|-----------|-------|-------------|\n| ClankerGateCore | 26 | Core logic, OP_IN, Merkle proof |\n| ClankerGate4337 | 21 | ERC-4337 validation, OP_IN integration |\n| ClankerGateSafe | 39 | Safe module, caller auth, OP_IN |\n| ClankerGate7579 | 22 | ERC-7579 module, install/uninstall |\n| GasBenchmark | 11 | Gas benchmarks |\n| UniV3Swap (E2E) | 4 | End-to-end integration tests |\n| Invariant | 8 | Invariant testing |\n| SDK Domain | 40 | Entities, value objects, errors |\n| SDK Simulator | 21 | Off-chain validation |\n| SDK Integration | 10 | End-to-end flows |\n\n## Documentation\n\n- `ARCHITECTURE.md` - Detailed architecture and design decisions\n- SDK TSDoc - API documentation in code\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalaprix%2Fclanker-gate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhalaprix%2Fclanker-gate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalaprix%2Fclanker-gate/lists"}