Log In Sign Up

A Formal Semantics of Findel in Coq (Short Paper)

by   Andrei Arusoaie, et al.

We present the first formal semantics of Findel - a DSL for specifying financial derivatives. The semantics is encoded in Coq, and we use it to prove properties of several Findel contracts.


page 1

page 2

page 3

page 4


Temporal Aspects of Smart Contracts for Financial Derivatives

Implementing smart contracts to automate the performance of high-value o...

Literature Review: Smart Contract Semantics

This review presents and evaluates various formalisms for the purpose of...

Certifying Findel Derivatives for Blockchain

Derivatives are a special type of financial contracts used to hedge risk...

Semantics of Conjectures

This paper aims to expand and detail the notion of formal semantics of C...

Towards Coq-verified Esterel Semantics and Compiling

This paper focuses on semantics of the Esterel synchronous programming l...

Formal Semantics and Formally Verified Validation for Temporal Planning

We present a simple and concise semantics for temporal planning. Our sem...

Formal Semantics of the CDL Language

We reverse-engineer a formal semantics of the Component Definition Langu...

1 Introduction

Financial derivatives are contracts between two or more parties whose value is based on underlying financial assets (e.g., bonds, comodities, currencies, etc.). Typically, these contracts are expressed using natural language on a written document which is authorized by a trusted authority. However, natural language is often ambiguous and lacks precision. To overcome this issue, domain specific languages (DSLs) for expressing precise financial agreements have been developed [3, 4]. Findel [2] is yet another DSL in this category, which is restricted to financial derivatives. Findel is designed to be executed on the Ethereum blockchain platform and thus, it enables the use of smart contracts to facilitate derivatives trading. In [2], the language is advertised as being capable of “expressing the most common derivatives”.

A fixed rate currency exchange [2] contract, can be expressed in Findel as follows:

And(Give(Scale(11, One(USD))), Scale(10, One(EUR)))

Each Findel contract has two parties: an issuer and an owner. Let us assume that Alice is the issuer. If Bob joins the contract, then Bob becomes an owner and the contract is now ready for execution. And, Give, Scale, and One are called primitives, i.e., the building blocks of Findel contracts. And specifies that its both (sub)contracts Give(Scale(11, One(USD))) and Scale(10, One(EUR)) are executed sequentially. Give swaps the issuer and the owner. Scale multiplies the value of the contract by a specified factor. Finally, One is the only primitive that actually performs a transfer from the issuer to the owner. So, specifies that Bob gives to Alice 11 dolars and receives 10 euros from Alice.

Findel has an implementation in Solidity, which is available on Github: Findel contracts can be registered inside an Ethereum smart contract and then executed. Once deployed, a contract cannot be changed and thus, it very important for someone who deploys a contract to make sure that the terms of the involved transactions cannot be violated. For example, it is important for Alice to know that once Bob joins the contract she receives 11 dollars. Conversely, it is important for Bob to know that Alice will pay him back 10 euros precisely as specified by the contract.

Ideally, a trustworthy organization (e.g., a bank) may want to issue Findel contracts together with proof certificates to ensure that both the issuer and the owner have certain rights and obligations.

Contributions. We take the challenge to prove and certify properties about Findel contracts. To achieve that, we formally define the semantics of Findel primitives in Coq. We add to our semantics several components in order to simulate an execution environment, where multiple contracts can be executed, events are triggered, and transactions are registered in a ledger. This environment, hereafter called marketplace, enables us to prove not only properties of Findel primitives, but also properties that depend on other factors (external data providers, time, events). Besides simple examples, we approach several non-trivial contracts and we highlight problems that contracts may hide. Note that we formalise the existing semantics of Findel as presented in [2], and we do not improve or modify the language.

Primitive Informal semantics
Zero Do nothing.
One(currency) Transfer 1 unit of currency from issuer to the owner.
Scale(, ) Multiply all payments of by a constant factor of .
ScaleObs(, ) Multiply all payments of by a factor obtained from address .
Give() Swap parties of .
And(, ) Execute and then .
Or(, ) Give the owner the right to execute either or (not both).
If(, , ) If is true, execute , else execute , where is obtained from address .
Timebound(, , ) Execute , if the current timestamp is within .
Table 1: The informal semantics of Findel primitives [2].

2 The informal semantics of Findel

