# EVM Protocol Adapter

**URL:** <https://forum.anoma.net/t/evm-protocol-adapter/891>\
**Category:** RM\
**Created:** [December 7, 2024, 3:32pm UTC](https://forum.anoma.net/t/evm-protocol-adapter/891 "2024-12-07T15:32:13Z")\
**Posts on this page:** 6\
**Page:** 2

<div class="post-metadata">

**Author:** ![cwgoes](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.anoma.net/cwgoes/32/22_2.png) [@cwgoes](https://forum.anoma.net/u/cwgoes)\
**Post date:** [January 30, 2025, 1:45pm UTC](https://forum.anoma.net/t/evm-protocol-adapter/891/21 "2025-01-30T13:45:59Z")

</div>

> [@Michael](#):
>
> Working on protocol adapter draft, I realized that the settlement-only protocol adapter can only handle EVM state reads (or, more generally speaking, EVM calls with return arguments) if the returned data obtained during transaction execution is still the same as during proof generation time. If the data differed, logic and compliance proofs would become invalid.

Yes, that makes sense.

> [@Michael](#):
>
> Probably, this isn’t an issue for the full protocol adapter.

It shouldn’t be – for the full protocol adapter we’d compute the state reads in the transaction function (if we expect them to change) and create the proofs therein (so the proofs would be valid).

---

<div class="post-metadata">

**Author:** ![xuyang](https://avatars.discourse-cdn.com/v4/letter/x/c68b51/32.png) [@xuyang](https://forum.anoma.net/u/xuyang)\
**Post date:** [February 5, 2025, 10:14am UTC](https://forum.anoma.net/t/evm-protocol-adapter/891/22 "2025-02-05T10:14:35Z")

</div>

We have [accelerated cryptographic primitives](https://dev.risczero.com/api/zkvm/precompiles) in risc0 circuits.  
secp256k1 and ECDSA signature seem like a good candidate. We can use `ecRecover` to check the binding signature. To build the binding public key, we also need `ecAdd` over secp256k1 in Solidity. However, we don’t have the pre-compiled version of ecAdd for secp256k1. Using the non-precompiled version might cost a bit more.

---

<div class="post-metadata">

**Author:** ![Michael](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.anoma.net/michael/32/434_2.png) [@Michael](https://forum.anoma.net/u/Michael)\
**Post date:** [February 5, 2025, 10:54am UTC](https://forum.anoma.net/t/evm-protocol-adapter/891/23 "2025-02-05T10:54:23Z")

</div>

In our last meeting, you, @cwgoes, mentioned that we should add an `FFICall` field to `Action` and `Logic.Instance`. Just thinking about the EVM for now, it could look as follows:

```auto
FFICall {
  address wrapperContract;
  bytes input; // (bytes4 selector, bytes calldata)
  bytes ouput;
}

```

IIRC, you also said that from an action, we could extract a list of kinds and check that for all FFI calls a corresponding wrapper (contract) resource is also included in the action.  
Wrapper resources could then enforce certain constraints, e.g., that the FFI call was authorized by someone or that some state-corresponding resources (e.g., ERC20 token resources) are part of the action.

However, I think we lack information allowing the RM to know which `kind`s to look for.  
IMO, while there could be a predefined _wrapper resource label_ (e.g., matching the `wrapperContract` field in `FFICall`) but there can’t be a single, general, and predefined _wrapper resource logic_.  
IMO, the `logic` of the wrapper contract resources will vary for different EVM state changes:

- For calls to ERC20 contracts, the wrapper contract resource logic could require one ERC20 resource of a specific kind to be consumed and another one to be created.
- Other wrapper contract resources could have different logics, e.g., requiring more than two resources to be consumed and created or signature checks to happen.  
Since the logic isn’t predefined, the RM cannot know the wrapper resource kind from `FFICall` info as shown above.

Providing the wrapper resource `logic` or `kind` as part of the FFICall field could work.

```auto
FFICall' {
  address wrapperContract;
  bytes32 wrapperResourceKind;
  bytes input;
  bytes ouput;
}

```

This would mean that the protocol adapter contract has to ensure the correspondence between the wrapper resource kind in the `FFICall` field and the wrapper contract (e.g., by requiring the wrapper resource kind to be immutably stored in `wrapper contract`). Setting this up will probably require some tricks, i.e., deterministic deployment.

Ultimately, the legitimacy of resources corresponding to EVM state comes from their kind being bound to the wrapper resource, which in turn must be bound to the wrapper contract.

---

<div class="post-metadata">

**Author:** ![cwgoes](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.anoma.net/cwgoes/32/22_2.png) [@cwgoes](https://forum.anoma.net/u/cwgoes)\
**Post date:** [February 6, 2025, 6:05am UTC](https://forum.anoma.net/t/evm-protocol-adapter/891/24 "2025-02-06T06:05:30Z")

</div>

> [@Michael](#):
>
> In our last meeting, you, @cwgoes, mentioned that we should add an `FFICall` field to `Action` and `Logic.Instance`.

Yes, I think we should do this (/cc @vveiln for context). In the canonical RM types, this would be an opaque `bytes`. For the EVM protocol adapter, we can decode it as a specific structure such as the one you propose.

> [@Michael](#):
>
> However, I think we lack information allowing the RM to know which `kind`s to look for.  
> IMO, while there could be a predefined _wrapper resource label_ (e.g., matching the `wrapperContract` field in `FFICall`) but there can’t be a single, general, and predefined _wrapper resource logic_.

In order to know which kinds to look for, we simply consult the wrapper contract \<\> resource kind mapping, based on the FFI calls actually performed by the transaction. The binding between a wrapper contract (on the EVM) and a wrapper resource kind _must_ be fixed. I think that this is similar to what you’re proposing, except that I don’t think we need to store the `wrapperResourceKind` in the FFI call, since we can simply look it up from the wrapper contract.

---

<div class="post-metadata">

**Author:** ![cwgoes](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.anoma.net/cwgoes/32/22_2.png) [@cwgoes](https://forum.anoma.net/u/cwgoes)\
**Post date:** [February 11, 2025, 9:37am UTC](https://forum.anoma.net/t/evm-protocol-adapter/891/25 "2025-02-11T09:37:39Z")

</div>

Notes from discussion with @vveiln @Michael:

- Put the FFI call field in app data (exact formatting TBD)
- Achieve the kind check with the resource logic proof (exact formatting TBD)

@vveiln to write this up in a forum post response.

---

<div class="post-metadata">

**Author:** ![vveiln](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.anoma.net/vveiln/32/60_2.png) [@vveiln](https://forum.anoma.net/u/vveiln)\
**Post date:** [February 11, 2025, 1:30pm UTC](https://forum.anoma.net/t/evm-protocol-adapter/891/26 "2025-02-11T13:30:38Z")

</div>

> We assume that all resources are shielded

- protocol adapter ( PA ) contract - main RM contract
- application contracts - exist
- wrapper contracts (WC) - connect application contracts to the RM world; for each wrapper contract there is a corresponding wrapper resource (WR) kind and PA is aware of the mapping

Each WR is associated with an FFI call that the PA is supposed to perform. In order to do that,

1. PA needs to know where to get these FFI calls
2. verify that the calls are authorised by the corresponding WC

### FFI calls in app data

We store FFI calls in `Action.AppData` in a fixed location. Currently, `AppData` is partitioned by tags - each partition corresponds to the public inputs of the logic of the resource with the corresponding tag:  
`tag -> instance`, with instance represented as a list of pairs `(bitstring, deletion_criterion)`

One option to have a standardised location for the FFI calls is to have them the first argument in the list. Alternatively, we can change the AppData structure to be a map and use a standard FFI key to store the FFI call value.

Q: how to tell the difference between WR putting their FFI calls in appData vs non-WR having FFI calls in their AppData?  
A: for that we need to verify that the resource associated with the FFI call is of the WC kind. To do that, we drop function privacy for WR (we don’t lose anything because WC are public anyway) and perform the kind check as described below

### Kind check

A logic of any application must have the self resource tag as a public input and resource object as private input - this is true for any logic. In addition to that, we require WR to have an **extra mandatory public input - WR kind** , and a **new mandatory constraint** checking that the input kind is the self resource kind:

- public\_input.kind = h\_{kind}(private\_input.label, private\_input.logic)

Here is why it works:

- bind FFI call to a kind:
  - in the new logic constraint, we bind the publicly known `kind` to the private resource object, proving that this is indeed the kind of the currently checked resource
  - having the logic constraints public (i.e., no function privacy for WR) allows us to verify that this constraint is checked
  - logic also probably should verify the FFI call associated with the resource

- bind kind to WC
  - having the mapping between the kinds and WCs allows the PA to know that the logic of the corresponding WR was checked

PA can go through the `AppData`, find the FFI calls, verify the logic proofs associated with them, and execute the FFI calls.

**TL; DR**

- no function privacy for WR
- kind is a mandatory public input for WRL
- an extra mandatory constraint in WRL verifying kind against the resource object
- FFI calls are stored in a standardized location in `appData`

**TO DO:**

- standardize the location for FFI calls in `appData`. I’ll think if it makes sense to turn this substructure into a map (instead of a list), and if yes, we just need to define the key for FFI calls

[Previous page](https://forum.anoma.net/t/evm-protocol-adapter/891.md?page=1)
