Announcing Ivy Playground
Writing Smart Contracts with Chain Core

We are delighted to release Ivy Playground, a tool for designing, drafting, and testing smart contracts on a Chain blockchain network with Ivy, our high-level contract programming language.
Ivy Playground is bundled directly into a special release of our open source Chain Core Developer Edition and is pre-loaded with several contract templates, which you can use to create contracts that control assets on our testnet or your own local Chain blockchain network.
Download Chain Core Developer Edition with Ivy Playground
In this post, we’ll explore how Chain thinks about smart contracts and the design principles for Ivy. We’ll describe how Ivy contracts can reduce the risk and costs of creating and entering into financial agreements and derivatives, such as escrowed transfers, collateralized loans, and call options, and how they can be used to better secure assets on a blockchain.
Background
The key characteristic that makes a Chain blockchain a shared ledger, rather than simply a distributed database, is that it is designed to track and control value — i.e., units of one or more assets. Unlike data, value is scarce: once issued, it cannot be copied, only transferred.
We gain new capabilities when the underlying format of a financial instrument becomes a cryptographically-issued digital asset, one of the most notable of which is the ability to write programs that control the asset. These programs are known as contracts.
All value on a Chain blockchain is secured by such contracts. Each contract controls, or locks, some specific value — i.e., some number of units of an asset — and enforces the conditions that must be satisfied before that value can be unlocked. From the simplest custodial account to the most complex derivative instrument, contracts define the rules for asset movement on a Chain blockchain network. And Ivy lets you compose those rules.
Ivy Design Principles
When designing Ivy we had a single goal: making it easy to write safe, secure, and simple programs to control the movement of value on a blockchain. Nothing more, nothing less.
Ivy is influenced by functional programming languages (such as Clojure, OCaml, and Haskell), safe languages (such as Rust and Swift), and logic programming languages (such as Prolog). Ivy is also inspired by ideas developed by Nick Szabo, particularly in A Formal Language For Analyzing Contracts (2002), Secure Property Titles with Owner Authority (1998), and The Idea of Smart Contracts (1997).
A focus on assets
The purpose of Ivy is to write contracts that control one or more assets. This focus means that such contracts can be written expressively, and with minimal boilerplate. Additionally, since Chain blockchains support multiple asset types on a single network, Ivy is designed to make it easy to write code to handle multiple assets in a single contract.
In contrast, most other smart contract approaches, even those aimed at financial use cases, aim to provide general-purpose platforms for distributed computation (e.g., Ethereum). Some platforms even use existing languages or runtime environments as their smart contract environments — Fabric’s “chaincode” can be written in Go, while Corda’s “corDapps” are executed on the Java Virtual Machine.
Immutability
Contracts on a Chain blockchain are immutable. A contract cannot be updated, only spent — i.e., removed from the blockchain and replaced with one or more new contracts that lock the same value. Ivy is designed to reflect this data model. Execution of contracts is pure — it does not depend on blockchain state (outside of the state contained in the transaction in which it is spent), and has no side effects.
Immutable contracts with side-effect-free execution have many benefits at the protocol level, such as allowing transactions to be validated in parallel and reducing the memory overhead of validating the blockchain, which are outside the scope of this post. But immutability also creates advantages for writing contracts, by making it easier to predict the effects of program execution. For similar reasons, programming with immutable data structures has experienced a recent surge of popularity outside of the blockchain context, in languages such as Clojure, Haskell, and Elm and frameworks such as JavaScript’s Redux.
This immutable state model distinguishes our approach from that of (for example) Ethereum and Fabric. In Ethereum, contracts can send messages and value to each other and can update their own state in response to these messages. While this model seems familiar to programmers accustomed to imperative programming, it can be very difficult to reason about, as was demonstrated by the subtle bug in the “DAO” contract that led to the theft of around $50 million worth of investor funds from a contract on the public Ethereum blockchain.
While our state model differs from Ethereum’s contracts and Fabric’s mutable “asset registries,” there are other blockchain platforms that make use of immutable contracts, such as Bitcoin (which has “unspent transaction outputs”) and Corda (which calls them “state objects”).
Safety
Ivy is designed with safety and security as its foremost priorities.
As described above, Chain’s immutable state model makes it easier to reason about the effects of contract execution. Additionally, the compiler provides its own safety guarantees, using a static type system to reject a large class of invalid programs, such as ones that incorrectly mix PublicKey and Signature inputs, or which compare results of different hash functions. Ivy also checks that all value passed into a contract is explicitly used, preventing contract writers from losing track of value that is passed into a contract. (These safety checks, among others, are further described in our documentation.)
Most current smart contract approaches provide the freedom to write programs that execute arbitrary logic on a blockchain, but make it essentially impossible to provide the kind of safety assurances that Ivy is designed to give. While other platforms have the goal of making it easy to build anything, Ivy’s goal is to make it difficult to build anything wrong.
Simplicity
We intend Ivy to be a small language, which concerns itself only with conditions that are needed to properly control value.
This doesn’t mean that blockchain applications can only have limited functionality. Rather, we believe that contract programming should make up only a thin layer of a full blockchain solution. As much as possible, the business logic of blockchain solutions should be executed off-chain, in the “application layer” — programs written in traditional languages, that interact with Chain Core through its SDK. The only logic that needs to be part of the “smart contract” layer is the set of rules that secure and transfer assets.
Some blockchain platforms are marketed as workflow automation tools, as a global database for shared state, or as a platform for building software-as-a-service applications. We believe that these goals make the wrong tradeoff, by effectively shifting computation and logic from traditional servers, where computation is cheap and information is private, to the blockchain, where every computation must be redundantly executed on every node in the network.
Our approach is to keep and execute only consensus-critical state and logic — i.e., the current set of values and the rules for unlocking those values — on the blockchain.
Anatomy of an Ivy Contract
An Ivy contract locks value on a blockchain with a set of clauses, each of which describes a set of conditions that can be satisfied to unlock the value. In the following example, there is only one way to unlock the value: by providing a valid signature to the spend clause.
contract LockWithPublicKey(
key: PublicKey
) locks value {
clause spend(sig: Signature) {
verify checkTxSig(key, sig)
unlock value
}
}
The public key is provided at the time the value is locked into the contract. The signature is provided at the time the value is unlocked.
You may recognize the spend clause as the simple logic used for standard addresses in Bitcoin or accounts in Ethereum, where funds are stored under the control of a single private key.
By adding clauses and conditions, contract writers can secure value with more complex logic. For example, the following contract enforces an American-style covered call option, where the seller (writer) of the option provides the buyer (holder) the right, but not the obligation, to purchase the underlying asset at a pre-agreed strike price before a specific time.
contract CallOption(
strikePrice: Amount,
strikeCurrency: Asset,
seller: Program,
buyerKey: PublicKey,
expiration: Time
) locks underlying {
clause exercise(
buyerSig: Signature
) requires payment: strikePrice of strikeCurrency {
verify before(expiration)
verify checkTxSig(buyerKey, buyerSig)
lock payment with seller
unlock underlying
}
clause expire() {
verify after(expiration)
lock underlying with seller
}
}
This contract is created by the option’s seller (presumably in return for a premium paid by the option’s buyer), and locks up the underlying asset that is the subject of the option. When creating the contract, the seller provides the strike price and currency, her own account program (to receive payment), the buyer’s public key (to strike), and the expiration time of the option.
This contract has two clauses, which can each unlock the value by satisfying a different set of conditions:
- The exercise clause allows the buyer to buy the underlying asset by signing the transaction and paying the strike price to the seller before the expiration time.
- The expire clause allows the seller to recover the underlying assets after the expiration time.
These clauses use several of the conditions supported in Ivy to enforce the parties’ rights with respect to the underlying asset:
- Checking Signatures — in the exercise clause,
checkTxSig(buyerKey, buyerSig)ensures that only the buyer can exercise the option. - Constraining Time — in the exercise clause,
verify before(expiration)ensures that the buyer cannot exercise the option after the expiration time. In the expire clause,verify after(expiration)ensures that the seller cannot trigger expiration until after the expiration time. - Requiring Value — in the exercise clause,
requires payment: strikePrice of strikeCurrencyensures that in order to buy the underlying asset, the buyer must provide a payment of the requested number of units of the requested asset. - Locking Value — in the exercise clause,
lock payment with sellerensures the payment is sent to the seller. In the expire clause,lock underlying with sellerensures that the underlying asset can only be sent back to the seller. - Unlocking Value — Since the exercise clause does not explicitly lock the underlying asset into a new contract, that asset must be explicitly unlocked with the statement,
unlock underlying. The buyer is then free to lock the value with any program they wish.
Market Applications of Ivy
By combining conditions like signature checks, time constraints, and value locks in creative ways, developers can implement sophisticated logic for controlling assets and re-imagine how markets interact with financial instruments. Let’s examine two categories of such applications: reducing risk and authorization.
Reducing risk
Many financial agreements involve one party taking a “security interest” in an asset owned by another party, or escrowing such an asset with a trusted third party. Contracts allow securing such assets in a way that reduces or eliminates the need to trust counterparties, third parties, or intermediaries. In computer science terms, Ivy contracts apply the “principle of least authority” to market interactions. By specifically limiting each party’s powers over an asset to those that are necessary to carry out the logic of the agreement, contracts can mitigate risks that are often implicit in financial agreements and products, and reduce costs due to reconciliation, dispute resolution, and enforcement.
Collateral
The following contract locks up the collateral for a loan, assuring the lender that she will be able to recover the collateral in case of default, while assuring the borrower that he will be able to recover the collateral by paying back the loan by the deadline.
contract LoanCollateral(
assetLoaned: Asset,
amountLoaned: Amount,
repaymentDue: Time,
lender: Program,
borrower: Program
) locks collateral {
clause repay() requires payment: amountLoaned of assetLoaned {
lock payment with lender
lock collateral with borrower
}
clause default() {
verify after(repaymentDue)
lock collateral with lender
}
}
Escrowed transfer
A contract can give an escrow agent the power to approve or reject an asset transfer between two parties, without giving that agent the ability to steal the asset being transferred.
contract Escrow(
agent: PublicKey,
sender: Program,
recipient: Program
) locks value {
clause approve(sig: Signature) {
verify checkTxSig(agent, sig)
lock value with recipient
}
clause reject(sig: Signature) {
verify checkTxSig(agent, sig)
lock value with sender
}
}
Covered call option
The CallOption contract introduced earlier locks up the underlying asset for a covered American-style covered call option. This assures the holder that the asset will be available on the exercise date, while simultaneously assuring the option writer that he will either receive the strike price (if the option is exercised) or the asset (if the option is not exercised).
Authorization
As shown in the LockWithPublicKey example above, contracts can be used to express authorization logic. Ivy can also be used to lock value with more complex conditions.
Custom authorization
Contracts can require arbitrary combinations of authorizations, such as requiring approval from 2-of-3 co-owners and approval from a trusted third party (such as a bank or exchange):
contract LockWithKeys(
ownerKey1: PublicKey,
ownerKey2: PublicKey,
ownerKey3: PublicKey,
thirdPartyKey: PublicKey
) locks value {
clause spend(
ownerSig1: Signature,
ownerSig2: Signature,
thirdPartySig: Signature
) {
verify checkTxMultiSig(
[ownerKey1, ownerKey2, ownerKey3],
[ownerSig1, ownerSig2]
)
verify checkTxSig(thirdPartyKey, thirdPartySig)
unlock value
}
}
Time-locked storage
A contract can guarantee that it cannot be unlocked at all until after a particular time. This can be used (alone or in combination with other contracts) to enforce periodic withdrawal limits or other security requirements.
contract LockInColdStorage(
ownerKey: PublicKey,
withdrawalTime: Time
) locks value {
clause spendWithOwnerKey(ownerSig: Signature) {
verify after(withdrawalTime)
verify checkTxSig(ownerKey, ownerSig)
unlock value
}
}
Temporary delegation
A contract could allow an owner to delegate spending power over her value to some other party for a limited period of time.
contract DelegateToKey(
ownerKey: PublicKey,
delegatedKey: PublicKey,
expiration: Time
) locks value {
clause spendWithOwnerKey(ownerSig: Signature) {
verify checkTxSig(ownerKey, ownerSig)
unlock value
}
clause spendWithDelegatedKey(delegatedSig: Signature) {
verify before(expiration)
verify checkTxSig(delegatedKey, delegatedSig)
unlock value
}
}
These examples are just the beginning. In future posts, we’ll examine security applications of Ivy in more detail, including its advantages when combined with hardware security modules. We will also talk about how smart contracts can be made confidential with our Confidential Assets solution.
Get Started with Ivy
At Chain, we obsess over developer experience. We know that designing the future of financial services is no small task and we want the tools you use to inspire you to think creatively about every problem you tackle. In addition, we believe non-developers — financial professionals, business leads, and lawyers— should be able to read and understand the logic of Ivy contracts, and apply them to solve problems in the financial industry.
As a first step toward this goal we built Ivy Playground, which interacts seamlessly with Chain Core. It is designed to teach you about the building blocks of Ivy and help you imagine, compose, and test contracts in a simple but powerful interface.
Now that you know a bit more about Ivy, it’s time to start writing your own contracts with Ivy Playground:
- Download Chain Core Developer Edition with Ivy Playground
- Follow the Ivy Playground Tutorial
- Check out the Ivy Documentation
- Join the Chain Slack Community to share and discuss
Acknowledgements
We’d like to thank Andrew Miller, Emin Gün Sirer, Patrick McCorry, Jeremy Rubin, Christopher Jeffrey, Steven McKie, Olaoluwa Osuntokun, and Kathleen Breitman for discussing Ivy with us before this release, and Nick Szabo for his feedback and inspiration throughout the language’s development.