{"id":17596268,"url":"https://github.com/saucepoint/foundry-arbitrum","last_synced_at":"2025-10-24T20:47:43.250Z","repository":{"id":113029595,"uuid":"603943129","full_name":"saucepoint/foundry-arbitrum","owner":"saucepoint","description":"Cross-chain message testing for Arbitrum with Foundry","archived":false,"fork":false,"pushed_at":"2023-03-22T14:42:38.000Z","size":188,"stargazers_count":66,"open_issues_count":0,"forks_count":11,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-18T21:31:19.987Z","etag":null,"topics":["arbitrum","cross-chain","foundry","l2","test"],"latest_commit_sha":null,"homepage":"","language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saucepoint.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2023-02-20T01:48:38.000Z","updated_at":"2025-02-20T22:15:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"f345b2c1-6f96-40df-b4da-626903b81e88","html_url":"https://github.com/saucepoint/foundry-arbitrum","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/saucepoint%2Ffoundry-arbitrum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saucepoint%2Ffoundry-arbitrum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saucepoint%2Ffoundry-arbitrum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saucepoint%2Ffoundry-arbitrum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saucepoint","download_url":"https://codeload.github.com/saucepoint/foundry-arbitrum/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251653360,"owners_count":21622111,"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":["arbitrum","cross-chain","foundry","l2","test"],"created_at":"2024-10-22T08:24:41.402Z","updated_at":"2025-10-24T20:47:43.170Z","avatar_url":"https://github.com/saucepoint.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# foundry-arbitrum\n\n\u003e 🚧 Currently experimental and actively being dogfooded\n\n\u003e 🚨 These utility mocks do not replace extensive testing (use of local nodes or testnet)\n\nReusable, mocked Arbitrum contracts to enable cross-chain message testing within the [foundry](https://book.getfoundry.sh) environment\n\n*Assuming the messages are **successful**, is the state changing as expected?*\n\n---\n\n## Usage\n\n```bash\nforge install saucepoint/foundry-arbitrum\n```\n\nIn the test files, inherit from `ArbitrumTest`\n\n```solidity\nimport {ArbitrumTest} from \"foundry-arbitrum/ArbitrumTest.sol\";\n\nimport {L1Contract} from \"../src/L1Contract.sol\";\nimport {L2Contract} from \"../src/L2Contract.sol\";\n\ncontract ExampleTest is Test, ArbitrumTest {\n    L1Contract l1Contract;\n    L2Contract l2Contract;\n\n    function setUp() public {\n        // Our L2 contract that will communicate with the L1 contract\n        // via ArbSys precompile at address(0x64) (mocked and etched in ArbitrumTest)\n        l2Contract = new L2Contract();\n\n        // Our L1 contract that will communicate with the L2 contract\n        // via inbox (mock deployed in ArbitrumTest)\n        l1Contract = new L1Contract(address(inbox), address(l2Contract));\n\n        l2Contract.setL1Target(address(l1Contract));\n    }\n\n    function testMessage() public {\n        // assert how *succesful* cross-chain messages would modify state\n        // (using the mocks implies that cross-chain messages are atomic \u0026 successful)\n    }\n}\n```\n\n---\n\nIntended for contracts relying on the Arbitrum `Inbox.sol` and the `ArbSys.sol` precompile:\n\nL1 Contract:\n```solidity\nimport {IInbox} from \"@arbitrum/nitro-contracts/src/bridge/IInbox.sol\";\n\n// Arbitrum Inbox (message handler)\nIInbox public inbox;\n\nconstructor(address _inbox, address _l2Target) {\n    inbox = IInbox(_inbox);\n    l2Target = _l2Target;\n}\n\n...\n\n// calls `handleMessageFromL1(uint256 num)` on L2\nbytes memory data = abi.encodeWithSelector(L2Contract.handleMessageFromL1.selector, number);\n\ninbox.createRetryableTicket{value: msg.value}(\n    l2Target, 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, data\n);\n```\n\nL2 Contract:\n```solidity\nimport {IArbSys} from \"./interfaces/IArbSys.sol\";\n\n// canonical precompile used to send messages to L1\nIArbSys constant arbsys = IArbSys(address(0x0000000000000000000000000000000000000064));\n\n...\n\n// calls `handleMessageFromL2(uint256 num)` on L1\nbytes memory data = abi.encodeWithSelector(L1Contract.handleMessageFromL2.selector, number);\narbsys.sendTxToL1(l1Target, data);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaucepoint%2Ffoundry-arbitrum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaucepoint%2Ffoundry-arbitrum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaucepoint%2Ffoundry-arbitrum/lists"}