{"id":28239363,"url":"https://github.com/cqlyj/calary","last_synced_at":"2025-10-09T05:35:34.405Z","repository":{"id":286125466,"uuid":"960447613","full_name":"cqlyj/Calary","owner":"cqlyj","description":"Compliance toolkit empowering killer consumer dApps with on-chain payroll, swaps \u0026 rewards","archived":false,"fork":false,"pushed_at":"2025-04-05T21:51:30.000Z","size":1893,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-11T07:43:44.955Z","etag":null,"topics":["celo-blockchain","ethglobal-taipei","hackathon","uniswap-hooks"],"latest_commit_sha":null,"homepage":"https://ethglobal.com/showcase/calary-se95k","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/cqlyj.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}},"created_at":"2025-04-04T13:00:30.000Z","updated_at":"2025-04-10T05:15:31.000Z","dependencies_parsed_at":"2025-04-04T14:22:26.003Z","dependency_job_id":"9d9aae8b-0c6a-411d-8f31-41a317753b6c","html_url":"https://github.com/cqlyj/Calary","commit_stats":null,"previous_names":["cqlyj/calary"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cqlyj/Calary","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cqlyj%2FCalary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cqlyj%2FCalary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cqlyj%2FCalary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cqlyj%2FCalary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cqlyj","download_url":"https://codeload.github.com/cqlyj/Calary/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cqlyj%2FCalary/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000741,"owners_count":26082932,"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-09T02:00:07.460Z","response_time":59,"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":["celo-blockchain","ethglobal-taipei","hackathon","uniswap-hooks"],"created_at":"2025-05-19T02:12:13.236Z","updated_at":"2025-10-09T05:35:34.389Z","avatar_url":"https://github.com/cqlyj.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Calary\n\nCalary is a next-generation developer toolkit that empowers teams to build consumer-grade decentralized applications (dApps) with robust on-chain financial features and regulatory compliance baked in. At its core, Calary provides a modular suite of tools that handle end-to-end processes—from user verification and identity management to complex payroll systems and token swaps.\n\n---\n\n### Flow Integration\n\nCalary integrates with **Flow** in two key areas:\n\n1. **User Registry**: Calary stores user compliance data (wallet, passport expiry, and `rewarded` status) on the Flow blockchain. This integration ensures compliance data is stored securely and accessible across the ecosystem.\n2. **Payroll Contracts**: Payroll systems such as **Time-Based Payroll**, **Custom Logic Payroll**, and **Milestone-Based Payroll** are deployed on Flow to manage salary payouts. These contracts benefit from Flow’s scalability and efficiency for handling payroll data and transactions in real time.\n\nBoth Flow integrations were achieved using Flow’s **EVM compatibility layer**, allowing seamless interaction with existing Ethereum-style smart contracts and development tools.\n\nCheck more about Calary as a developer toolkit [here](developer-toolkit.md).\n\n### Team \u0026 Social Handles\n\nThis project was developed by a solo blockchain developer focused on smart contract development and ecosystem integration.\n\n- **GitHub**: [cqlyj](https://github.com/cqlyj)\n- **Twitter**: [luoyingjie0721](https://x.com/luoyingjie0721)\n\n## Uniswap v4 Integration\n\n### Project Overview\n\nCalary leverages **Uniswap v4 Hooks** as a core component to provide a compliance-driven, reward-based swap system. The integration optimizes the swap functionality, ensuring that only verified and compliant users participate in the swap ecosystem. It also includes reward mechanisms, where users are incentivized with Calary tokens after completing a compliant swap, reinforcing the system’s compliance framework and ensuring payroll participants are rewarded.\n\nFor more use cases, check [here](./developer-toolkit.md#swap-infrastructure--incentives)\n\n### Uniswap v4 Hooks Integration\n\nCalary uses **two custom hooks**—`beforeSwap` and `afterSwap`—to enforce compliance and trigger reward mechanisms:\n\n1. **beforeSwap Hook**: This hook ensures that the user is verified before any swap is executed. It checks whether the user has passed the KYC process by referencing the user’s compliance status stored in the **Registry**.\n2. **afterSwap Hook**: After a successful swap, this hook ensures that users who have claimed payroll and are eligible for rewards receive native Calary tokens. The hook checks the `rewarded` flag for each user and mints tokens if the flag is false. This guarantees that rewards are distributed once per claim cycle.\n\nThese hooks integrate directly into the swap logic, enabling smooth, on-chain transaction validation while maintaining regulatory compliance.\n\n### Architecture\n\nBelow is the architecture of the Calary system, illustrating how the Uniswap v4 Hooks are integrated:\n\n![Uniswap Architecture](img/swap-infrastructure-and-incentives.png)\n\n### Example \u0026 Testing\n\n- **Testnet Deployment**: Contracts and hooks are deployed on a **testnet** for validation. The system interacts with real Uniswap v4 pairs, executing mock swaps and minting Calary tokens.\n- **Smart Contract Execution**: Both `beforeSwap` and `afterSwap` hooks are implemented in Solidity and tested locally via Foundry.\n\n```\nTraces:\n  [135429] Swap::run()\n    ├─ [0] VM::broadcast()\n    │   └─ ← [Return]\n    ├─ [4834] 0x81F55140e2D2f277510d5913CEF357bc88dC185a::approve(PoolSwapTest: [0x9B6b46e2c869aa39918Db7f52f5557FE577B6eEe], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])\n    │   ├─ emit Approval(owner: 0xFB6a372F2F51a002b390D18693075157A459641F, spender: PoolSwapTest: [0x9B6b46e2c869aa39918Db7f52f5557FE577B6eEe], value: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])\n    │   └─ ← [Return] true\n    ├─ [0] VM::broadcast()\n    │   └─ ← [Return]\n    ├─ [4834] 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE::approve(PoolSwapTest: [0x9B6b46e2c869aa39918Db7f52f5557FE577B6eEe], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])\n    │   ├─ emit Approval(owner: 0xFB6a372F2F51a002b390D18693075157A459641F, spender: PoolSwapTest: [0x9B6b46e2c869aa39918Db7f52f5557FE577B6eEe], value: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])\n    │   └─ ← [Return] true\n    ├─ [0] VM::broadcast()\n    │   └─ ← [Return]\n    ├─ [107759] PoolSwapTest::swap(PoolKey({ currency0: 0x81F55140e2D2f277510d5913CEF357bc88dC185a, currency1: 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE, fee: 3000, tickSpacing: 60, hooks: 0x98d576BF36EE2eCf257396dE5f40eD9B0FBEc0C0 }), SwapParams({ zeroForOne: false, amountSpecified: 1000000 [1e6], sqrtPriceLimitX96: 1461446703485210103287273052203988822378723970341 [1.461e48] }), TestSettings({ takeClaims: false, settleUsingBurn: false }), 0x000000000000000000000000fb6a372f2f51a002b390d18693075157a459641f)\n    │   ├─ [102092] PoolManager::unlock(0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000fb6a372f2f51a002b390d18693075157a459641f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081f55140e2d2f277510d5913cef357bc88dc185a000000000000000000000000effd7ac3073f3e4122e31ff18f9ae69a4a595dfe0000000000000000000000000000000000000000000000000000000000000bb8000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000098d576bf36ee2ecf257396de5f40ed9b0fbec0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000fffd8963efd1fc6a506488495d951d5263988d2500000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000fb6a372f2f51a002b390d18693075157a459641f)\n    │   │   ├─ [100051] PoolSwapTest::unlockCallback(0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000fb6a372f2f51a002b390d18693075157a459641f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081f55140e2d2f277510d5913cef357bc88dc185a000000000000000000000000effd7ac3073f3e4122e31ff18f9ae69a4a595dfe0000000000000000000000000000000000000000000000000000000000000bb8000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000098d576bf36ee2ecf257396de5f40ed9b0fbec0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000fffd8963efd1fc6a506488495d951d5263988d2500000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000fb6a372f2f51a002b390d18693075157a459641f)\n    │   │   │   ├─ [2559] 0x81F55140e2D2f277510d5913CEF357bc88dC185a::balanceOf(0xFB6a372F2F51a002b390D18693075157A459641F) [staticcall]\n    │   │   │   │   └─ ← [Return] 999999999999998003000000 [9.999e23]\n    │   │   │   ├─ [2559] 0x81F55140e2D2f277510d5913CEF357bc88dC185a::balanceOf(PoolManager: [0xE03A1074c86CFeDd5C142C4F04F1a1536e203543]) [staticcall]\n    │   │   │   │   └─ ← [Return] 1997000000 [1.997e9]\n    │   │   │   ├─ [859] PoolManager::exttload(0x83409d4e11f9013dcca2b53a92eaedb9dd49b0909e5cb642397b8b76116402db) [staticcall]\n    │   │   │   │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000000\n    │   │   │   ├─ [2559] 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE::balanceOf(0xFB6a372F2F51a002b390D18693075157A459641F) [staticcall]\n    │   │   │   │   └─ ← [Return] 997697070703 [9.976e11]\n    │   │   │   ├─ [2559] 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE::balanceOf(PoolManager: [0xE03A1074c86CFeDd5C142C4F04F1a1536e203543]) [staticcall]\n    │   │   │   │   └─ ← [Return] 2003009297 [2.003e9]\n    │   │   │   ├─ [859] PoolManager::exttload(0x00a777b1b939ce8dfaef96af610955a10387bc26489a0ad982436811f19b9b64) [staticcall]\n    │   │   │   │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000000\n    │   │   │   ├─ [48840] PoolManager::swap(PoolKey({ currency0: 0x81F55140e2D2f277510d5913CEF357bc88dC185a, currency1: 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE, fee: 3000, tickSpacing: 60, hooks: 0x98d576BF36EE2eCf257396dE5f40eD9B0FBEc0C0 }), SwapParams({ zeroForOne: false, amountSpecified: 1000000 [1e6], sqrtPriceLimitX96: 1461446703485210103287273052203988822378723970341 [1.461e48] }), 0x000000000000000000000000fb6a372f2f51a002b390d18693075157a459641f)\n    │   │   │   │   ├─ [13097] 0x98d576BF36EE2eCf257396dE5f40eD9B0FBEc0C0::beforeSwap(PoolSwapTest: [0x9B6b46e2c869aa39918Db7f52f5557FE577B6eEe], PoolKey({ currency0: 0x81F55140e2D2f277510d5913CEF357bc88dC185a, currency1: 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE, fee: 3000, tickSpacing: 60, hooks: 0x98d576BF36EE2eCf257396dE5f40eD9B0FBEc0C0 }), SwapParams({ zeroForOne: false, amountSpecified: 1000000 [1e6], sqrtPriceLimitX96: 1461446703485210103287273052203988822378723970341 [1.461e48] }), 0x000000000000000000000000fb6a372f2f51a002b390d18693075157a459641f)\n    │   │   │   │   │   ├─ [6924] 0x74aCE009385B13197AC36939CfF24CB3Dbd2521C::checkValidity(0xFB6a372F2F51a002b390D18693075157A459641F) [staticcall]\n    │   │   │   │   │   │   └─ ← [Return] true\n    │   │   │   │   │   └─ ← [Return] 0x575e24b4, 0, 0\n    │   │   │   │   ├─ emit Swap(id: 0x8878a61be08b0aee98da042e042d63d95ed8274d991e6088c9df0df13c9fa0dc, sender: PoolSwapTest: [0x9B6b46e2c869aa39918Db7f52f5557FE577B6eEe], amount0: 1000000 [1e6], amount1: -1003217 [-1.003e6], sqrtPriceX96: 79237529344531561555930754913 [7.923e28], liquidity: 33837499809 [3.383e10], tick: 2, fee: 3000)\n    │   │   │   │   ├─ [2183] 0x98d576BF36EE2eCf257396dE5f40eD9B0FBEc0C0::afterSwap(PoolSwapTest: [0x9B6b46e2c869aa39918Db7f52f5557FE577B6eEe], PoolKey({ currency0: 0x81F55140e2D2f277510d5913CEF357bc88dC185a, currency1: 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE, fee: 3000, tickSpacing: 60, hooks: 0x98d576BF36EE2eCf257396dE5f40eD9B0FBEc0C0 }), SwapParams({ zeroForOne: false, amountSpecified: 1000000 [1e6], sqrtPriceLimitX96: 1461446703485210103287273052203988822378723970341 [1.461e48] }), 340282707203305384401838070806375643223208239 [3.402e44], 0x000000000000000000000000fb6a372f2f51a002b390d18693075157a459641f)\n    │   │   │   │   │   ├─ [566] 0x74aCE009385B13197AC36939CfF24CB3Dbd2521C::checkRewardStatus(0xFB6a372F2F51a002b390D18693075157A459641F) [staticcall]\n    │   │   │   │   │   │   └─ ← [Return] false\n    │   │   │   │   │   └─ ← [Return] 0xb47b2fb1, 0\n    │   │   │   │   └─ ← [Return] 340282707203305384401838070806375643223208239 [3.402e44]\n    │   │   │   ├─ [559] 0x81F55140e2D2f277510d5913CEF357bc88dC185a::balanceOf(0xFB6a372F2F51a002b390D18693075157A459641F) [staticcall]\n    │   │   │   │   └─ ← [Return] 999999999999998003000000 [9.999e23]\n    │   │   │   ├─ [559] 0x81F55140e2D2f277510d5913CEF357bc88dC185a::balanceOf(PoolManager: [0xE03A1074c86CFeDd5C142C4F04F1a1536e203543]) [staticcall]\n    │   │   │   │   └─ ← [Return] 1997000000 [1.997e9]\n    │   │   │   ├─ [859] PoolManager::exttload(0x83409d4e11f9013dcca2b53a92eaedb9dd49b0909e5cb642397b8b76116402db) [staticcall]\n    │   │   │   │   └─ ← [Return] 0x00000000000000000000000000000000000000000000000000000000000f4240\n    │   │   │   ├─ [559] 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE::balanceOf(0xFB6a372F2F51a002b390D18693075157A459641F) [staticcall]\n    │   │   │   │   └─ ← [Return] 997697070703 [9.976e11]\n    │   │   │   ├─ [559] 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE::balanceOf(PoolManager: [0xE03A1074c86CFeDd5C142C4F04F1a1536e203543]) [staticcall]\n    │   │   │   │   └─ ← [Return] 2003009297 [2.003e9]\n    │   │   │   ├─ [859] PoolManager::exttload(0x00a777b1b939ce8dfaef96af610955a10387bc26489a0ad982436811f19b9b64) [staticcall]\n    │   │   │   │   └─ ← [Return] 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0b12f\n    │   │   │   ├─ [1932] PoolManager::sync(0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE)\n    │   │   │   │   ├─ [559] 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE::balanceOf(PoolManager: [0xE03A1074c86CFeDd5C142C4F04F1a1536e203543]) [staticcall]\n    │   │   │   │   │   └─ ← [Return] 2003009297 [2.003e9]\n    │   │   │   │   └─ ← [Stop]\n    │   │   │   ├─ [9320] 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE::transferFrom(0xFB6a372F2F51a002b390D18693075157A459641F, PoolManager: [0xE03A1074c86CFeDd5C142C4F04F1a1536e203543], 1003217 [1.003e6])\n    │   │   │   │   ├─ emit Transfer(from: 0xFB6a372F2F51a002b390D18693075157A459641F, to: PoolManager: [0xE03A1074c86CFeDd5C142C4F04F1a1536e203543], value: 1003217 [1.003e6])\n    │   │   │   │   └─ ← [Return] true\n    │   │   │   ├─ [2533] PoolManager::settle()\n    │   │   │   │   ├─ [559] 0xeffD7ac3073F3e4122e31fF18F9Ae69A4a595dFE::balanceOf(PoolManager: [0xE03A1074c86CFeDd5C142C4F04F1a1536e203543]) [staticcall]\n    │   │   │   │   │   └─ ← [Return] 2004012514 [2.004e9]\n    │   │   │   │   └─ ← [Return] 1003217 [1.003e6]\n    │   │   │   ├─ [10454] PoolManager::take(0x81F55140e2D2f277510d5913CEF357bc88dC185a, 0xFB6a372F2F51a002b390D18693075157A459641F, 1000000 [1e6])\n    │   │   │   │   ├─ [8881] 0x81F55140e2D2f277510d5913CEF357bc88dC185a::transfer(0xFB6a372F2F51a002b390D18693075157A459641F, 1000000 [1e6])\n    │   │   │   │   │   ├─ emit Transfer(from: PoolManager: [0xE03A1074c86CFeDd5C142C4F04F1a1536e203543], to: 0xFB6a372F2F51a002b390D18693075157A459641F, value: 1000000 [1e6])\n    │   │   │   │   │   └─ ← [Return] true\n    │   │   │   │   └─ ← [Stop]\n    │   │   │   └─ ← [Return] 0x000000000000000000000000000f4240fffffffffffffffffffffffffff0b12f\n    │   │   └─ ← [Return] 0x000000000000000000000000000f4240fffffffffffffffffffffffffff0b12f\n    │   └─ ← [Return] 340282707203305384401838070806375643223208239 [3.402e44]\n    └─ ← [Stop]\n```\n\nAnd you can have the contract in `sepoliaTestAddress.txt` file to check the hook address on sepolia testnet.\n\n### How to Run\n\n1. Clone the repository:\n\n```bash\ngit clone https://github.com/cqlyj/Calary\ncd calary\n```\n\n2. Install dependencies (using Foundry for contract testing):\n\n```bash\nmake install\n```\n\n3. Then directly run the command\n\n```bash\nmake swap\n```\n\nI have already set up the stuff OK for you, if you find the transaction reverted, please check if you have add yourself to the Registry contract.\n\n## Key Contracts\n\n### Registry\n\n- [Polygon Registry](https://polygon.blockscout.com/address/0x8371CA3C7aCB1002f2f940A3F30635623caa7590)\n- [Flow Registry](https://evm-testnet.flowscan.io/address/0x94a19c37aeb9f333157a4a577a16cdaff5007ba2)\n\n### Calary Contracts\n\n- [Flow Calary](https://evm-testnet.flowscan.io/address/0x6f9c71817bfa4a3e6466672143f57decea4457af)\n\n### Payroll Contracts\n\n- [Flow Time-Based Payroll](https://evm-testnet.flowscan.io/address/0xeb6421483320405dd5378518f3f16468af9c6e9b)\n- [Flow Custom Logic Payroll](https://evm-testnet.flowscan.io/address/0x4dd01797126924a50a48ca43eaead277d3e57aa5)\n- [Flow Milestone-Based Payroll](https://evm-testnet.flowscan.io/address/0xa7fbcaad0d4c2e8188b386b7c3951e1e0792bf8e)\n\n### Additional Contracts\n\n- [Celo CVLayer](https://celoscan.io/address/0x8371ca3c7acb1002f2f940a3f30635623caa7590)\n- [Celo ChainlinkRelayer](https://celoscan.io/address/0xe03040bf46cfd0284bf622d082116ab3dc579865)\n\n---\n\n## Key Features\n\n### User Onboarding \u0026 Compliance\n\n- **KYC via Self Protocol**: Users undergo KYC via the **Self Protocol**, submitting their passport details (nationality, age, passport expiry) and ensuring they are not from restricted regions (e.g., North Korea or Iran).\n- **Registry on Celo**: After verification, the user's wallet, passport expiry date, and a `rewarded` flag (for managing rewards eligibility) are stored on the **Celo Registry contract**.\n\n- **Cross-Chain Verification**: Utilizing **Hyperlane**, Calary relays user information (wallet address, passport expiry) to other supported chains, ensuring compliance checks are consistent across ecosystems.\n\n---\n\n### Payroll System\n\nCalary offers a flexible payroll framework that adapts to different business needs:\n\n- **Time-Based Payroll**: This system allows employers to set fixed intervals for salary claims. Employees receive scheduled payouts at regular intervals.\n\n- **Custom Logic Payroll**: For advanced payroll configurations, employers can implement custom payroll logic through the `ICustomPayrollLogic` interface. This interface can be extended with future zk-privacy features to secure sensitive payroll data.\n\n- **Milestone-Based Payroll**: Trigger salary payouts based on performance or specific events. The current implementation uses event signatures, but there is future potential for fully decentralized event-driven payments.\n\n---\n\n### Swap Infrastructure \u0026 Incentives\n\n- **Compliant Swaps**: Calary integrates a swap mechanism with **Uniswap v4**. Before executing a swap, the `beforeSwap` hook verifies that the user is compliant (i.e., verified through the registry).\n\n- **Rewarding Payroll Participation**: The `afterSwap` hook checks the user's `rewarded` flag. If the flag is false (indicating they’ve claimed their salary), Calary tokens are minted as a reward. These tokens serve as credentials, allowing users to redeem various perks such as **ENS names**, **event tickets**, and more.\n\n---\n\n## Smart Contracts \u0026 On-Chain Logic\n\nCalary is built using **Solidity** and **Foundry** for development, testing, and deployment. It consists of multiple contracts:\n\n- **Registry Contract**: Manages user compliance by recording wallet addresses, passport expiry, and the `rewarded` flag. Deployed on **Celo** for native integration.\n\n- **Payroll Contracts**:\n\n  - **Time-Based Payroll**: Supports fixed interval salary claims.\n  - **Custom Logic Payroll**: Requires employers to implement custom payroll logic via the `ICustomPayrollLogic` interface.\n  - **Milestone-Based Payroll**: Uses event-driven triggers to release salary payments.\n\n- **Swap Logic with Uniswap v4**: Integrates Uniswap v4 Hooks to ensure compliance during token swaps. The hooks check user verification status before the swap and mint Calary tokens post-swap.\n\n---\n\n## Off-Chain \u0026 Cross-Chain Infrastructure\n\n- **Hyperlane for Cross-Chain Data**: **Hyperlane** relays user compliance data across chains, ensuring that users' KYC information is accessible on supported networks.\n\n- **KYC Integration via Self Protocol**: The onboarding process includes **Self Protocol** to ensure users meet the compliance requirements before entering the system.\n\n---\n\n## Frontend \u0026 Backend (Minimal, Just to Prove It Works)\n\n### Frontend\n\n- **Minimal UI with Hardcoded Values**: The frontend is simple, focused on demonstrating the system's functionality, including:\n\n  - Role selection (Boss or Employee)\n  - Payroll contract deployment\n  - Calling key functions such as `depositFunds`, `addEmployee`, and `claimPayroll`\n  - Calary token minting logic via the Uniswap v4 hooks interaction\n\n- **Why Minimal?**: As a solo developer focusing on smart contracts, the UI is minimal to **demonstrate that the system works**. Advanced design elements have been omitted for hackathon purposes.\n\n### Backend\n\n- **Gas Master (Mock)**: A dummy backend simulates a \"gas master\" using a private key to trigger state-changing functions like `claimPayroll` or swap settlement, following the intended UX flow.\n\n---\n\n## Contact\n\nFor any inquiries or collaboration opportunities, please reach out via:\n\n[luoyingjie0721@gmail.com](luoyingjie0721@gmail.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcqlyj%2Fcalary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcqlyj%2Fcalary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcqlyj%2Fcalary/lists"}