{"id":28470535,"url":"https://github.com/hypercerts-org/protocol-periphery","last_synced_at":"2025-07-03T00:04:59.084Z","repository":{"id":288339554,"uuid":"967708029","full_name":"hypercerts-org/protocol-periphery","owner":"hypercerts-org","description":"Periphery contracts for the Hypercerts Protocol","archived":false,"fork":false,"pushed_at":"2025-05-02T06:02:35.000Z","size":43,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-07T09:35:29.955Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/hypercerts-org.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-16T21:55:51.000Z","updated_at":"2025-05-02T06:02:32.000Z","dependencies_parsed_at":"2025-04-17T11:14:54.607Z","dependency_job_id":"a508970e-e51c-4c40-933c-7ae2b62ff40b","html_url":"https://github.com/hypercerts-org/protocol-periphery","commit_stats":null,"previous_names":["hypercerts-org/protocol-periphery"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hypercerts-org/protocol-periphery","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypercerts-org%2Fprotocol-periphery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypercerts-org%2Fprotocol-periphery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypercerts-org%2Fprotocol-periphery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypercerts-org%2Fprotocol-periphery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hypercerts-org","download_url":"https://codeload.github.com/hypercerts-org/protocol-periphery/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypercerts-org%2Fprotocol-periphery/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263007042,"owners_count":23398750,"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":"2025-06-07T09:30:54.464Z","updated_at":"2025-07-01T17:30:48.847Z","avatar_url":"https://github.com/hypercerts-org.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hypercerts Periphery Contracts\n\n[![TEST](https://github.com/hypercerts-org/protocol-periphery/actions/workflows/test.yml/badge.svg)](https://github.com/hypercerts-org/protocol-periphery/actions/workflows/test.yml)\n[![Slither Analysis](https://github.com/hypercerts-org/protocol-periphery/actions/workflows/slither.yaml/badge.svg)](https://github.com/hypercerts-org/protocol-periphery/actions/workflows/slither.yaml)\n\n## Table of Contents\n\n- [Hypercerts Periphery Contracts](#hypercerts-periphery-contracts)\n\t- [Table of Contents](#table-of-contents)\n\t- [BatchTransferFraction](#batchtransferfraction)\n\t\t- [Implementation](#implementation)\n\t\t- [Usage](#usage)\n\t\t- [Deployments](#deployments)\n\n## BatchTransferFraction\n\n### Implementation\n\n```mermaid\nsequenceDiagram\nactor o as Owner\nparticipant h as Hypercert Minter Contract\nparticipant b as BatchTransfer Contract\nactor r as Recipients\n\no -\u003e\u003e h: call splitFraction()\nh -\u003e\u003e h: split fraction\no -\u003e\u003e h: call setApprovalForAll()\no -\u003e\u003e b: call batchTransfer()\ncritical will be reverted if the owner is not the owner of each fractions\nb --\u003e h: check if caller is the owner of fraction\nb -\u003e\u003e r: safeTransferFrom()\nend\n\n```\n\n```solidity\n    /// @dev msg.sender must be the owner of all the fraction IDs being transferred\n    /// @dev msg.sender must have approved the contract to transfer the fractions\n    /// @dev The length of recipients and fractionIds must be the same\n    /// @param data The encoded data containing the recipients and fraction IDs\n    function batchTransfer(bytes memory data) external {\n        require(data.length \u003e 0, INVALID_DATA());\n        TransferData memory transferData = abi.decode(data, (TransferData));\n        require(transferData.recipients.length == transferData.fractionIds.length, INVALID_LENGTHS());\n        _batchTransfer(transferData.recipients, transferData.fractionIds);\n    }\n\n    /// @notice Transfers fractions to multiple recipients\n    /// @dev The length of recipients and fractionIds must be the same\n    /// @dev The caller must be the owner of all the fraction IDs being transferred\n    /// @param recipients The addresses of the recipients\n    /// @param fractionIds The IDs of the fractions to be transferred\n    function _batchTransfer(address[] memory recipients, uint256[] memory fractionIds) internal {\n        uint256 length = recipients.length;\n        for (uint256 i = 0; i \u003c length; i++) {\n            address recipient = recipients[i];\n            uint256 fractionId = fractionIds[i];\n            require(hypercertToken.ownerOf(fractionId) == msg.sender, INVALID_CALLER(msg.sender));\n\n            hypercertToken.safeTransferFrom(msg.sender, recipient, fractionId, 1, \"\");\n        }\n        emit BatchFractionTransfer(msg.sender, recipients, fractionIds);\n    }\n```\n\n### Usage\n\n\u003e [!important]\n\u003e make sure you own the hypercerts.\n\u003e\n\u003e most of hypercerts have **CREATOR ONLY** [transfer restriction](https://github.com/hypercerts-org/hypercerts-protocol/blob/a606868b1f8d0502124428c45a985002170e6fca/contracts/src/protocol/interfaces/IHypercertToken.sol#L9-L19), so make sure you created the hypercerts as well.\n\n1. Encode data with [ethers](https://docs.ethers.org/v5/api/utils/abi/coder) or [viem](https://viem.sh/docs/abi/encodeAbiParameters#encodeabiparameters).\n\n   with ethers\n\n   ```javascript\n   import { ethers } from \"ethers\";\n   ...\n   const recipients = [\"0x123....\", \"0x456....\"];\n   const fractionIds = [BigInt(\"23894....5301\"), BigInt(\"23894....5302\")];\n\n   const encodedData = ethers.AbiCoder.defaultAbiCoder().encode(\n   \t[`tuple(address[], uint256[])`],\n   \t[[recipients, fractionIds]]\n   );\n   console.log('Encoded Data:', encodedData);\n    // e.g. Encoded Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000006aa005386f53ba7b980c61e0d067cabc7602a620000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000c000000000000000000000000000000002\n   ```\n\n   with viem\n\n   ```javascript\n   import { encodeAbiParameters } from 'viem';\n\n   ...\n   const recipients = [\"0x123....\", \"0x456....\"];\n   const fractionIds = [BigInt(\"23894....5301\"), BigInt(\"23894....5302\")];\n   const abiParams = [\n    {\n      type: 'tuple',\n      components: [{ type: 'address[]' }, { type: 'uint256[]' }],\n    },\n   ];\n   const encodedData = encodeAbiParameters(abiParams, [\n    [recipients, fractionIds],\n   ]);\n   ```\n\n2. In the HypercertsMinter contract on the chain where you want to execute batch transfer, call [setApprovalForAll (0xa22cb465)](https://optimistic.etherscan.io/address/0x822F17A9A5EeCFd66dBAFf7946a8071C265D1d07#writeProxyContract#F17) to approve the batchTransfer contract to send hypercerts.\n   `operator == BatchTransfer contract address, approved == true`\n\n3. call batchTransfer function\n\n### Deployments\n\n| chain            | chainId  | address                                                                                                                          |\n| ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |\n| Sepolia          | 11155111 | [0x59e07f1cc8eb8eca2703179a7217673318a0fe47](https://sepolia.etherscan.io/address/0x59e07f1cc8eb8eca2703179a7217673318a0fe47)    |\n| Base Sepolia     | 84532    | [0x3C0FaAA04078d715BB05Af82Ca99c41623AeC5Ae](https://sepolia.basescan.org/address/0x3C0FaAA04078d715BB05Af82Ca99c41623AeC5Ae)    |\n| Arbitrum Sepolia | 421614   | [0x0fCCa2bAd3103934304874E782450688B7a044B0](https://sepolia.arbiscan.io/address/0x0fCCa2bAd3103934304874E782450688B7a044B0)     |\n| Optimism         | 10       | [0xf77e452ec289da0616574aae371800ca4d6315b1](https://optimistic.etherscan.io/address/0xf77e452ec289da0616574aae371800ca4d6315b1) |\n| Base             | 8453     | [0xc4aEB039BC432343bf4dB57Be203E0540d385a18](https://basescan.org/address/0xc4aEB039BC432343bf4dB57Be203E0540d385a18)            |\n| Arbitrum         | 42161    | [0x8b973c408c2748588b3ECFfDA06D670819FbEb1D](https://arbiscan.io/address/0x8b973c408c2748588b3ECFfDA06D670819FbEb1D)             |\n| Celo             | 42220    | [0xB64B7e4793D72958e028B1D5D556888b115c4c3E](https://celoscan.io/address/0xB64B7e4793D72958e028B1D5D556888b115c4c3E)             |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhypercerts-org%2Fprotocol-periphery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhypercerts-org%2Fprotocol-periphery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhypercerts-org%2Fprotocol-periphery/lists"}