New Ethereum talks, every Monday. The week's conference uploads by event, in your inbox.

Loading player…

Confidential Solidity With Co-Processors & ERC-7984 | Aryeh Greenberg - OpenZeppelin

Ethereum DenverMon, Mar 9, 2026, 12:00 AM

Aryeh has been deeply involved in the crypto space since 2020. Over the years, he has focused on protocol engineering at the following organizations: Compound Labs, OpenSea, PartyDao, and OpenZeppelin. He has also played crucial roles within the Compound Dao including building governor bravo.

Transcript

After a very good presentation on intense by LiFi and Philillip, now we have Arya Greenberg who will be talking about confidential solidity and ERC 7984 on this topic. I'm really excited because as we move a little bit closer towards confidential comput and privacy, this is going to be really really interesting. Arya, are you ready? Over to you. All the best.

Thank you so much for the intro. I'm Ari Greenberg. I'm a developer at Open Zeppelin and I'll be speaking about confidential solidity with co-processors and ERC 7984. Uh before I start, I want to get a show of hands of how many people here have written smart contracts before in general. Okay, almost everyone.

And how many people have written smart contracts using confidentiality or privacy in some way? Okay, very few. Good good context. Okay. So, we'll start off with uh what we're going to be going over with over here.

We're going to start over start off with co-processors just in general so that you can understand the tech and how this is working which is really crucial when you're building confidential contracts using co-processors. Uh then we'll get into how solidity interacts with it. Uh the token standard that we at Open Zeppelin have built along with Zama and Inco ERC 7984. And then we'll do a quick demo using the Open Zeppelin library and deploy a token and interact with it. Um, so to start off, what is a co-processor?

In traditional computing, a co-processor assists the CPU, right? The CPU gets a task and the CPU is like, do I have someone else here who can help me out do it a little quicker? So, you'll have dedicated units which are helping the CPU accelerate tasks. The CPU will delegate a task that comes in to, for example, the FPU uh floating point unit uh or some others. some examples above.

When we get to the EVM, it's basically the same thing, right? The same concept carrying over the EVM will delegate via smart contracts to a co-processor which is dedicated to doing a specific use case and will either accelerate it or make something that's not possible possible. Um, so co-processors generally will monitor for events or other onchain activities and trigger computation based on that. So your contract can emit a specific event and if you have a co-processor wired up to it, it will be looking for that and do something based on it. Um and then the EVM can accept information back from a co-processor via some sort of to attestation generally signatures from maybe an MPC network or uh ZK proofs something like that.

Um so how do these co-processors enable confidentiality? There's two main ways that we have been working with two main uh systems for these co-processors uh which are FHE fully homorphic encryption. Uh so with FHE you have cippher text that are quite large those are stored on the co-processor and you'll have handles that there's a mapping of handle to cipher text and on the co-processor it will do the FHE operation. None of that actually happens on Ethereum. um and that makes it relatively cheap to do on Ethereum where all the excess uh computation is delegated to the co-processor.

Another method is uh TEES where the co-processor is a trusted execution environment uh with a private key stored inside the co-processor. Um Inko is working on a solution using TEES and uh decrypts, operates and then re-encrypts on the co-processor. Um so all that is opaque to the EVM and the outside world. Um so before we get any further uh we just want to define what confidentiality is here uh sometimes it's a little confusing uh in a general public transfer right on Ethereum in the EVM land uh you always know who's involved and the amounts right so the from the two and the amount is public when we're talking about confidentiality what we mean is that amounts are always obsc like obfiscated so you're not able to figure out the amount unless you're involved in the transaction But other people know who the is involved parties in the transaction. And this is because we don't have stealth addresses.

We're still using the Ethereum accountbased um storage management. So you'll have mappings of your addresses and when that changes, everyone knows that changes, but what it's changing to people can't see. Okay. So we've defined a little bit about co-processor. Um now let's get into the specifics of how uh you'll interact with them using Solidity.

So for any code examples here we're using uh the Zama FHE FHEVM examples just for simplicity uh the primitives will carry over to other uh co-processors pointerbased uh solidity paradigms. So over here on top we have the integer representation of 64 right unsigned integer oh no 100 my bad and on the bottom we have encrypted integer unsigned integer for 100. So what's the bottom value? We'll get to that later. What's the top value?

Right? Pretty simple hexodimal. Um so value representation is a bit different. Now if we want to do an operation right within solidity simple we have bitwise addition. So 100 plus 100 equals 200.

Um but with encrypted integers right what's the answer to this? I don't really know. Technically, yeah, I can do bitwise addition. Um, but certainly that is not the solution, right? 100 plus 100 with handles is not the bitwise addition.

So, let's get into what these handles actually are. Um, so the handles are a handle to external data, uh, a pointer to somewhere else. So, you can kind of think of it as a storage slot. You have that in storage, but you don't know what the value is unless you fetch it. And the way you fetch it is a little bit different.

Um so the first 21 bytes is entropy which is just a hash. Uh the second the next one is one bite of the index which isn't so important right now. We have eight bytes for the chain ID, one bite for the type and one bite for the version. So this is what our contracts can see on chain. So like what do you think you can do with that?

You can't really do much with that on your own uh without help from the co-processor, right? We don't know the value. If you see a long string of bits that represents 100, you you have no way of getting that. You're not able to branch. You're not able to revert based on it.