A Findel contract is a tuple with three components: a description, an issuer and an owner. A Findel description is essentially a tree with basic primitives as leaves and composite primitives as internal nodes. The list of available primitives and their informal semantics is shown in Table 1. Zero and One are basic primitives, while the others are composite. The execution model [2] of a Findel contract is:

  1. The first party issues a contract and becomes its issuer. This is a mere declaration of the issuer’s desire to conclude an agreement and entails no obligations.

  2. The second party joins the contract and becomes its owner. As a consequence, both parties accept the specified rights and obligations.

  3. The contract is executed immediately:

    1. Let the current node be the root node of the contract description. If the current node is either Or or Timebound with , postpone the execution: issue a new Findel contract, with the same parties and the current node as root. The owner can demand later its execution.

    2. Otherwise, execute all sub-nodes recursively.

    3. Delete the contract.

A Findel contract is not guaranteed to be executed: only the owner can trigger the execution for issued contracts. It is worth noting that the execution of a contract may produce new contracts (if Or or Timebound are present) or it can affect the balances of the parties. The current implementation of Findel does not enforce any constraints on the balances of the users that prevents them from building up debt.

3 The formal semantics in Coq

3.1 Syntax

The syntax of Findel is fairly small in size and it is quite easy to encode it in Coq using Inductive as shown in Figure 1.

Inductive Primitive :=
(* basic primitives *)
| Zero      :                                      Primitive
| One       : Currency ->                          Primitive
(* composite primitives *)
| Scale     : nat -> Primitive ->                  Primitive
| ScaleObs  : Address -> Primitive ->              Primitive
| Give      : Primitive ->                         Primitive
| And       : Primitive -> Primitive ->            Primitive
| Or        : Primitive -> Primitive ->            Primitive
| If        : Address -> Primitive -> Primitive -> Primitive
| Timebound : nat -> nat -> Primitive ->           Primitive.
Figure 1: The syntax of Findel in Coq.

For convenience, several additional primitives are introduced in [2]: At, Before, After, and Sell. In Coq, these are simple definitions. We show here only the definition for At:

Definition At (t : nat) (p : Primitive) := Timebound (t - ) (t + ) p.

is a just parameter which is used to adjust intervals for accepting transactions. Having these new constructs enables us to define interesting contracts in Coq. For instance, here is a zero-coupon-bond contract, where the issuer asks for 10 dollars and will pay an eventual owner 11 dollars after 1 year:

(And (Give (Scale (One USD) 10)) (At (now + 1 yr) (Scale (One USD) 11)))

3.2 Semantics

In Coq, we provide a function called exec which executes primitives recursively. The function takes as inputs the description id, a scale factor, the issuer, the owner, the current time, an external gateway, the ledger, and a fresh id. The base cases of exec are: for Zero it does nothing, for One it modifies the balances of the participants and the ledger, for Or and Timebound it generates new contracts. The gateway is used to retrieve external data, and it is modeled as a map from addresses to values. The function exec returns a tuple: the updated balance, the generated contracts, a fresh identifier, the updated ledger . Contracts are denoted as , where is the contract id, is the corresponding description, is the issuer, is the owner, is the the proposed owner, and is the scale of the contract.

The marketplace (i.e., the environment where contracts are executed) is a tuple with several components encoded as a record in Coq: - the list of the issued contracts; - the list of the available descriptions; - the current balance; - the current timestamp, i.e., a natural number; - the external gateway, i.e., a map from addresses to values, used to execute ScaleObs and If; - a fresh identifier i.e., a natural number which is always fresh; - a global ledger, i.e., the ordered list of the performed transactions; - the list of events, which are triggered during execution (e.g., Deleted, Executed, IssuedFor). We show below the semantical rules that specify how the marketplace evolves.

[Issue] When issued, a contract is added to the list of issued contracts in the marketplace having a unique id . The owner field contains the address of the issuer, while the proposed owner field contains the address of the intended owner. The primitive of the contract is initialized from an existing description. Also an event IssuedFor is triggered, and the global fresh id is incremented:

[Join] Joining a contract is the most complex operation and requires several conditions. First, , i.e., the owner is the proposed owner. Second, the root node should not be an Or: . Third, the execution is limited within a time interval by its description : . Finally, the execution should be successful: . The rule for joining a contract is shown below. Note that E is enriched with an Executed event.

[Join OR] If the primitive of the current contract is then the owner can execute either or : . Here, is either or :

[Fail] If the execution of a contract fails (e.g., if contract is expired or the gateway does not provide fresh data), i.e., , then the Deleted event is triggered:

[Tick] Since the execution of the Findel contracts depends on the current timestamp, the marketplace contains a global time. The tick rule increases the global time : [] ⟨C, D, B, t + 1, G, i, L, E ⟩ ⟨C, D, B, t, G, i, L, E

4 Proving properties of Findel contracts

