{"id":19610849,"url":"https://github.com/onflow/flow-cadence-eth-utils","last_synced_at":"2026-03-06T14:33:37.293Z","repository":{"id":191435336,"uuid":"673488132","full_name":"onflow/flow-cadence-eth-utils","owner":"onflow","description":null,"archived":false,"fork":false,"pushed_at":"2023-10-31T23:17:17.000Z","size":169,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-26T17:27:10.883Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Cadence","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/onflow.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":"2023-08-01T18:33:22.000Z","updated_at":"2024-02-17T21:31:54.000Z","dependencies_parsed_at":"2024-11-11T10:34:36.028Z","dependency_job_id":null,"html_url":"https://github.com/onflow/flow-cadence-eth-utils","commit_stats":null,"previous_names":["onflow/flow-cadence-eth-utils"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/onflow/flow-cadence-eth-utils","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onflow%2Fflow-cadence-eth-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onflow%2Fflow-cadence-eth-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onflow%2Fflow-cadence-eth-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onflow%2Fflow-cadence-eth-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/onflow","download_url":"https://codeload.github.com/onflow/flow-cadence-eth-utils/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onflow%2Fflow-cadence-eth-utils/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30180672,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T12:39:21.703Z","status":"ssl_error","status_checked_at":"2026-03-06T12:36:09.819Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2024-11-11T10:34:04.890Z","updated_at":"2026-03-06T14:33:37.263Z","avatar_url":"https://github.com/onflow.png","language":"Cadence","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ethereum Signature Verification with Cadence\n\nThis guide will show you how to generate a public key, a signature, and a message that can be passed into a Cadence smart contract. This can be achieved using Ethereum JavaScript libraries such as ethers.js or any other Web3 API.\n\n## Requirements\nThis function depends on the following libraries:\n\n- `ethers.js`: Ethereum's JavaScript library used for interacting with Ethereum's network and its smart contracts.\n- `@onflow/fcl`: Flow's JavaScript library used for interacting with Flow's network and its smart contracts.\n\n\n## Example\n\n```js\ntry {\n    const provider = new ethers.providers.Web3Provider(window.ethereum, \"any\");\n   \n    // Send a request to access the user's Ethereum accounts\n   \tawait provider.send(\"eth_requestAccounts\", []);\n   \n    const signer = provider.getSigner();\n\n    // Define a string message to be signed\n    const toSign = `Hello Cadence World!`\n\n    const ethSig = await signer.signMessage(toSign);\n\n    // Remove the '0x' prefix from the signature string\n    const removedPrefix = ethSig.replace(/^0x/, '');\n   \n    // Construct the sigObj object that consists of the following parts\n    let sigObj = {\n   \t \tr: removedPrefix.slice(0, 64),  // first 32 bytes of the signature\n    \ts: removedPrefix.slice(64, 128),  // next 32 bytes of the signature\n    \trecoveryParam: parseInt(removedPrefix.slice(128, 130), 16),  // the final byte (called v), used for recovering the public key\n  \t};\n\n    // Combine the 'r' and 's' parts to form the full signature\n    const signature = sigObj.r + sigObj.s;\n\n    // Construct the Ethereum signed message, following Ethereum's \\x19Ethereum Signed Message:\\n\u003clength of message\u003e\u003cmessage\u003e convention.\n    // The purpose of this convention is to prevent the signed data from being a valid Ethereum transaction\n    const ethMessageVersion = `\\x19Ethereum Signed Message:\\n${toSign.length}${toSign}`;\n\n    // Compute the Keccak-256 hash of the message, which is used to recover the public key\n  \tconst messageHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(ethMessageVersion));\n\n    const pubKeyWithPrefix = ethers.utils.recoverPublicKey(messageHash, ethSig);\n\n    // Remove the prefix of the recovered public key\n    const pubKey = pubKeyWithPrefix.slice(4);\n\n    // The pubKey, toSign, and signature can now be used to interact with Cadence\n\n} catch (err) {\n  \tconsole.error(err);  // Log any errors\n}\n\n```\n\nThis function does the following:\n\n1. **Set up an Ethereum provider**: Uses window.ethereum, which is provided by MetaMask or other Ethereum wallet extensions.\n2. **Request account access**: Asks the user to unlock their Ethereum wallet.\n3. **Get a signer**: A signer is an Ethereum account that can sign transactions and messages.\n4. **Create a message to sign**: For this example, the message is Hello Cadence World!.\n5. **Sign the message**: The signer signs the message.\n6. **Clean up the signature**: Removes the '0x' prefix from the signature string.\n7. **Create a signature object**: Constructs an object with the signature components.\n8. **Create the full signature**: Combines the 'r' and 's' components to form the full signature.\n9. **Format the message**: Follows Ethereum's signed message convention to prevent the signed data from being a valid Ethereum transaction.\n10. **Hash the message**: Computes the Keccak-256 hash of the message, which will be used to recover the public key.\n11. **Recover the public key**: Uses the hashed message and the signature to recover the public key.\n12. **Clean up the public key**: Removes the prefix of the recovered public key.\n\n\n\n## Usage\n\nYou can use this function in any situation where you need to authenticate and verify an Ethereum account in Cadence.\n\n\n```js\nawait fcl.query({\n    cadence: `\n      import ETHUtils from \u003cADDRESS_HERE\u003e\n\n      pub fun main(hexPublicKey: String, hexSignature: String, message : String): Bool {\n          return ETHUtils.verifySignature(hexPublicKey: hexPublicKey, hexSignature: hexSignature, message: message)\n      }\n    `,\n    args: (arg, t) =\u003e [arg(pubKey, t.String), arg(signature, t.String), arg(toSign, t.String)],\n  });\n```\n\nThis example queries a Cadence smart contract to verify the Ethereum signature.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonflow%2Fflow-cadence-eth-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonflow%2Fflow-cadence-eth-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonflow%2Fflow-cadence-eth-utils/lists"}