GIF Smart Contracts Architecture
The core smart contracts of the Generic Insurance Framework.

The Generic Insurance Framework (GIF, or simply “the framework”) is a part of the platform for insurance product builders, which helps them develop decentralized insurance apps. The GIF consists of a collection of smart contracts (the “core (smart) contracts”) on the one side and a collection of microservices to operate these smart contracts on the other side.
The core contracts will be deployed on-chain and operated as a service for product builders. While we will dedicate a separate blog post to the many possible operational models for this, for the purpose of this post you can assume that the core contracts are deployed and maintained by some entity in the Decentralized Insurance Platform. An insurance product (for brevity, and because we could also have products which are not an insurance product in the legal sense, we will call it just “product” in our terminology) on top of the GIF is a smart contract connected to the framework through the interface of a single entry point smart contract.
We won’t be able to cover every single aspect of this complex system in this blog post, but it should give you a general idea of some basic concepts. We will follow up with separate blog posts on the main elements in the next weeks.
Design principles
In what follows, we describe the main underlying principles and requirements, which guided the development of the core contracts.
- The core contracts should support the whole lifecycle of a policy, giving all involved parties a full audit trail of all legally relevant steps and events.
- Because of the potential complexity of such a lifecycle, it should be possible to deploy a variety of different workflows in the system. Currently, this is enabled by the “PolicyFlow” contract which can be overridden.
- A policy, as stored in a smart contract, represents a subset* of the clauses of the legal contract which constitutes a policy. The data and workflow should be as close as possible to the legal lifecycle of the policy.
- A product utilizes a simple and clear interface for integration with the GIF.
- The GIF provides a unified interface which connects a product to data and decision providers (oracles). These oracles can be provided on a per-product base or as a general service which is accessible by many products (e.g. price feeds).
- And last, but not least, core contracts are upgradeable. The reason why we need upgradeability for smart contracts is to deliver fixes and new features. Products are subject to change, and we need an elegant mechanism to enable changes while keeping existing policies unaltered.
* It represents a subset because, in most real policies, there are terms which cover edge cases (like exclusion of terrorism) which cannot be reasonably implemented in a smart contract.
Upgradeability: How to deal with fixes and new features
This gives rise to the question, if the system of core contracts can be upgraded, once a policy is issued, is it allowed to update (replace) a certain smart contract during the policy lifecycle? Of course not. Once the agreement is signed and the policy is issued, we cannot unilaterally change the specified behavior. So, from this point we have another requirement: the framework must ensure that all involved parties can always exactly predict which set of smart contracts will execute the policy.
We distinguish two different situations which could trigger an update of a smart contract:
- A bug has been detected. A bug is a deviation of expected behavior to actual behavior — a difference between specification and implementation. We need a way to fix bugs. Bugs can be technical bugs (a flawed implementation of a certain calculation, leading to wrong results), but they can also occur in the translation process from legal prose to code. In this case, the specification would be flawed, and correct implementation of a flawed specification still leads to wrong results.
- New features need to be implemented for various reasons: modifications in pricing, risk model etc.. In this case, the specification changes.
Both cases can occur on the core contract level as well as on the product-specific contract level.
We handle the two cases slightly different:
- A bug fix upgrade will affect all policies, existing and new ones.
- A “new feature” upgrade will affect only new policies. Existing policies will be executed with the original set of smart contracts (modulo bug fixes).
Core objects
Another aspect that has to be defined before we dive into the smart contracts architecture is the definition of core objects. Core Objects store the data of core contracts.
- Product — a registered smart contract with permissions to create and manage policy flows
- Application — represents an application for a policy by a customer. An “application” is not yet a valid policy but collects the data which will then be signed and turned in a policy.
- Policy — represents an agreement between the customer and the insurance company. A policy is essentially unchangeable (except for the status). If for some reason a modification of the terms is necessary, this will always create a new technical object; in the same sense as a legal contract is in principle unalterable, and a modification essentially creates a new version (on which all involved parties have to agree upon and sign again). Policies are managed by the policy module (see below).
- Claim — data about the claim, requires approval
- Payout — data about expected and actual payouts for the claim
- Metadata — a shared object between all the objects of the particular policy flow
- Policy token — an ERC1521* (extension of ERC721 NFT) token which represents a policy, a set of particular fields. A Policy token contract represents a specific product, while the individual token represents a single policy. These tokens can serve as objects which make policies suitable to securitization and refinancing purposes.
The detailed specification and use of these core objects will be subject of a separate blog post.
* https://github.com/ethereum/EIPs/pull/1512
Modules — the fundamental building blocks
In the GIF, the fundamental building blocks (of product specific and core contracts) are called “modules”. A module is a pair of storage contracts and its controller(s). They share the same storage model and interface objects. A storage contract is a proxy and it delegates calls from the storage to controller. It brings upgradeability to the module. A similar proxy pattern was introduced by the OpenZeppelin team as “Eternal proxy”.
The modules from the upcoming GIF release:
- Policy module (manages applications, policies, claims, payouts, and metadata objects)
- Access module (defines permissions between contracts and actors)
- Ledger module (bookkeeper for operations, aggregates premiums, payouts, expenses, etc.)
- Registry module (register’s sets of core contracts which are used within the policy flow lifecycle in release groups)
- License module (manages products)
- Query module (manages queries to oracles and delivers responses from them).
Check the code to see how the modules are organized.
Modules are controlled by service contracts. Service contracts provide controlled access to the module data storage. The only way to access and change data in the storage contract is via service contract. Here is the list of service contracts:
- DAOService (administrative operations)
- ProductService (product operations)
- ProductOwnerService (product owner operations)
- OracleService (oracle operations)
- OracleOwnerService (oracle owner operations)
The product contract is connected to ProductService, which exposes a public interface. A certain PolicyFlow contract should be defined during contract registration. Each PolicyFlow has a certain set of actions available for products. The Product contract uses the ProductService interface to start and control the policy flow lifecycle.
The main methods of the ProductService contract available for products:
- newApplication. This method is used to store new application data, which contains such fields as a premium amount, currency, payout options, risk definition, etc. A customer signs a policy agreement using this method.
- underwrite. This method is used to sign a policy agreement on behalf of an insurance company.
- decline. Used to decline an application.
- newClaim. Used to declare a new claim.
- confirmClaim. Used to confirm a claim. A new payout object is created after this.
- declineClaim. Used to decline a claim.
- payout. Used to declare a payout which was handled off-chain or on-chain based on a policy currency.
- expire. Used to set policy expiration.
- register. Used to register new products. After approval, a contract obtains access to call entry methods.
- query. This method is used to communicate with oracles when a product requires data or decision of a particular actor.
Each product should be registered in the License module in order to obtain access to call ProductService methods and modify the state of internal objects through it.

Once products are registered, a new Policy token contract is deployed to it. A Policy token derives from the ERC1521 token standard which is an extension of the ERC721 NFT token standard and represents a policy as a JSON object, possibly stored in IPFS.
Core contracts should be registered in the Registry module. They are grouped into releases. Each policy has a reference to the corresponding release. This reference is used to resolve the contracts, which are used in the current policy flow lifecycle.
As mentioned before, there are two types of updates on contracts: Fix and Upgrade. Fix is used to deliver bug fixes, while Upgrade is used to deliver new features. During Fix, a certain contract in the current release is replaced with a new contract. In contrast, during Upgrade, a new release is created. New policies which are issued after this release will have a pointer to a new release.

In the next article, we will show how to build a simple insurance product with role-based actors.