{"id":16404114,"url":"https://github.com/aimensahnoun/aimbridge","last_synced_at":"2025-03-23T05:31:17.696Z","repository":{"id":131860440,"uuid":"561295990","full_name":"aimensahnoun/AimBridge","owner":"aimensahnoun","description":"A EVM token bridge build using NextJS and relies on OpenZeppelin Defender to manage transactions.","archived":false,"fork":false,"pushed_at":"2025-03-14T07:52:44.000Z","size":8708,"stargazers_count":8,"open_issues_count":28,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-20T09:59:39.235Z","etag":null,"topics":["bridge","ethereum","ethersjs","jotai","nextjs","openzeppelin","openzeppelin-defender","polygon","rainbowkit","solidity","wagmi"],"latest_commit_sha":null,"homepage":"https://www.aimbridge.xyz","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/aimensahnoun.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}},"created_at":"2022-11-03T11:42:44.000Z","updated_at":"2024-10-11T10:04:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"f3b9c972-cad8-48d1-8cf0-d5425fc1dc0a","html_url":"https://github.com/aimensahnoun/AimBridge","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aimensahnoun%2FAimBridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aimensahnoun%2FAimBridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aimensahnoun%2FAimBridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aimensahnoun%2FAimBridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aimensahnoun","download_url":"https://codeload.github.com/aimensahnoun/AimBridge/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245061382,"owners_count":20554563,"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","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":["bridge","ethereum","ethersjs","jotai","nextjs","openzeppelin","openzeppelin-defender","polygon","rainbowkit","solidity","wagmi"],"created_at":"2024-10-11T05:51:29.612Z","updated_at":"2025-03-23T05:31:15.668Z","avatar_url":"https://github.com/aimensahnoun.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n![Logo](https://user-images.githubusercontent.com/62159014/202256101-c48303cb-9149-4e74-bee8-aceb67254bf2.png)\n\n\n# AimBridge\n\nAimBridge is a proof of concept for a EVM token-bridge developed that uses OpenZeppelin Defender in order to manage the transactions between two networks.\n\n\n\n\n[![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/)  ![Lines of code](https://img.shields.io/tokei/lines/github/aimensahnoun/aimbridge) ![GitHub top language](https://img.shields.io/github/languages/top/aimensahnoun/aimbridge)\n\n## Demo\n[![AimBridge Demo](https://user-images.githubusercontent.com/62159014/201940171-02699192-5032-47d7-a05d-44d7fc52813e.png)](https://www.loom.com/share/b4281493343e4deea3a1dfc1be36819f)\n## Features\n\n- Transfer tokens from source network to target network, by generating a new Wrapper Token in the target network.\n- Reverse the wrapping process, by burning the warpped token in the source network and releasing locked tokens in the target network.\n- Display history of user's transactions using *The Graph* .\n- Streamline the `minting/releasing` process by implementing `OpenZeppelin Defender`, to provide a smoother and easier UX. (This is highly experimental and not suggested in production).\n\n\n## How it works\nThe bridge is has three important components:\n\n- the [`UI`](https://www.aimbridge.xyz) that manages all of the user's interactions and provides an easy and smooth UX.\n- The [`Smart contracts`](https://github.com/aimensahnoun/EVM-Bridge-hh) which are the backbone of all transactions.\n- [`OpenZeppelin Defender`](https://www.openzeppelin.com/defender) which are a very important component in this project, and what makes the UX much better.\n\n### Architecture \n![AimBridge Architecture](https://user-images.githubusercontent.com/62159014/201778084-b7bd232b-9522-4dd5-b138-8cde02baca6c.png)\n\nThis is a simplified version of how the whole system works.\n\nThe application detects all of the `ERC20` tokens a users has, and allows them to select any of them to bridge to the target network.\n\nAfter the users select their token, the amount is then transfered from the user's address into the bridge's address and locked there.\n\nOnce this process is complete, a `webhook` using `OpenZeppelin AutoTask` is called with the needed data in order to start the `minting`in the target network.\n\nThis is done in order to ensure the transaction on target network is executed automatically, without the user needing to switch networks or claim later on.\n\nHere's is a flowchart that explains the same details:\n![FlowChart](https://user-images.githubusercontent.com/62159014/201779496-f57e9d34-62f9-4fb3-89c1-b90e8dffa71c.png)\n\n## Security\n\nWhile `OpenZeppelin AutoTask` and `OpenZeppelin Relayer` help streamline the process, there are many security issues that arise.\n\n- Can anyone call the `miniting` and `releasing` methods ?\n- How to avoid showing the `webhook` url to users ?\n- How to secure a successful transaction against `replay attacks` ?\n\n### Roles\nIn order to solve the first issue, `Roles` were implemented into the bridge smart contracts, which makes `OpenZeppelin Relayer`s perfect for this.\n\nBy giving the `Relayer` account a role that allows them and only them to call the methods, we prevent regular users from causing issues.\nAnd since the relayes `keys`are injected automatically into the `OpenZeppelin AutoTask` this makes it easier.\n\n### NextJS API Route\nIn order to avoid the `WebHook` from being overwhelmed or attacked, it the `POST` request is abstracted by a `NextJS` api route.\nThe route is the only way to communicate with the `WebHook`.\n\nAnd the route is also secure with a secret key, any request to that route would fail unless the key is provided.\n\n### Replay attacks\nReplay attacks are the biggest threat to this architecture, a `Replay Attack` is when an attacker intercepts a communication, in our case the `webhook` call and delays it or repeat the successful transaction again.\n\nIt is apparent that if an attacker can repeat a successful transaction again, one could `mine` unlimited amount of the same token over and over again, or `release` the total balance of the bridge contract.\n\nIn order to avoid that a security mesure has been put in place.\n\n`timestamp + hash`:\n\nAny transaction sent to the webhook would consist of three things,\n\n- `Timestamp` : a `UNIX` timestamp of when the transaction has been started by the front-end\n- `Data` : the data needed to be sent to the `webhook` in order for it to carry out the command properly.\n- `Hash` : this is a hash generated using a private key, its a combination of the previously mentioned `timestamp` and `data` ( `h(timestamp+data)` ).\n\nOnce the `POST` request is sent to the `webhook`, if first checks the time passed from the `timestamp` it received and the current `timestamp`. If the difference between the two is bigger than a certain interval the request is automatically rejected.\n\nex: `timestamp-webhook - timestamp-front-end \u003e 5 minutes { reject }`\n\nThis is just an example and not how the actual thing is coded.\n\nNext, the webhook generates a `hash` using the same private key as the front-end, if the newly generated `hash` is the same with the one sent by the front-end it means the data has not been tampered with.\n\nex : `5a6b9c05466f6826530c379c2d1ad87b === 5a6b9c05466f6826530c379c2d1ad87b` Passes\n`5a6b9c05466f6826530c379c2d1ad87b === 5a667adbd4dfcaae3c8f86a835b8b54f` REJECTED\n\na change in the original `timestamp` or the `data` would also cause the hash to change, which leads to the request being rejected.\n\n\n\n\n\n\n## Important Note\n\nEven though there are security measures implemented , this is just a proof of concept and is not advised to be deployed to production.\n\nPlease make sure that your system is well secured before deploying as it can cause major loses for both the service and users.\n## Environment Variables\n\nTo run this project, you will need to add the following environment variables to your .env file\n\n\n```\n#Alchemy API key\nNEXT_PUBLIC_ALCHEMY_KEY=\n\n#Alchemy Goerli HTTPS URL\nNEXT_PUBLIC_ALCHEMY_GOERLI=\n\n#Alchemy Mumbai HTTPS URL\nNEXT_PUBLIC_ALCHEMY_MUMBAI=\n\n#Web-hook urls provided by OpenZeppelin Defender Autotask\nNEXT_PUBLIC_MUMBAI_WEBHOOK =\nNEXT_PUBLIC_GOERLI_WEBHOOK =\n\n#Secret key used for hashing\nNEXT_PUBLIC_WEBHOOK_SECRET=\n\n#Secret key used for securing API route\nNEXT_PUBLIC_API_SECRET_KEY=\n```\n\n\n\n## Smart Contracts\n\nIf you want to use your own deployed smart contrants you should change the addresses in `src/utils/chain-info.ts`\n\n\n```\nexport const chainInfo: Record\u003cstring, Chain\u003e = {\n  5: {\n    name: \"Goerli\",\n    contract: YOUR CONTRACT ADDRESS,\n    alchemyUrl: process.env.NEXT_PUBLIC_ALCHEMY_GOERLI as string,\n    webHookUrl: process.env.NEXT_PUBLIC_GOERLI_WEBHOOK as string,\n    explorer: \"https://goerli.etherscan.io/tx/\",\n    subgraph: YOUR SUBGRAPH ADDRESS,\n  },\n  80001: {\n    name: \"Mumbai\",\n    contract: YOUR CONTRACT ADDRESS,\n    alchemyUrl: process.env.NEXT_PUBLIC_ALCHEMY_MUMBAI as string,\n    webHookUrl: process.env.NEXT_PUBLIC_MUMBAI_WEBHOOK as string,\n    explorer: \"https://mumbai.polygonscan.com/tx/\",\n    subgraph: YOUR SUBGRAPH ADDRESS\n  },\n};\n```\n\n\n\n## Run Locally\n\nClone the project\n\n```bash\n  git clone https://github.com/aimensahnoun/AimBridge\n```\n\nGo to the project directory\n\n```bash\n  cd my-project\n```\n\nInstall dependencies\n\n```bash\n  npm install\n\n  #or\n\n  yarn install\n```\n\nStart the server\n\n```bash\n  npm run dev\n\n  #or\n\n  yarn dev\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faimensahnoun%2Faimbridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faimensahnoun%2Faimbridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faimensahnoun%2Faimbridge/lists"}