# Mina Schnorr Signature verification in EVM

**URL:** https://forums.minaprotocol.com/t/mina-schnorr-signature-verification-in-evm/6695
**Category:** Mina Navigator Proposals
**Created:** [November 25, 2024, 12:00am UTC](https://forums.minaprotocol.com/t/mina-schnorr-signature-verification-in-evm/6695 "2024-11-25T00:00:37Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![hgedia](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.minaprotocol.com/hgedia/32/1734_2.png) [@hgedia](https://forums.minaprotocol.com/u/hgedia)
#### Post date: [November 25, 2024, 12:00am UTC](https://forums.minaprotocol.com/t/mina-schnorr-signature-verification-in-evm/6695/1 "2024-11-25T00:00:37Z")

</div>

This topic is to discuss the proposal submitted by @br0wnD3v  
Please see below for the details of the proposal and discussion.

The proposer has requested the funds only to be distributed on a successful delivery.

**25th November, 2024**  
_Current status: Under Consideration._  
_Opened for community discussion on: 25th November, 2024._

**4th December, 2024**  
_Current status: Funded_  
_Funding Note : This proposal is approved for funding. These primitives are useful to enable cross-chain validation and can find greater usage in the ecosystem as building blocks. The risk is medium due to complexity and the budget is inline with the work proposed._

---

<div class="post-metadata">

### Author: ![br0wnD3v](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.minaprotocol.com/br0wnd3v/32/1966_2.png) [@br0wnD3v](https://forums.minaprotocol.com/u/br0wnD3v)
#### Post date: [November 25, 2024, 7:38am UTC](https://forums.minaprotocol.com/t/mina-schnorr-signature-verification-in-evm/6695/2 "2024-11-25T07:38:00Z")

</div>

# Title

### Mina Schnorr Signature verification in EVMs

## Project Background

We’re working on bringing Mina’s signature verification methods to EVMs, inspired by mina-signer. The goal is simple but powerful - allow developers to [verify signatures](https://github.com/o1-labs/o1js/blob/a0f0f349811fd812b27cb18bac74e8edecd48f9a/src/mina-signer/mina-signer.ts) native to Mina Protocol right on EVM chains through Solidity smart contracts. For this project it means verifying both [Field signatures](https://github.com/o1-labs/o1js/blob/9020799115e00ed2b89bbbd53977dca705e85ee3/src/mina-signer/mina-signer.ts#L170), [Message signatures](https://github.com/o1-labs/o1js/blob/9020799115e00ed2b89bbbd53977dca705e85ee3/src/mina-signer/mina-signer.ts#L206C3-L206C16) and also validating Mina’s native Public Keys (Pallas Points).

The groundwork is already [underway](https://github.com/Doot-Foundation/pallas_curve_verifier), and we’re excited to take this to the next level.

## Proposal Overview

### Problem

Right now, developers looking to work with Mina Schnorr Signatures on EVM chains are stuck - there’s no ready-to-use smart contract template for verifying signatures over the Pallas Pasta curve. This gap is holding back cross-chain innovation.

### Solution

We’re creating a clone of the current verification [methods](https://github.com/o1-labs/o1js/blob/a0f0f349811fd812b27cb18bac74e8edecd48f9a/src/mina-signer/mina-signer.ts), starting with the most crucial ones - verifyMessage and verifyFields. Based on community feedback, we’ll expand to cover other methods that developers find valuable.

### Impact

This project opens up some exciting possibilities:

**Cross-Chain Identity/Authentication:**

- Your Mina account becomes readable by Ethereum contracts
- One identity works across both chains (imagine having a matched Public Key pair on EVM/Mina)
- Sign once, use anywhere - your signature works on both chains
- Complements the existing [ECDSA verification](https://docs.minaprotocol.com/zkapps/o1js/ecdsa)

**Cross-Chain Logic Execution:**

- Smart contracts that react to verified Mina signatures
- Build trustless bridges without extra dependencies
- Simple plug-and-play verification for any developer

The best part? This lays the foundation for trustless bridges without relying on complex solutions. Developers can simply call our contracts and validate Mina native signatures.

### Audience

We’re building this for:

- Potential bridge developers
- Solo developers wanting to build cross-chain zkApps
- Anyone looking for an entry point to connect Mina and EVM chains

## Budget & Milestones

**Deliverables:** Production-ready EVM contracts that can verify both Mina Public Keys and Signatures (supporting fields and messages)

**Mid-Point:** Working verification on local Hardhat environment with basic test coverage

**Timeline:** 1 month

**Budget:** 10,000 MINA, broken down as:

- Developer Costs: 8000 MINA (core development)
- Deployment: 2000 MINA total
  - Initial deployments across chains
  - Comprehensive testing with edge cases
  - Buffer for potential hotfixes to meet deadlines

## Team Info

**Github:** [br0wnD3v (Brown Dev) · GitHub](https://github.com/br0wnD3v)

**Experience:** I’ve contributed to projects around Raffles, Perpetuals, RWAs and NFTs on Ethereum, and I’m deeply involved in Mina’s zkApp ecosystem as well as the community.

**Team:** Just me - Anuj Tanwar (br0wnD3v on Mina’s Discord), handling all development.

**Achievements:**

- Mina: Built [Doot](https://doot.foundation) (Oracle, in production) and [BMM](https://buymina.meme) (Memecoin Launchpad, near beta)
- Ethereum: Delivered whitelabel solutions for [POP](https://x.com/TradeOnParsa), [QuantumFair](https://www.quantumfair.com/raffleprofile?address=0xB6d62342d1da3Ca97c68943E3A5530ebf3d38f1E), and [Perped](https://perped.com)

## Risks & Mitigations

Let’s be honest - the main challenge is gas fees. Verification is computationally heavy, and right now, we can’t do it in a single contract call. This creates two issues:

1. Higher than ideal gas costs
2. Slightly complex developer experience

But we’ve got solutions:

- Deploy on gas-efficient L1s like Base
- Integrate MakerDAO’s [multicall](https://github.com/mds1/multicall/blob/main/README.md#usage) for better UX
- Provide copy-paste examples to make integration dead simple

## Sneak Peek

The following section is dedicated to displaying where we are at in the grand scheme of cloning the verification :

### Public Key Verification

We have already implemented a function call that can validate a Public Key (Pallas Point) in solidity, it can be found [here](https://github.com/Doot-Foundation/pallas_curve_verifier/blob/4fc303e392f85dac33611983bfd6c1fe7b07a760/contracts/CORE_PallasSignatureVerification.sol#L51). The relevant struct to represent a Public Key can be found [here](https://github.com/Doot-Foundation/pallas_curve_verifier/blob/4fc303e392f85dac33611983bfd6c1fe7b07a760/contracts/PallasTypes.sol#L8). The hardhat test can be found [here](https://github.com/Doot-Foundation/pallas_curve_verifier/blob/4fc303e392f85dac33611983bfd6c1fe7b07a760/test/Pallas.js#L28).

### Verification methods.

Taking `verifyFields()` from [mina-signer.ts](https://github.com/o1-labs/o1js/blob/a0f0f349811fd812b27cb18bac74e8edecd48f9a/src/mina-signer/mina-signer.ts#L170). It internally calls `verify()` which I have started working on in the CORE file as can be seen [here](https://github.com/Doot-Foundation/pallas_curve_verifier/blob/4fc303e392f85dac33611983bfd6c1fe7b07a760/contracts/CORE_PallasSignatureVerification.sol#L65).  
What I have in mind at the moment is as follows :

```auto
step1_prepareMessage + step2_prepareHashInput + step3_computeHash → hashMessage()
step4_computeHP + step5_negatePoint → scale(pk, e) and negate
step6_computeSG → scale(G, s) 
step7_finalAddition → add points
step8_verify → check x coordinate and y parity

```

At the time of writing this proposal we have the step\_1 ready and the Public Key verification completed.

### What the next weeks would look like?

After completing the `verifyFields()` implementation, I will start working on the steps related with `verifyMessage()` from [mina-signer.ts](https://github.com/o1-labs/o1js/blob/a0f0f349811fd812b27cb18bac74e8edecd48f9a/src/mina-signer/mina-signer.ts#L206C2-L208C4). The function in the source code internally calls `verifyStringSignature()` which in turn calls `verifyLegacy()`.

The `verifyLegacy()` is same as `verify()`, but using the “legacy” style of hash input packing. Considering that the source code explicitly [mentions](https://github.com/o1-labs/o1js/blob/a0f0f349811fd812b27cb18bac74e8edecd48f9a/src/mina-signer/src/signature.ts#L248) that the only difference is in the way of hash input packing, the majority of the main logic would remain same with some fine tuning here and there to the already existing methods implemented earlier in the `verify()` solidity implementation.

### What the DX would look like?

Our architecture follows a cascading pattern such that the only requirement would be to call the steps sequentially with a `verificationId` that is generated at the very first step (step\_1). A dedicated struct exists on The CORE file that keeps track of the steps and output of each step as can be seen [here](https://github.com/Doot-Foundation/pallas_curve_verifier/blob/4fc303e392f85dac33611983bfd6c1fe7b07a760/contracts/CORE_PallasSignatureVerification.sol#L20) Example -

```auto
step_5(id) -> step_5_output
step_6(id) -> step_6_output 

```

Again, a lot of the functions on the smart contract repository shared are not finalized and will be edited aggresively so please take everything mentioned above with a grain of salt. For example - A lot of functions on the smart contract expects one more param other than the `verificationId` which won’t be there in the final state of the project.

What I am certain about however is that **the final result would be a smart contract deployment that is a dot to dot clone of `verifyMessage()` and `verifyFields()` method from mina-signer under o1js.  
The developer will only supply Message/Fields, Signature, PublicKey and the rest would be carry forwarded with each step (to be called sequentially by the user i.e (`step_1 -> step_2`)). Ultimately returning `True` if the message/fields signed did originate from the claimed Public Key or `False` if not.**

The Smart Contract Interface would be along the following lines :

```auto
// verifyFields()
function step_1VF() external returns(uint256 verificationId) {}
function step_2VF(uint256 verificationId) external {}
function step_3VF(uint256 verificationId) external {}
...

// verifyMessage()
function step_1VM() external returns(uint256 verificationId) {}
function step_2VM(uint256 verificationId) external {}
function step_3VM(uint256 verificationId) external {}
...

```

## Bonus Note

This project is actually laying groundwork for something bigger - a feature called ‘Barter Swap’ (will be introduced under Doot) that’ll make ETH/MINA cross-chain swaps possible.  
Getting this funded helps push that vision forward too. Have a good day 😊.

---

<div class="post-metadata">

### Author: ![hgedia](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.minaprotocol.com/hgedia/32/1734_2.png) [@hgedia](https://forums.minaprotocol.com/u/hgedia)
#### Post date: [December 4, 2024, 10:33am UTC](https://forums.minaprotocol.com/t/mina-schnorr-signature-verification-in-evm/6695/3 "2024-12-04T10:33:06Z")

</div>

This proposal is approved for funding. These primitives are useful to enable cross-chain validation and can find greater usage in the ecosystem as building blocks. The risk is medium due to complexity and the budget is inline with the work proposed.

---

<div class="post-metadata">

### Author: ![br0wnD3v](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.minaprotocol.com/br0wnd3v/32/1966_2.png) [@br0wnD3v](https://forums.minaprotocol.com/u/br0wnD3v)
#### Post date: [December 17, 2024, 4:39am UTC](https://forums.minaprotocol.com/t/mina-schnorr-signature-verification-in-evm/6695/4 "2024-12-17T04:39:49Z")

</div>

Exciting News: verifyFields() and verifyMessage() Primitives Are Now EVM Compatible!

Dear Community,

I am thrilled to announce a significant milestone in the project’s development. The verifyFields() and verifyMessage() primitives, have been successfully made compatible with the Ethereum Virtual Machine (EVM). This achievement marks a crucial step forward and opens up new possibilities for integrating Mina ↔ EVM solutions.

Over the next several days, we will be focusing on optimizing the implementation of these primitives and finding ways to reduce the associated gas costs. Gas optimization is a critical aspect of smart contract development, as it directly impacts the usability and affordability of our solution for end-users. By minimizing gas consumption, we aim to provide a more efficient and cost-effective experience for those interacting with our smart contracts.

In addition to optimization efforts, we will be conducting extensive testing to ensure the stability, security, and reliability of the verifyFields() and verifyMessage() primitives within the EVM environment. Thorough testing is essential to identify and address any potential issues or vulnerabilities before deploying the solution to mainnet.

Once we are confident in the optimized implementation and have successfully completed the testing phase, we plan to deploy our smart contracts on the Ethereum mainnet and Arbitrum, a leading Layer 2 scaling solution for Ethereum. By targeting both Ethereum and Arbitrum, we aim to provide our community with flexibility and choice in terms of network selection, while also leveraging the benefits of Arbitrum’s scalability and lower transaction costs.  
The deployment related details will be added to the project’s README.md as well as will be reflected on Doot’s [Verify](https://www.doot.foundation/verify) page.

For those interested in exploring the technical details of our project, we invite you to visit our repository [here](https://github.com/Doot-Foundation/pallas_curve_verifier). There, you can find the source code, and other resources related to the verifyFields() and verifyMessage() primitives and their EVM implementation.

I extend my thanks to our community for their ongoing support and belief in the greater vision.

Stay tuned for further updates as we progress through the optimization and testing phases, and move closer to the mainnet deployment on Ethereum and Arbitrum. Together, we are building a more secure, efficient, and accessible future for blockchain-based applications.

Final Notes : We highly encourage the community to clone the repository and play around with the test/ files. Mix & match various inputs/signatures/publicKeys and if you stumble upon anything feel free to message me on discord (@br0wn\_d3v).

Best regards, Team [Doot](https://www.doot.foundation/)

---

<div class="post-metadata">

### Author: ![br0wnD3v](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.minaprotocol.com/br0wnd3v/32/1966_2.png) [@br0wnD3v](https://forums.minaprotocol.com/u/br0wnD3v)
#### Post date: [January 4, 2025, 6:37pm UTC](https://forums.minaprotocol.com/t/mina-schnorr-signature-verification-in-evm/6695/5 "2025-01-04T18:37:26Z")

</div>

# Pallas Protocol: Contract Deployment Update

We’re pleased to announce the successful deployment of our contracts on both Arbitrum Mainnet and Arbitrum Sepolia testnet.

## Deployed Contracts

### Arbitrum Sepolia (Testnet)

- PallasFieldsSignatureVerifier: [`0x2c393870Ed13b8DF0ed2861fBdC109cc2B9bd35F`](https://sepolia.arbiscan.io/address/0x2c393870Ed13b8DF0ed2861fBdC109cc2B9bd35F)
- PallasMessageSignatureVerifier: [`0x5790918c7db60C9c57dc1031FAf5f672EB22b4fC`](https://sepolia.arbiscan.io/address/0x5790918c7db60C9c57dc1031FAf5f672EB22b4fC)

### Arbitrum Mainnet

- PallasFieldsSignatureVerifier: [`0x643aDFd52cB8c0cb4c3850BF97468b0EFBE71b25`](https://arbiscan.io/address/0x643aDFd52cB8c0cb4c3850BF97468b0EFBE71b25)
- PallasMessageSignatureVerifier: [`0xB352B0dE8AF1e27a0fc927c1aD38BdB1bc4FCf40`](https://arbiscan.io/address/0xB352B0dE8AF1e27a0fc927c1aD38BdB1bc4FCf40)

## Quick Start

```bash
git clone https://github.com/Doot-Foundation/pallas_curve_verifier.git
cd core/
npm install

# Run verification scripts (Mainnet)
npx hardhat run scripts/verify_message.js --network arbitrum
npx hardhat run scripts/verify_fields.js --network arbitrum

```

Note:

- In `verify_message.js`, you can modify the `message` constant to your desired message as well as the `keypair` (Mina).
- In `verify_fields.js`, you can customize the `fields` array as well as the `keypair` (Mina) according to your requirements.
- Create a `.env` file in the core/ directory with your private key :

```bash
PRIVATE_KEY=your_private_key_here

```

Contracts are verified and available on Sourcify.

---

<div class="post-metadata">

### Author: ![0x471](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.minaprotocol.com/0x471/32/2097_2.png) [@0x471](https://forums.minaprotocol.com/u/0x471)
#### Post date: [January 11, 2025, 1:08am UTC](https://forums.minaprotocol.com/t/mina-schnorr-signature-verification-in-evm/6695/6 "2025-01-11T01:08:49Z")

</div>

Hi @br0wnD3v great work! The tests are passing but when I tried to run the scripts, had this error both for verifying fields and message. Here are the steps I followed:

1. `cd core && npm install`
2. `export PRIVATE_KEY=....`
3. **npx hardhat run scripts/verify\_fields.js --network arbitrum\_sepolia**

```auto
(node:4663) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
Error: could not decode result data (value="0x", info={ "method": "vfCounter", "signature": "vfCounter()" }, code=BAD_DATA, version=6.13.4)
    at makeError (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/utils/errors.ts:694:21)
    at assert (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/utils/errors.ts:715:25)
    at Interface.decodeFunctionResult (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/abi/interface.ts:916:15)
    at staticCallResult (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/contract/contract.ts:346:35)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
    at staticCall (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/contract/contract.ts:303:24)
    at Proxy.vfCounter (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/contract/contract.ts:351:41)
    at main (/Users/peterpan/rd/p/pallas_curve_verifier/core/scripts/verify_fields.js:18:14) {
  code: 'BAD_DATA',
  value: '0x',
  info: { method: 'vfCounter', signature: 'vfCounter()' },
  shortMessage: 'could not decode result data'
}

```

1. **npx hardhat run scripts/verify\_message.js --network arbitrum\_sepolia**

```auto
(node:4703) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
Error: could not decode result data (value="0x", info={ "method": "vmCounter", "signature": "vmCounter()" }, code=BAD_DATA, version=6.13.4)
    at makeError (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/utils/errors.ts:694:21)
    at assert (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/utils/errors.ts:715:25)
    at Interface.decodeFunctionResult (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/abi/interface.ts:916:15)
    at staticCallResult (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/contract/contract.ts:346:35)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
    at staticCall (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/contract/contract.ts:303:24)
    at Proxy.vmCounter (/Users/peterpan/rd/p/pallas_curve_verifier/core/node_modules/ethers/src.ts/contract/contract.ts:351:41)
    at main (/Users/peterpan/rd/p/pallas_curve_verifier/core/scripts/verify_message.js:18:16) {
  code: 'BAD_DATA',
  value: '0x',
  info: { method: 'vmCounter', signature: 'vmCounter()' },
  shortMessage: 'could not decode result data'
}

```

I suspect it might be related to the variable passed to `vfCounter` and `vmCounter` maybe some validation checks are missing.

---

<div class="post-metadata">

### Author: ![bot-coder101](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.minaprotocol.com/bot-coder101/32/2299_2.png) [@bot-coder101](https://forums.minaprotocol.com/u/bot-coder101)
#### Post date: [January 11, 2025, 4:39am UTC](https://forums.minaprotocol.com/t/mina-schnorr-signature-verification-in-evm/6695/7 "2025-01-11T04:39:23Z")

</div>

Hello @0x471 🙂 You need to make sure the `--network` you are passing in the cli and the smart contract address in the file matches, ie if you use `--network arbitrum_sepolia` make sure the contract address is the one for that network. There’s a list of contract addresses in DEPLOYMENTS.md and you can refer it to get what matches your network flag.

The files are by default using Arbitrum Mainnet’s addresses.  
You will see the address being used within the `.attach('ADDRESS')` step.

---

<div class="post-metadata">

### Author: ![0x471](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.minaprotocol.com/0x471/32/2097_2.png) [@0x471](https://forums.minaprotocol.com/u/0x471)
#### Post date: [July 23, 2025, 10:52am UTC](https://forums.minaprotocol.com/t/mina-schnorr-signature-verification-in-evm/6695/8 "2025-07-23T10:52:00Z")

</div>

OpenZeppelin announced ERC-7913 for arbitrary signature verification support today. This could be an interesting integration!

[https://x.com/OpenZeppelin/status/1947723960923394515](https://x.com/OpenZeppelin/status/1947723960923394515)
