How to attach an encrypted file to your NFT

EFT Protocol definition

Oleg Shatniuk
FileMarket.xyz
6 min readJan 16, 2023

--

While starting FileMarket— a multifaceted platform that serves as a NFT2.0 storefront builder, cutting-edge marketplace, and a protocol for tokenizing, storing, and swapping files. At one point, we thought that it would be nice to have some private content linked to NFT to solve Ctrl+c — Ctrl+v problem. We’ve done some research and realized that there are no such technologies to have private content and the ability to transfer it while remaining hidden from the world. After that, we decided to design and implement a protocol for private NFT using encryption.

This article will describe our path to the solution and include many technical details, so one reading this article should be familiar with basic encryption concepts like symmetric and asymmetric encryption, NFT standards like ERC721 and ERC1155, and the Solidity language because there will be a lot of code!

The entire code of the FileMarket project is open source, it can be found in our Github organization. A demo version of our platform is also already available.

Basic concept

Our main goal was to make the protocol completely decentralized, which leads us to the file immutability requirement because with re-encryption file contents can be changed after minting. So, we decided to encrypt the file with any symmetric encryption and store the result. Thus, the transfer process will consist of symmetric encryption key transfer.

Of course, we can’t transfer the key in a direct way, so it also must be encrypted. We thought that asymmetric encryption suits us the best as the receiver will have his private key hidden and the sender will be able to encrypt the symmetric encryption key with the only public key of the receiver.

So, our first basic concept looks like this:

General protocol scheme

Fraud verifying

The case of confirmation of the transfer by the receiver does not require additional attention, but the case of rejection implies that something is wrong with the file. There are a few possible options:

  1. The encrypted file key is not valid (for example, an empty string or decrypted data is not a valid key).
  2. The encrypted key is valid, but the result of the decryption is not the same file that was originally encrypted. To verify this fact, the file is concatenated with its hash during encryption.

If none of these conditions are met, but the receiver declined the transfer, then this is fraud on the part of the receiver because he gained access to the encrypted file but did not accept the transfer, and this transfer could be part of some kind of transaction like the sale of NFTs.

Hence, the protocol should provide for the resolution of disputes in case of rejection of the transfer. That is, some trusted third party is needed to carry out the verification in this case. Schematically it looks like this:

Protocol scheme with defined 3rd-party

Decentralized fraud verifying

Our next problem is to make the trusted third-party decentralized. To do this, the implementation technology must have the following properties:

  1. Have access to the data storage;
  2. Be able to perform encryption and decryption operations;
  3. With its help, the implementation of NFT must be possible.

Filecoin has all these properties:

  1. From FVM actors there is access to the Filecoin data storage;
  2. The implementation language of FVM actors — Rust makes it convenient to use encryption protocols. Using Solidity to implement encryption is difficult and inefficient — such operations will have a high cost in gas and a long execution time due to a large number of operations with the memory (you can read more about this issue in one of my previous articles);
  3. FEVM allows us to use Solidity implementations of NFT standards like ERC721 or ERC1155, while all encryption work will be done with FVM actors.

With Filecoin, our protocol looks like this:

Protocol scheme

Development process

Initially, we decided to divide the development into two parts:

  1. FVM actors for working with files and encryption;
  2. FEVM Solidity NFT smart contracts.

We entered the FVM Early Builders program and participated in the FEVM hackathon (unfortunately, we did not make it to the final). At the time of the start of development (August 2022), FVM was not yet fully completed, so we decided that we should implement Solidity smart contracts that we will deploy in Polygon and a Rust server that would listen to the blockchain and wait for fraud reports, after which it would conduct decryption attempt. This Rust server will be able to call the smart contract methods responsible for resolving disputes. The choice of the Rust language here is not accidental, it is needed in order to make it easier for us to convert this server into a FVM actor in the future.

So, the Polygon version with the Rust server looks like this:

Protocol version with Polygon and Rust server as judge

And we decided to pack Solidity smart contracts into a standard and define them as interfaces. We named this standard Encrypted File Token or EFT. Next, we will consider the standard in more detail.

Encrypted File Token Standard

So, the main requirements for our standard:

  1. It must implement the token transfer pipeline.
  2. It must be possible to use an FVM actor for fraud verification when the result of the check is obtained in a single call and use a plain EVM smart contract (managed by a Rust server) as a source of dispute resolution.
  3. It must be possible to trigger some events when a transfer is canceled or completed. This is necessary to create other high-level applications that interact with the EFT standard, since passing an EFT cannot be an atomic operation.

To fulfill these requirements, we define 3 interfaces:

  1. IEncryptedFileToken — main standard for Encrypted NFT.
  2. IFraudDecider — interface for fraud decider contract. It’s required to make this interface for the possibility of using FVM-actor and EVM contract (for Polygon version of our system), which will be called from the Rust server.
  3. IEncryptedFileTokenCallbackReceiver — interface for contracts to implement for the ability to make some actions on transfer cancellation of finish.

Let’s start with IEncryptedFileTokenCallbackReceiver as it is the simplest standard.

The IFraudDecider interface is defined so that EFT instances can interact with both the FVM actor and to interact with the Polygon smart contract managed by our backend. To do this, the fraud check function returns two boolean values ​​ — the first determines whether a decision was made, and the second takes the value true if there is indeed a fraud act.

And finally, the token standard itself. We have omitted some obvious comments like “MUST revert if the token doesn’t exist” in this Gist to shorten it. Also, block with ERC721 transfers and instructions to make them revert always was omitted. Full interface definition and reference implementation can be found in our repository.

EFT Standard

Examples

For a better understanding, let’s take a look at a few important examples: the implementation of IFraudDecider in our current version, which is controlled by our Rust server, and the implementation of the simplest exchange contract for selling EFT.

IFraudDecider

FraudDeciderWeb2 — A contract that implements the IFraudDecider interface. It has a special lateDecision method that is called from our Rust server. It is called when an attempt has been made to decrypt a file, and the verdict is passed in the arguments.

IFraudDecider implementation

EFT Exchange

FileMarketExchange — an example of a simple exchange for selling EFT. An order is created and at that moment an EFT transfer is created to lock the token (the creation of any other transfers will be impossible until the order completion of cancellation). Using the fulfillOrder function, the buyer fixes his address for receiving EFT and locks the funds, and the functions of the IEncryptedFileTokenCallbackReceiver interface allow the exchange contract to unlock the funds upon successful or unsuccessful completion of the transfer.

Simple exchange contract implementation

What’s next?

After the MVP version, our two main goals are:

  1. To implement our protocol on FVM/FEVM.
  2. To build developer tools for easy usage of our EFT standard.

We will continue development and are excited to share results in future parts of this article series. Thank you for reading and may the force be with you!

Useful links:

--

--

Oleg Shatniuk
FileMarket.xyz

Backend and Web3/Solidity developer, data science engineer