ERC-7390: Vanilla Option Standard

A standard interface for creating and interacting with vanilla options.

You can see an implementation of this ERC here

I went through the EIP as well as the accompanying implementation. Great stuff! I am also interested in bringing different kinds of financial instruments to the blockchain, and vanilla options are a great product to start with.

I have a few comments:

(1) Creating a new contract for each option issuance seems a bit sub-optimal. Options are ephemeral by nature, so once the option has expired, the contract just stays on the blockchain and doesn’t do anything. I would propose a change where the parameters of the option are not defined in the contract’s constructor, but instead are given on the create() call, and the create() would return a uint256 id.

The id value would then be passed as a parameter to the buy(), exercise(), retrieveExpiredTokens(), and cancel() function calls to signal which option issuance is the targeted action. Internally, inside the implementing contract, the option issuance data could be saved to a struct, and a mapping (and an incrementing counter) could be used for storing.

In this way, a single contract could hold a large number of option issuances, and in my opinion, it would be a better way to organize the option issuances and reduce fragmentation.

(2) When the counterparty pays the premium and takes the other side to buy a call or put, there should be tokens that should be minted for the buyer representing the options. The amount of tokens should be the same as the amount of the underlying asset.

As an example, in the “Concrete Example - Call Option” part, the amount of underlying is 8000000000000000000 LINKs. When the counterparty pays the premium, they should get 8000000000000000000 tokens that represent the amount of LINK tokens that can be bought at the strike price.

Again, due to the ephemeral nature of the options, I don’t think the tokens should be represented by an ERC-20 contract that is created on-the-fly; instead, I would go for ERC-1155 to hold all option tokens in a single contract. Also, when options are represented as tokens, they could be traded independently to other parties.

(3) One potential limitation of the current interface design is that on the exercise() method, the buyer must exercise all options. I would suggest that there should be a parameter for the exercise() function to define how many option tokens the buyer wants to exercise. This would make sense, e.g., when the buyer might want to exercise only a portion of the option tokens to hedge and take gains of the currently favorable underlying price while still retaining the other portion to see if the market moves even more in the buyer’s favor (given that buyer still has exercise time left).

When the buyer exercises they need to of course have the amount of option tokens and they need to pay strikePrice * amount of strikeToken to the seller. Anyone who holds option tokens would be able to exercise them during exercise window.

(4) For the create method, I would add an array of addresses that are the allowed counterparties to (initially) take the other side. This is the improvement idea mentioned at the end of the ERC, and I think it would make sense to add it. If the array is empty, then it is free-for-all. Now, if suggestions (2) and (3) are taken into account, then there should be no restrictions on who can exercise the underlying as long as they own the tokens that represent the options. If we want to limit this, then there could be an extra boolean parameter for the create() method called “renounceable” that defines if the counterparty can buy/sell the option tokens to other parties as they wish or if those tokens are locked to the counterparty’s address, and only they can exercise them.

(5) I would remove from the state variables the type of the option (“european” / “american”). Also I would remove expiration state variable. Instead of these I would define two state variables, exerciseWindowStart and exerciseWindowEnd, which represent when user can start to exercise and when the exercising ends. After exerciseWindowEnd time has passed, seller can call retrieveExpiredTokens() to get the underlying tokens back that have not been exercised.

1 Like

Hey, thanks so much for your interest in this EIP!

Here’s my answer for each suggestion:

(1) Yes that’s a really good idea! This would be a change a bit like Uniswap V4 = making a singleton contract. And this would be simpler for users to create a new contract (instead of creating, then calling create() to “enable” the option).
However, I’m not sure this would be a standard (ERC), but rather a “private” protocol on itself (because there would be only one contract on the blockchain). But if this standard is created by every dApp, we should think about how to transfer options between smart contracts.
Maybe another solution to improve gas: make the contract reusable. This mean that after the option is “inactive”, someone (or the same writer), can change all the parameters to create a new option, instead of creating a new smart contract.

(2) So your idea is to create a kind of coupon represented as a token, so that the buyer can “share” his right with multiple people to exercise according to the amount he gave to each of them? It’s really interesting and would brought even more possibilities. But do you think it is more gas efficient to use a system of token (with an ERC-1155), or to simply implement the functionality without token (e.g. a function shareExercise(uint256 amount, address recipient) that would store each amount for each address in a map, and when exercising, the contract would verify if msg.sender can exercise)?

(3) Great idea! It would offer more possibilities.

(4) Another great idea, this would (has you said) be the solution to the suggestion written in the EIP :slight_smile:

(5) Very smart, it would be simpler and probably more gas efficient.

Hi,

my (current) proposal for the interface is at the fork that is available on GitHub - mlalma/ERC-7390: Fork of draft implementation of ERC-7390 spec for hatching out changes to the standard.

I think the key here would be the interface on IVanillaOption.sol. It basically is IOption.sol with all my prposed changes.

I have updated the README.md and documented the interface there. If you could take a look at it, try out the fork and see that the reference implementation (and the related tests) work as expected and then provide some comments back that would be amazing.

For the summary, some of the key changes I would propose are:

  • VanillaOptionData struct contains the essential features of a vanilla option in a single struct that is passed to the create() function
  • None of the functions return bool stating success / failure. If the function returns, then the action is successful and for any failure an exception is thrown
  • There is now ID parameter that needs to be passed around so that single contract can handle multiple option issuances due to the ephemeral nature of the instrument
  • Option buyer does not need to buy the whole lot, they can define the amount of options they want to buy (and later on exercise)
  • I have added updatePremium() function to enable option seller to change the premium to keep it more in synch

There are probably also other smaller changes, but I think those are the main ones.

-mla