Welcome

Last updated 4 months ago

Flint is a new type-safe, capabilities-secure, contract-oriented programming language specifically designed for writing robust smart contracts on Ethereum.

Medium article: Flint: A New Language for Safe Smart Contracts on Ethereum

Academic paper: Writing Safe Smart Contracts in Flint

Overview

Flint is still under active development and proposes a variety of novel contract-oriented features.

Caller Capabilities

Caller capabilities require programmers to think about who should be able to call the contract’s sensitive functions. Capabilities are checked statically for internal calls (unlike Solidity modifiers), and at runtime for calls originating from external contracts.

Example:

// State declaration
contract Bank {
var manager: Address
}
// Functions are declared in caller capability blocks,
// which specify which users are allowed to call them.
Bank :: (manager) { // manager is a state property.
// Only the manager of the Bank can call "clear".
func clear(address: Address) {
// body
}
}
// Anyone can initialize the contract.
Bank :: (any) {
public init(manager: Address) {
self.manager = manager
}
}

Immutability by default

Restricting writes to state in functions helps programmers more easily reason about the smart contract. A function which writes to the contract’s state needs to be annotated with the mutating keyword.

Example:

Bank :: (any) {
mutating func incrementCount() {
// count is a state property
count += 1
}
func getCount() -> Int {
return count
}
func decrementCount() {
// error: Use of mutating statement in a nonmutating function
// count -= 1
}
}

Asset types

Assets, such as Ether, are often at the center of smart contracts. Flint puts assets at the forefront through the special Asset trait.

Flint’s Asset type ensure a contract’s state always truthfully represents its Ether value, preventing attacks such as TheDAO.

A restricted set of atomic operations can be performed on Assets. It is impossible to create, duplicate, or lose Assets (such as Ether) in unprivileged code. This prevents attacks relating to double-spending and re-entrancy.

Example use:

Bank :: account <- (balances.keys) {
@payable
mutating func deposit(implicit value: inout Wei) {
// Omitting the next line would cause a compiler warning:
// the value received should be recorded.
balances[address].transfer(&value)
}
mutating func withdraw() {
// balances[account] is automatically
// set to 0 before transferring.
send(account, &balances[account])
}
}

Safer semantics

In the spirit of reducing vulnerabilities relating to unexpected language semantics, such as wrap-arounds due to integer overflows, Flint aims to provide safer operations. For instance, arithmetic operations on Int are safe by default: an overflow/underflow causes the Ethereum transaction to be reverted.