Um and you can't use native operations. You can't do right just uh you'll add with those. It doesn't mean anything. Um so the way that it works is generally you'd be calling a single contract which represents the co-processor on the chain. So for example on Ethereum you would have an executor contract and on that contract you'll have a bunch of exposed functions for example add subtract multiply divide and you will pass handle A handle B and it will deterministically produce handle C and it will emit an event of this operation and the co-processor will be watching it and the co-processor will observe that I want to add handle A and B and the result is C.

So the co-processor will look in the mapping it will see handle A results in cipher text A handle B results in cipher text B and let me add them then I get cippher text C and I hand and I store it in the co-processor at handle C. Um so that's that's how the co-processor will react. That's how solidity will interact with the co-processor. Um and then if you actually want to uh figure out what the value is, you have to send a request to the co-processor for decryption and then the co-processor will send back uh the result along with um an attestation generally a signature. Um so who can actually use these handles right so we have confidentiality and I said right you can decrypt it you can operate on it but who's able to do that since it's confidential obviously not everyone can so we have the concept of an ACL and it acts as control list um and to utilize a handle in any way whatsoever you must be permitted explicitly on the ACL um so any account with permission on the ACL can do any operation can decrypt and it also can pass on allowance to another user Um, just for some context, if you bring a new value into the confidential realm, you generate a zk proof that you know what that value is and then you get added to the ACL for that value.

So, uh, no one can get access to a value without knowing what it is. But once you know what it is, then you have access and you can give others access. Okay. So, we've built on these, we we've kind of defined the primitives in high level. Um, now how do we build a token using these primitives?

Um so at open zeppelin uh along with others we built ERC 7984 which is a token that's optimized for using handles for transfers events all of it is using handles um so right that means that it's uh agnostic to what the actual implementation is you can use any co-processor implementation with it meaning it can use be utilized for FHE confidentiality TE confidentiality or other schemes or even token systems that aren't confidential but gain from pointerbased to storage. Um so again it's fungeible like ERC20 and it enables confidential uh onchain transactions. The addresses are always public uh while the balances involved in events and balance on chain is private. Um, so how do we do this? Right, getting back to the concept of handles, defining value representation, defining operations, right?

ERC20, ERC 721, you always agree on how your values are represented, right? Unsigned integers, you always agree on how you're operating on them. Addition, subtraction, simple, bitwise. Uh, with ERC 7984, we diverge from that, right? Um, so we redefine value representation.

Again, handles can be anything you want. And we redefine operations. Um, and this brings up some interesting topics where, right, if you have multiple tokens, you have different confidential contracts that don't agree on value representation that don't agree on operations, how do they interact? And the answer is that they can't. So, in the realm of confidentiality, you have a lot of uh different ways that contracts can be interacting.

And if they don't interpret operations and values the same, you basically need to bridge between them. Um, we built a lot of extensions at Open Zeppelin. If you want to experience 7984, you can look at our repo and build with these extensions. Um, and then without further ado, I'll jump into a quick little demo here. If anyone wants to follow along, you can follow along with the the whole thing.

We're going to use Open Zeppelin wizard and then a little command line interface to help you interact with the uh token that we're going to deploy. So, oh, the internet's working. Okay, so I recorded this in case the internet wasn't working, but uh we go to wizard.openzeppelin.com, click on confidential, and we have a section for the 7984.

Name the token, specify a symbol. Um, and by the way, this is actually released this week. So, this is all brand new uh tech. And if you want to deploy a confidential contract, well, you'll see it right now. We'll do a prement of 10,000 tokens to ourselves.

And, uh, we'll leave the rest configured as is. We'll be using Zama. Uh, we'll open it in Remix and follow these instructions. Uh we're going to add the remapping as the wizard described. So remapping.

txt and paste the remappings that wizard gave us. Save that and go back to contracts to compile. Now we'll head over to deploy the contract. uh the Ethereum with an arrow and we'll select our injected provider MetaMask and deploy to Sapoleon. Um we have to specify a receiver in the constructor.

So that will send to the deployer address. And we'll wait for a second for this to be deployed. Once we get the contract address, we'll pull up the command line interface which is a separate repo that was on the second QR code over there. Um, again, right, these are all handles that are encrypted. So, you need some tooling to actually see what's going on with them.

So, you can see the command line interface pasted in the token address and it's fetching the deployer balance, decrypting the balance. The handle over there is the balance that's stored onchain. And you can see so we have 10,000 ETH Denver in this wallet. Um, and now we'll go to do a transfer. Um, so the transfer parameters is the token, the amount, and the two address.

And we'll encrypt this amount offchain. Right? So we generate a new handle and a proof an input proof which verifies that we know the value of this handle so we can utilize it onchain and in a second I'll show the actual input proof on scan. So, we have the transaction on Sapoleia sent 20 E Denver to the other address. And while this resolves, we'll check my balance again to see that it was deducted.

So, we should have 9,980. Um, and as Solia scan indexes, we'll see what the inputs for that transfer were. So again, right, we did a transfer for 20 tokens and there so the 20 tokens we have the two the encrypted amount which again is a handle and then we have a zk proof that we know what that value is. Um okay and we have a few minutes for any questions if anyone has any questions. Thank you for listening.

This is a QR code for the confidential contracts library that we've been building at Open Zeppelin and any contact information if you have questions afterwards. Um, any questions? Nope. Okay. Thank you.

Automatic transcript — names and jargon may be misspelled.