A Findel contract specifies certain rights and obligations for parties. We show here examples of contracts and some interesting properties that we prove in Coq. We will see that, although they are are small is size, contracts may hide unexpected behaviors. Hereafter, we assume that Alice is the issuer and Bob is the owner. For each contract, we formalise the desired properties as theorems and we prove them in Coq.

I. Fixed-rate currency exchange. Recall the fixed rate currency exchange contract, where Bob gives Alice 11 dollars and receives 10 euros from Alice. In Coq, we are able to prove the next lemma:

Theorem 4.1.

If is executed, then Alice receives 11 dollars.

The lemma is straightforward: the hypothesis imply that the [Join] rule applies successfully. In this case, a transaction from Bob to Alice involving an amount of 11 dollars is registered in the ledger. Conversely, one may want to prove that Bob also receives 10 euros from Alice, which is also straightforward in Coq:

Theorem 4.2.

If is executed, then Bob receives 10 euros from Alice.

Note that the lemmas above hold, no matter what other contracts are executed in the marketplace. If one of the participants does not have enough money to pay then they can build up debt. The current semantics of Findel does not prevent from building up too much debt [2] and we do not formalize that in Coq.

II. External gateway rate - currency exchange. A more interesting contract is a currency exchange that uses a rate retrieved from an external source (a gateway). Consider the following Findel description:

(And (Give (Scale n (One EUR))) (ScaleObs ADDR (Scale n (One USD))))

specifies that the issuer is supposed to receive n EUR and will pay to the owner (rate * n) USD, where the rate is obtained from an external address ADDR using the gateway. A non-obvious problem is that it is possible for the gateway to fail for various reasons (e.g., data expired, invalid address). In such cases, the contract execution fails and the specified agreement between parties fails as well. Even if the balance of the parties is not affected, an intruder can determine certain contracts to fail on purpose.

In [2], the owner is “advised” to update gateways “shortly before execution”. Also, the gateway is assumed to be “trustworthy”. Under the same assumptions we prove in Coq the next theorems:

Theorem 4.3.

If is executed then Alice receives an amount of n euros.

Theorem 4.4.

If is executed and the gateway returns a rate then Bob receives rate * n dollars.

III. Zero-coupon bond. An interesting Findel contract is (Section 3.1): Alice should receive from Bob 10 dollars, while Bob receives 11 dollars after 1 year. Proving that Alice is paid is straightforward:

Theorem 4.5.

If is executed, then Alice receives 10 dollars from Bob.

One the other hand, due to the semantics of At (in Section 3.1, At is implemented using Timebound), we cannot prove that Bob receives 11 dollars from Alice! What we can prove is that after 1 year, Bob can claim 11 dollars from Alice. This is because when Timebound is executed, a new contract is issued, having Bob as owner. If Bob fails to demand the execution of the contract in the specified time boundaries then he might not receive his money back. So, the only guarantee that Bob has is given by this theorem:

Theorem 4.6.

If is executed, then Bob can claim 11 dollars from Alice.

If Bob demands the execution of the contract generated by Timebound then he receives the 11 dollars.

5 Conclusions

Using the formal semantics of Findel in Coq we are able to prove properties of Findel contracts. When proofs cannot be completed, they typically reveal problems in contracts that might cause money loses (e.g. Zero-coupon bond) or failed agreements (e.g., External gateway rate - currency exchange). This can be done by simply inspecting the failed proof case, which provides the failing conditions.

The results shown in Section 4 use several meta-properties of our Coq formalisation: (1) the step relation preserves state consistency; (2) event generation preserves states consistency; (3) the ledger is consistent; (4) parties cannot withdraw once they have agreed to upon a contract; (5) the time passing is not affected by contract execution.

Our Coq semantics of Findel is small and consists of 450 (non-empty) lines of code.111The code is available on Github: The proof of a theorem has around 15 lines of code, but these proofs use several helper lemmas and some handy tactics that we provide together with the semantics.

Acknowledgements. This work was supported by a grant of the “Alexandru Ioan Cuza” University of Iaşi, within the Research Grants program, Grant UAIC, ctr. no. 6/01-01-2017.


  • [1]
  • [2] Alex Biryukov, Dmitry Khovratovich & Sergei Tikhomirov (2017): Findel: Secure Derivative Contracts for Ethereum. In: Financial Cryptography Workshops, LNCS 10323, Springer, pp. 453–467.
  • [3] David Raymond Christiansen, Klaus Grue, Henning Niss, Peter Sestoft & Kristján S. Sigtryggsson (2013): An Actuarial Programming Language for Life Insurance and Pensions.
  • [4] Simon Peyton Jones, Jean marc Eber & Julian Seward (2000): Composing contracts: an adventure in financial engineering - Functional Pearl.