An Brief Introduction to Confidential Contract Provided by Eigen Network

The Necessary of Confidential Contract

For the Ethereum public main chain, its most proud or important feature is that all transactions are open and transparent, which means that anyone who joins in this network can obtain the whole transaction history. They can analyze them freely.

However, a coin has two sides. The absolutely privacy still has its vitality. In the DeFi application, due to its transparency, the perpetrator can make some inferences from the transaction and “attacks” with these transaction histories. These transparency may be used to make the perpetrators profitable and cause losses to investors.

Eigen Network Confidential Contracts Framework — — EigenCC

Based on a series theoretical foundation and practical experience, The Eigen Network provides several technical infrastructure to support confidential contracts in a public blockchain network, with the L2 solution of Arbitrum.

The framework EigenCC provides an easy way to add new instructions in the trusted execution environment (TEE). We focus on 3 important parts to leverage the confidential trusted computing environment:

  • Confidential operators: what operators inside TEE can be provided and how it get done;
  • Secure transportation: how the privacy information is sent or received from the Eigen Network without privacy breach;
  • On-chain data protection: how we store the privacy information on the chain.

The TEE is often hardware based. It ensures that even the node operator does NOT have any access to private data, including immediate computation results. This feature ensures the security of private data. EigenCC provides a decentralized mechanism for TEE nodes. Due to the compatibility of Arbitrum with Ethereum, the Ethereum digital assets (e.g., ERC-20 tokens) can move between Ethereum and our own token, which means that anyone can develop smart contracts with a minor modification.

Confidential Operators

Some fundamental confidential operators should be provided to simplify the development and abstract some common calculations. Thus we provide a series of confidential operators. For now, we’ve implemented:

  • Three arithmetic operators: addition, subtraction and multiplication on 256bits integer
  • Comparison operators: greater than, less than and equal
  • Debug operators: encryption and decryption

These operators are done inside TEE, which makes it confidential. The latest implementation and documents could be found in our Github.

Secure Transportation

Referring to the security mechanism of TLS, we adopt the RA-TLS schema for a secure channel between end-user and EigenCC. The general workflow is like below:

The main update is that we put the Enclave Quote embedded in the X509 certificate, and the challenger verifies the quote after the general certificate verification.

In our implementation, we provide a socket-based channel between EGVM(AVM) and EigenCC.

Hence, all above encrypted items are encrypted by an ECC public key with ECIES. When EigenCC launches, it will generate an ECC key pair, and the public key will be registered to PKCS.

On-chain Data Protection

This is a tough issue. Since the on-chain data is openly accessed by anyone, if a vulnerable logic or weak key was used, it leads to all the privacy inside the corresponding contract being exposed to everyone. Hence, how to encrypt the on-chain data becomes crucial.

It recommends taking the secret key into custody by the owner itself, and using re_encrypt to encrypt the privacy information, and upgrade the key periodically.

Use Cases

Some use cases are provided to show how to use the EigenCC framework.

EigenCall Library

To make it easy to use and save gases, we implement a link library named EigenCallLibrary here. It can be deployed on L2 and anyone can call them if deployed with the address.

EigenCallLibrary is implemented based on EGIP 00001, for now, we have implemented these public functions in here.

These functions hide the details of implementations of eigenCall, so the user does not care about how to compose an eigenCall input bytes, or how to decode the returning RLP encoded value. An assert is put into each wrapper function to ensure eigenCall is called successfully. If any error occurs, the contract call will cause a transaction revert with a message.

To use EigenCallLibrary in a contract, just import it with the right path, and regard it as a typical link library. For example, in TestCCCustomToken.sol, demo_addCipherCipher function calls EigenCallLibrary.addCipherCipher:

function demo_addCipherCipher(bytes memory cipher1, bytes memory cipher2)



returns (bytes memory)


bytes memory output = EigenCallLibrary.addCipherCipher(cipher1, cipher2);

return output;


The output is ensured a valid cipher result of addCipherCipher operator. So the user can use the result without caring about the correctness of the result.

Other demo_* functions can be found in TestCCCustomToken.sol.

If we want to call the contract function in Javascript or Typescript, we should tell the link library address in the contract we want to use EigenCallLibrary.

For example, we can see the snippet in exec.js:

// …

