æpps Update: Sophia Smart Contract Language

At æternity we are continuing to migrate our æpps to the æternity Testnet in preparation for the Mainnet release. In the meantime we are working on a number of developer tools and tutorials, which we would like to share in upcoming æpps updates.

At the time of the Mainnet release, æternity will offer two smart contract languages: Sophia and Varna. We will discuss Varna in a separate post. Today we are focusing on Sophia.

Sophia Smart Contract Language

Sophia is the more expressive of the two smart contract languages. In the next few paragraphs we’ll go over some of the features which make it a superior smart contract language. We have written a tutorial which explains and illustrates some of these features as code examples.

Functional Programming

Sophia is a functional language in the ML family. We’ve chosen the functional programming paradigm because it makes it easier to write correct programs — something which is particularly important with smart contracts. The qualities of functional languages which make them (potentially) more reliable than programs written using the imperative paradigm include restricted mutable state, fewer side-effect, easier to read code components, better handling of concurrency, and ease of debugging and testing.

State

Sophia does not have arbitrary mutable state, but only a limited form of state associated with each contract instance. An example of state specific code and ways to access the state can be found here.

Strongly Typed

Sophia is a strongly typed language, which means that the compiler checks if the value assigned to a variable is indeed the type that was declared for the this variable at time of compiling. Being able to specify and automatically prove the properties of a smart contract make Sophia a safer smart contract language.

First Class Objects

In Sophia the following components are first class objects: smart contracts, oracles, names, and state channels. This means that they are directly available, instead of defined by code libraries making these objects easier to access, cheaper while reducing the complexity of the code.

Pattern Matching

Sophia features pattern matching based on ReasonML allowing for a streamlined control flow and ability to construct easy to read control statements.

A Crowdfunding Example

To illustrate some of the features mentioned above we have written a simple example of a Crowdfunding Campaign smart contract, which we would like to share:

/*
* A simple crowd-funding example
*/
contract FundMe =
record spend_args = { recipient : address,
amount : int }
record state = { contributions : map(address, int),
total : int,
beneficiary : address,
deadline : int,
goal : int }
private function require(b : bool, err : string) =
if(!b) abort(err)
private function spend(args : spend_args) =
Chain.spend(args.recipient, args.amount)
public function init(beneficiary, deadline, goal) : state =
{ contributions = {},
beneficiary = beneficiary,
deadline = deadline,
total = 0,
goal = goal }
private function is_contributor(addr) =
Map.member(addr, state.contributions)
public stateful function contribute() =
if(Chain.block_height >= state.deadline)
spend({ recipient = Call.caller, amount = Call.value }) // Refund money
false
else
let amount =
Map.lookup_default(Call.caller, state.contributions, 0) + Call.value
put(state{ contributions[Call.caller] = amount,
total @ tot = tot + Call.value })
true
public stateful function withdraw() =
if(Chain.block_height < state.deadline)
abort("Cannot withdraw before deadline")
if(Call.caller == state.beneficiary)
withdraw_beneficiary()
elif(is_contributor(Call.caller))
withdraw_contributor()
else
abort("Not a contributor or beneficiary")
private stateful function withdraw_beneficiary() =
require(state.total >= state.goal, "Project was not funded")
spend({recipient = state.beneficiary,
amount = Contract.balance })
put(state{ beneficiary = #0 })
private stateful function withdraw_contributor() =
if(state.total >= state.goal)
abort("Project was funded")
let to = Call.caller
spend({recipient = to,
amount = state.contributions[to]})
put(state{ contributions @ c = Map.delete(to, c) })

Near Future

In addition to our ongoing æpps progress, we are working on a number of new developer tools which we will be announcing in the near future. Stay tuned for more and as always feel free to contact us directly in the Forum or in GitHub.


We recently published an æpps FAQ that might have the answer that you are looking for. Access it here.

Interested in æternity? Get in touch:

GitHub | Forum | Reddit | Telegram | Twitter | Facebook | Mail


Leave a Reply

Your email address will not be published. Required fields are marked *