{"id":15935378,"url":"https://github.com/dhruv-2003/mru-contract-hooks","last_synced_at":"2026-06-29T17:31:38.687Z","repository":{"id":255192453,"uuid":"848427394","full_name":"Dhruv-2003/mru-contract-hooks","owner":"Dhruv-2003","description":null,"archived":false,"fork":false,"pushed_at":"2024-08-28T14:07:08.000Z","size":221,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-09T04:13:03.200Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/Dhruv-2003.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":"2024-08-27T18:34:02.000Z","updated_at":"2024-08-28T14:07:12.000Z","dependencies_parsed_at":"2024-08-28T14:36:34.892Z","dependency_job_id":"7e52a45c-be21-4555-b094-956ba7b12b68","html_url":"https://github.com/Dhruv-2003/mru-contract-hooks","commit_stats":null,"previous_names":["dhruv-2003/mru-contract-hooks"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dhruv-2003%2Fmru-contract-hooks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dhruv-2003%2Fmru-contract-hooks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dhruv-2003%2Fmru-contract-hooks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dhruv-2003%2Fmru-contract-hooks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dhruv-2003","download_url":"https://codeload.github.com/Dhruv-2003/mru-contract-hooks/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247024155,"owners_count":20870940,"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":[],"created_at":"2024-10-07T03:41:43.922Z","updated_at":"2026-06-29T17:31:33.664Z","avatar_url":"https://github.com/Dhruv-2003.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Using contract hooks for a Stackr Micro Rollup\n\n## Overview\n\nThis guide provides basic instructions for utilizing contract hooks for a Stackr Micro Rollups (MRU) using a hook contract. This setup allows you to perform actions when a batch is submitted by the vulcan operator to the MRU's AppInbox contract.\n\nIn this example, the latest stateRootHash of the latest blocks is being sent to an Inbox on L2 i.e. optimism sepolia using a GMP bridge like Hyperlane.\n\n## Prerequisites\n\nBefore you begin this tutorial, please ensure you go through the following:\n\n- Basic understanding of the Stackr Micro rollup framework: [Zero to One](/build/zero-to-one/getting-started)\n- Familiarity with Solidity and smart contract deployment\n\n## How to use Hooks ?\n\n### Step 1 Creating up the hook contracts\n\nOnce you have your MRU setup ready with a template of your choice, Start by creating a hooks contract by inheriting the `IBaseHook.sol`.\n\nThen define the logic for the function `postSubmit` to perform the action you want to with the `_batch` data and `_submitter` address.\n\n```solidity\n contract Hook is IBaseHook {\n    /**\n     * post submit Hook that is called after the batch is submitted\n     * @param _batch the batch that was submitted\n     */\n    function postSubmit(\n        IAppInbox.Batch calldata _batch,\n        address\n    ) external override {\n        // Get the state root of the last block in that batch\n        bytes32 stateRoot = _batch.lastBlock.stateRoot;\n\n        // Send the state root\n        sendRootToOptimismViaHyperlane(stateRoot);\n    }\n}\n```\n\nIn this case, we utilize the Hyperlane Message bridge to send the state root from the `Sepolia` chain where the Appinbox to `Optimism Sepolia` where the `L2Inbox` will be deployed. We prepare the message by encoding it and also handling the fees payment for the bridging on both origin \u0026 destination chain.\n\n```solidity\n contract Hook is IBaseHook {\n    ....\n\n    /**\n     * Send the state root to the L2Inbox\n     * @param _rootHash the root hash to send\n     */\n    function sendRootToOptimismViaHyperlane(bytes32 _rootHash) public {\n        // Get a fee quote for the message\n        uint256 fee = quoteSendRoot(_rootHash);\n\n        // check is the contract has enough balance to pay the fee\n        if (address(this).balance \u003e= fee) {\n            // Send the message to the mailbox\n            mailbox.dispatch{value: fee}(\n                BRIDGE_DOMAIN,\n                TypeCasts.addressToBytes32(L2InboxAddress),\n                abi.encode(_rootHash)\n            );\n        }\n    }\n\n    /**\n     \u0026 quoteSendRoot to get the fee for sending the root hash to the L2Inbox\n     * @param _rootHash the root hash to send\n     */\n    function quoteSendRoot(\n        bytes32 _rootHash\n    ) public view returns (uint256 fee) {\n        fee = mailbox.quoteDispatch(\n            BRIDGE_DOMAIN,\n            TypeCasts.addressToBytes32(L2InboxAddress),\n            abi.encode(_rootHash)\n        );\n    }\n\n    ....\n}\n```\n\nSimilarly we have a simple contract on the L2 called `L2Inbox` which keeps the record of the latest state root hash on the L2 chains. You can refer the contract [here](https://github.com/Dhruv-2003/mru-contract-hooks/blob/main/src/contract/L2Inbox.sol)\n\n### Step 2 Adding the hook to appInbox\n\nOnce the contracts are deployed on both the chains, we have to add the Hook contract to our AppInbox, which can be done using the `@stackr/cli` as follow\n\n```bash\nnpx @stackr/cli@latest add hook \u003chook-contract-address\u003e\n```\n\nFor detailed info , you can refer to the doc [here](https://docs.stf.xyz/build/cli/add-hook)\n\nAnd that's it, you have successfully created the Hook logic that will be executed every time a batch is submitted to the AppInbox contract for your MRU.\n\n## Project structure\n\n```bash\n.\n├── .gitignore\n├── genesis-state.json\n├── src\n│   ├── index.ts ## -\u003e starting point, everything gets imported here.\n│   ├── server.ts ## -\u003e server setup if any in the example.\n│   ├── cli.ts ## -\u003e CLI interaction setup if any in the example.\n│   ├── contract ## -\u003e hook contracts\n│   │   ├── Hook.sol ## -\u003e Hook contract to send the stateRoot of the latest block to L2Inbox via GMP\n│   │   └── L2Inbox.sol ## -\u003e Inbox on L2 to keep record of the latest state Root of the MRU\n│   ├── stackr\n│       ├── machine.ts ## -\u003e preferred place to keep your State Machine(s) and export from\n│       ├── mru.ts ## -\u003e place to initialize your MicroRollup\n│       ├── schemas.ts ## -\u003e one place to create and export all schemas from\n│       ├── state.ts ## -\u003e file to define your State class, can be omitted if state is trivial.\n│       └── transitions.ts ## -\u003e one place to store all your transitions \u0026 hooks _(hooks can have seaprate hooks.ts file too.)_\n└── stackr.config.ts\n```\n\nNote: Some files are specific to certain examples, as mentioned in the tree above.\n\n## How to run?\n\n### Run using Node.js :rocket:\n\n```bash\nnpm start\n```\n\n### Run using Docker :whale:\n\n- Build the image using the following command:\n\n```bash\n# For Linux\ndocker build -t rollup:latest .\n\n# For Mac with Apple Silicon chips\ndocker buildx build --platform linux/amd64,linux/arm64 -t rollup:latest .\n```\n\n- Run the Docker container using the following command:\n\n```bash\n# If using SQLite as the datastore\ndocker run --env-file .env -v ./db.sqlite:/app/db.sqlite -p \u003cHOST_PORT\u003e:\u003cCONTAINER_PORT\u003e --name=rollup -it rollup:latest\n\n# If using other URI based datastores\ndocker run --env-file .env -p \u003cHOST_PORT\u003e:\u003cCONTAINER_PORT\u003e --name=rollup -it rollup:latest\n```\n\n## Playground Plugin\n\nTo leverage examples and test the SDK, you can use Stackr's Playground hosted at: [https://playground.stackrlabs.xyz](https://playground.stackrlabs.xyz).\n\nIn you application, add Playground by importing the following:\n\n```ts\nimport { Playground } from \"@stackr/sdk/plugins\";\n\nconst rollup = ...\nawait rollup.init();\n\nPlayground.init(rollup);\n// this will start a server at http://localhost:42069, which is taken as input by the Playground\n```\n\nFull instructions can be found at [here](https://docs.stf.xyz/build/plugins/playground)\n\n## Vulcan Explorer\n\nTo explore your submitted blocks and batches, you can use the Vulcan Explorer hosted at: [https://explorer.vulcan.stf.xyz/](https://explorer.vulcan.stf.xyz/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdhruv-2003%2Fmru-contract-hooks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdhruv-2003%2Fmru-contract-hooks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdhruv-2003%2Fmru-contract-hooks/lists"}