var L2EigenCallLibrary = await (

await ethers.getContractFactory(“EigenCallLibrary”)


L2EigenCallLibrary = await L2EigenCallLibrary.deploy();

await L2EigenCallLibrary.deployed();


“EigenCallLibrary is deployed at address:”,



var L2EigenCallLibraryUseDemo = await (

await ethers.getContractFactory(“EigenCallLibraryUseDemo”, {

libraries: {

EigenCallLibrary: L2EigenCallLibrary.address,




console.log(“Deploying EigenCallLibraryUseDemo contract to L2”);

L2EigenCallLibraryUseDemo = await L2EigenCallLibraryUseDemo.deploy({

gasLimit: 25000000,


await L2EigenCallLibraryUseDemo.deployed();


`EigencallDemo contract is deployed to ${L2EigenCallLibraryUseDemo.address}`


// …

Before deploying EigenCallLibraryUseDemo which uses EigenCallLibrary, we should ensure that we have got the link address of it, after passing it to the factory function, the contract can be deployed successfully.

The Typescript example can be found in cc.ts, it is similar with the Javascript snippet.

After the successful deployment, we can freely call these contract functions with TEE operators support!

Confidential ERC20

The Standard ERC20 token is widely used for now. Following is an interface contract declaring the required functions and events to meet the ERC20 standard:

contract ERC20 {

function totalSupply() constant returns (uint totalSupply);

function balanceOf(address _owner) constant returns (uint balance);

function transfer(address _to, uint _value) returns (bool success);

function transferFrom(address _from, address _to, uint _value) returns (bool success);

function approve(address _spender, uint _value) returns (bool success);

function allowance(address _owner, address _spender) constant returns (uint remaining);

event Transfer(address indexed _from, address indexed _to, uint _value);

event Approval(address indexed _owner, address indexed _spender, uint _value);


One of the core functions of ERC20 is transfer. In brief, transfer applies two math operations on corresponding balances, that is, adding the amount to the receiver’s balance and minus the amount to the sender’s balance.

For our Confidential ERC20, which had been implemented at TestCCCustomToken.sol, The math operators used in balance calculation are privacy operators.

For example, in TestCCCustomToken.sol, transfer can be implemented as:

function transfer(address recipient, uint256 amount) public virtual override returns (bool) {

// …

bytes memory sender_cipher_hex_balance = _cipher_balances[_msgSender()];

bytes memory sender_cipher_hex = EigenCallLibrary.subCipherPlain(




_cipher_balances[_msgSender()] = EigenCallLibrary.copyBytes(sender_cipher_hex);

bytes memory recipient_cipher_hex_balance = _cipher_balances[recipient];

bytes memory recipient_cipher_hex = EigenCallLibrary.addCipherPlain(




_cipher_balances[recipient] = EigenCallLibrary.copyBytes(recipient_cipher_hex);

emit TransferCipher(_msgSender(), recipient, bytes(amount.toString()));

return true;


Instead of store plain balances, cipher balances are used in Confidential ERC20. So typical add and sub are replaced with privacy operators, (here, we use addCipherPlain and subCipherPlain as replacement). Quite easy to implement such tokens with EigenCallLibrary.

Also, we can implement another version of transfer named cipherTransfer, which means the amount can be also cipher:

function cipherTransfer(address recipient, bytes memory cipher_amount)



returns (bool)


// …

bytes memory sender_cipher_hex_balance = _cipher_balances[_msgSender()];

bytes memory sender_cipher_hex = EigenCallLibrary.subCipherCipher(




_cipher_balances[_msgSender()] = EigenCallLibrary.copyBytes(sender_cipher_hex);

bytes memory recipient_cipher_hex_balance = _cipher_balances[recipient];

bytes memory recipient_cipher_hex = EigenCallLibrary.addCipherCipher(




_cipher_balances[recipient] = EigenCallLibrary.copyBytes(recipient_cipher_hex);

emit TransferCipher(_msgSender(), recipient, cipher_amount);

return true;


Just use addCipherCipher and subCipherCipher instead of addCipherPlain and subCipherPlain.

What about getting the balance? Of course, we can get the cipher balance with cipherBalanceOf.

Other functions are implemented similarly. To know more details, we can read the overall source code.

About Eigen Network

Official WebsiteTwitterGithubDiscord

If you liked this article and care about Privacy, smash that clap button, then tweet everyone



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Eigen Network

Eigen Network

Where make transaction secure and private for Web3.0(