Clarc compiles Clarity smart contracts into Ethereum virtual machine (EVM) bytecode.
More specifically, the Clarc compiler, called clarc
, parses .clar
files and
compiles them into an equivalent EVM bytecode program that runs on the Ethereum
blockchain.
Note: Here be dragons. This is a pre-alpha, work-in-progress project. Assume nothing works, and you may be pleasantly surprised on occasion.
The latest release binaries for macOS and Linux are available here:
To install, just download and untar the archive and then copy the resulting
binary to /usr/local/bin
, as follows:
wget https://github.com/weavery/clarc/releases/download/0.5.0/clarc-0.5.0-macos.tar.gz
tar xf clarc-0.5.0-macos.tar.gz
sudo install clarc-0.5.0-macos /usr/local/bin/clarc
wget https://github.com/weavery/clarc/releases/download/0.5.0/clarc-0.5.0-linux.tar.gz
tar xf clarc-0.5.0-linux.tar.gz
sudo install clarc-0.5.0-linux /usr/local/bin/clarc
If you wish to try out the latest and greatest Clarc, you will need to build it from source code yourself, which entails setting up an OCaml development environment. Reserve at least half an hour of time and see further down in this document for the particulars.
To view Clarc's built-in man page that documents all command-line options, run:
clarc --help
To compile the Clarity counter.clar
example contract to programmer-readable
output, known as symbolic opcode, run:
clarc -t opcode counter.clar
The previous writes out the compiled program to standard output, which is helpful during development and debugging.
To compile the Clarity counter.clar
example contract to deployable
bytecode, run:
clarc -t bytecode counter.clar
Alternatively, you can specify an output file name in the usual way, with the
target type inferred from the output file extension (.bin
for bytecode,
in keeping with the Solidity compiler):
clarc -o counter.bin counter.clar
MyEtherWallet is the easiest way to deploy the generated contracts:
The currently tested contracts, deployed to the public Ropsten testnet, are:
Contract ID | Contract Code | Contract Bytecode | Contract ABI |
---|---|---|---|
0x8a90b1e93020933295b3bd4ce2317062319351d4 | counter.clar |
counter.bin |
counter.json |
0x2e2487c64b1420111e8d66d751f75f69515c5476 | kv-store.clar |
kv-store.bin |
kv-store.json |
0x9a1b29fc432af1e37af03ed2fee00d742ff7372f | panic.clar |
panic.bin |
panic.json |
MyEtherWallet is the easiest way to interact with these deployed contracts.
(define-data-var counter int 0)
(define-read-only (get-counter)
(ok (var-get counter)))
(define-public (increment)
(begin
(var-set counter (+ (var-get counter) 1))
(ok (var-get counter))))
(define-public (decrement)
(begin
(var-set counter (- (var-get counter) 1))
(ok (var-get counter))))
$ clarc counter.clar -t opcode
PUSH1 0x00 PUSH1 0x00 SSTORE PUSH1 0x64 DUP1 PUSH1 0x10 PUSH1 0x00 CODECOPY
PUSH1 0x00 RETURN PUSH1 0xe0 PUSH1 0x02 EXP PUSH1 0x00 CALLDATALOAD DIV DUP1
PUSH4 0x8ada066e EQ PUSH1 0x28 JUMPI DUP1 PUSH4 0xd09de08a EQ PUSH1 0x36
JUMPI DUP1 PUSH4 0x2baeceb7 EQ PUSH1 0x4d JUMPI STOP JUMPDEST POP PUSH1 0x00
SLOAD PUSH1 0x00 MSTORE PUSH1 0x20 PUSH1 0x00 RETURN STOP JUMPDEST POP
PUSH1 0x01 PUSH1 0x00 SLOAD ADD PUSH1 0x00 SSTORE PUSH1 0x00 SLOAD PUSH1 0x00
MSTORE PUSH1 0x20 PUSH1 0x00 RETURN STOP JUMPDEST POP PUSH1 0x01 PUSH1 0x00
SLOAD SUB PUSH1 0x00 SSTORE PUSH1 0x00 SLOAD PUSH1 0x00 MSTORE PUSH1 0x20
PUSH1 0x00 RETURN STOP
$ clarc counter.clar -t bytecode
600060005560648060106000396000f360e060020a6000350480638ada066e146028578063d09de08a1460365780632baeceb714604d57005b5060005460005260206000f3005b5060016000540160005560005460005260206000f3005b5060016000540360005560005460005260206000f300
Clarc is written in OCaml, an excellent programming language for crafting compiler toolchains.
Clarc is a standard multi-pass compiler consisting of the following stages:
The Clarity parser and abstract syntax tree (AST) are maintained as a subproject in an OCaml library called Clarity.ml. The library enables anyone familiar with OCaml to quickly and easily develop more best-of-class tooling for Clarity contracts.
See Clarity.ml's lexer.mll
for the lexical analyzer source code.
See Clarity.ml's parser.mly
and parse.ml
for the parser source code.
See Clarity.ml's grammar.ml
for the structure of the Clarity AST.
This section documents how to get set up with a development environment for building Clarc from source code. It is only of interest to people who wish to contribute to Clarc.
The following baseline tooling is required in order to build Clarc from source code:
We would recommend you don't install OCaml from a package manager.
Rather, get set up with OPAM and then let OPAM install the correct version of OCaml as follows:
opam init -c 4.11.1 # if OPAM not yet initialized
opam switch create 4.11.1 # if OPAM already initialized
Once OPAM and OCaml are available, install Dune as follows:
opam install dune
The following OCaml tools and libraries are required in order to build Clarc from source code:
-
Alcotest for unit tests
-
Clarity.ml for parsing Clarity code
-
Cmdliner for the command-line interface
-
Cppo for code preprocessing
-
Cryptokit for the Keccak-256 hash function
-
ISO8601 for date handling
-
Num for 128-bit integers
-
Ocolor for terminal colors
These aforementioned dependencies are all best installed via OPAM:
opam install -y alcotest cmdliner cppo cryptokit iso8601 num ocolor
opam pin add -y clarity-lang https://github.com/weavery/clarity.ml -k git
alias clarc='dune exec bin/clarc/clarc.exe --'
clarc --help
git clone https://github.com/weavery/clarc.git
cd clarc
dune build
sudo install _build/default/bin/clarc/clarc.exe /usr/local/bin/clarc
We thank the Stacks Foundation for sponsoring the development of Clarc.
We thank Blockstack and Algorand for having developed the Clarity language, an important evolution for the future of smart contracts.
Feature | Type | Status | Notes |
---|---|---|---|
* |
function | ✅ | For two parameters. Without overflow checking. |
+ |
function | ✅ | For two parameters. Without overflow checking. |
- |
function | ✅ | For two parameters. Without underflow checking. |
/ |
function | ✅ | For two parameters. Without division-by-zero checking. |
< |
function | ✅ | |
<= |
function | ✅ | |
> |
function | ✅ | |
>= |
function | ✅ | |
and |
operator | ✅ | For two parameters. |
append |
function | ✅ | |
as-contract |
operator | 🚧 | |
as-max-len? |
operator | 🚧 | |
asserts! |
function | ✅ | |
at-block |
operator | ❌ | Not implemented yet. |
begin |
operator | 🚧 | |
block-height |
keyword | ✅ | |
buff |
literal | ✅ | |
burn-block-height |
keyword | ✅ | |
concat |
function | ✅ | Only for lists. |
contract-call? |
operator | ❌ | Not implemented yet. |
contract-caller |
keyword | ✅ | |
contract-of |
operator | ❌ | Not implemented yet. |
default-to |
function | ✅ | |
err |
function | ✅ | |
false |
literal | ✅ | |
filter |
function | 🚧 | |
fold |
function | 🚧 | |
ft-get-balance |
function | 🚧 | |
ft-mint? |
function | 🚧 | |
ft-transfer? |
function | 🚧 | |
get |
operator | 🚧 | |
get-block-info? |
operator | ❌ | Not implemented yet. |
hash160 |
function | ✅ | |
if |
operator | ✅ | |
impl-trait |
operator | ❌ | Not implemented yet. |
int |
literal | ✅ | |
is-eq |
function | ✅ | For two parameters. |
is-err |
function | ✅ | |
is-in-regtest |
keyword | ✅ | |
is-none |
function | ✅ | |
is-ok |
function | ✅ | |
is-some |
function | ✅ | |
keccak256 |
function | ✅ | |
len |
function | ✅ | Only for literals. |
let |
operator | 🚧 | |
list |
function | ✅ | |
map |
function | 🚧 | |
map-delete |
function | 🚧 | |
map-get? |
function | ✅ | |
map-insert |
function | 🚧 | |
map-set |
function | 🚧 | |
match |
operator | ✅ | |
mod |
function | ✅ | Without division-by-zero checking. |
nft-get-owner? |
function | 🚧 | |
nft-mint? |
function | 🚧 | |
nft-transfer? |
function | 🚧 | |
none |
literal | ✅ | |
not |
function | ✅ | |
ok |
function | ✅ | |
or |
operator | ✅ | For two parameters. |
pow |
function | ✅ | Without overflow checking. |
principal |
literal | 🚧 | |
principal-of? |
function | 🚧 | |
print |
function | ✅ | Only for literals. Without a meaningful return value. |
secp256k1-recover? |
function | ❌ | Not implemented yet. |
secp256k1-verify |
function | ❌ | Not implemented yet. |
sha256 |
function | ✅ | |
sha512 |
function | ❌ | Not implemented yet. |
sha512/256 |
function | ❌ | Not implemented yet. |
some |
function | ✅ | |
sqrti |
function | ❌ | Not implemented yet. |
string |
literal | ✅ | |
stx-burn? |
function | ❌ | Not supported. |
stx-get-balance |
function | ❌ | Not supported. |
stx-liquid-supply |
keyword | ❌ | Not supported. |
stx-transfer? |
function | ❌ | Not supported. |
to-int |
function | 🚧 | |
to-uint |
function | 🚧 | |
true |
literal | ✅ | |
try! |
function | ✅ | |
tuple |
operator | 🚧 | |
tx-sender |
keyword | ✅ | |
uint |
literal | ✅ | |
unwrap! |
function | ✅ | |
unwrap-err! |
function | ✅ | |
unwrap-err-panic |
function | ✅ | |
unwrap-panic |
function | ✅ | |
use-trait |
operator | ❌ | Not implemented yet. |
var-get |
operator | ✅ | |
var-set |
operator | ✅ | |
xor |
function | ✅ |
Legend: ❌ = not supported. 🚧 = work in progress. ✅ = supported.