1 of 33

Slang: building Solidity Compiler APIs

from a declarative language specification

Solidity Summit - Istanbul - November 2023

2 of 33

Nomic Foundation

A non-profit dedicated to Ethereum developers. We provide open-source software to empower developers today and ensure Ethereum's continued success in the future.

Hardhat

Slang

EDR

Build, Test, Deploy

Analyze

Execute

3 of 33

Agenda

  • Evolution of Solidity over the years.
  • Impact on the Ecosystem.
  • Introducing a Language Specification.
  • Building Slang: Modular Solidity Compiler APIs.
  • Using Slang: Analyzing Solidity Contracts.

4 of 33

Evolution of Solidity over the years

  • Rapid evolution since its inception in 2015.
  • Solidity code lives forever!
  • Keeping track of language updates:
    • Syntax.
    • Semantics.
    • Type System.
    • Built-in functions and variables.
    • Code Generation.
    • Compiler Interface.
  • Examples.

5 of 33

Evolution of Solidity over the years

Which of these are valid in a top-level position in a source file?

contract

library

interface

struct

enum

function

constant

error

type

using

event

6 of 33

  • valid in all versions
  • valid in all versions
  • valid in all versions

Evolution of Solidity over the years

Which of these are valid in a top-level position in a source file?

contract

library

interface

struct

enum

function

constant

error

type

using

event

7 of 33

  • valid in all versions
  • valid in all versions
  • valid in all versions
  • valid after 0.6.0
  • valid after 0.6.0

Evolution of Solidity over the years

Which of these are valid in a top-level position in a source file?

contract

library

interface

struct

enum

function

constant

error

type

using

event

8 of 33

  • valid in all versions
  • valid in all versions
  • valid in all versions
  • valid after 0.6.0
  • valid after 0.6.0
  • valid after 0.7.1

Evolution of Solidity over the years

Which of these are valid in a top-level position in a source file?

contract

library

interface

struct

enum

function

constant

error

type

using

event

9 of 33

  • valid in all versions
  • valid in all versions
  • valid in all versions
  • valid after 0.6.0
  • valid after 0.6.0
  • valid after 0.7.1

Evolution of Solidity over the years

Which of these are valid in a top-level position in a source file?

contract

library

interface

struct

enum

function

constant

error

type

using

event

  • valid after 0.7.4

10 of 33

  • valid in all versions
  • valid in all versions
  • valid in all versions
  • valid after 0.6.0
  • valid after 0.6.0
  • valid after 0.7.1

Evolution of Solidity over the years

Which of these are valid in a top-level position in a source file?

contract

library

interface

struct

enum

function

constant

error

type

using

event

  • valid after 0.7.4
  • valid after 0.8.4

11 of 33

  • valid in all versions
  • valid in all versions
  • valid in all versions
  • valid after 0.6.0
  • valid after 0.6.0
  • valid after 0.7.1

Evolution of Solidity over the years

Which of these are valid in a top-level position in a source file?

contract

library

interface

struct

enum

function

constant

error

type

using

event

  • valid after 0.7.4
  • valid after 0.8.4
  • valid after 0.8.8

12 of 33

  • valid in all versions
  • valid in all versions
  • valid in all versions
  • valid after 0.6.0
  • valid after 0.6.0
  • valid after 0.7.1

Evolution of Solidity over the years

Which of these are valid in a top-level position in a source file?

contract

library

interface

struct

enum

function

constant

error

type

using

event

  • valid after 0.7.4
  • valid after 0.8.4
  • valid after 0.8.8
  • valid after 0.8.13

13 of 33

  • valid in all versions
  • valid in all versions
  • valid in all versions
  • valid after 0.6.0
  • valid after 0.6.0
  • valid after 0.7.1

Evolution of Solidity over the years

Which of these are valid in a top-level position in a source file?

contract

library

interface

struct

enum

function

constant

error

type

using

event

  • valid after 0.7.4
  • valid after 0.8.4
  • valid after 0.8.8
  • valid after 0.8.13
  • valid after 0.8.22

14 of 33

Evolution of Solidity over the years

What is the result of calling a function on another contract?

someContract.call("f");

15 of 33

Evolution of Solidity over the years

What is the result of calling a function on another contract?

someContract.call("f");

  • Before 0.5.0: it would return a boolean indicating whether the call succeeded or not:

bool success = someContract.call("f");

  • After 0.5.0: it returns a tuple of both a success boolean and the returned bytes:

(bool success, bytes memory data) = someContract.call("f");

16 of 33

Given the following function:

function two_power(uint8 exponent) returns (uint256 result) {

return 2 ** exponent;

}

What is the result of calling two_power(16)?

Evolution of Solidity over the years

17 of 33

Given the following function:

function two_power(uint8 exponent) returns (uint256 result) {

return 2 ** exponent;

}

What is the result of calling two_power(16)?

  • Before 0.7.0: it would return 0, as the calculation was performed using the type of exponent (uint8), which would overflow. The compiler would also warn about it.
  • After 0.7.0: it returns the expected value 65536, since the calculation is now performed using the type of the base literal 2 (uint256), which won’t overflow.

Evolution of Solidity over the years

18 of 33

Impact on the Ecosystem

  • Impact on downstream language tools:
    • Maintaining legacy behavior.
    • Duplicated efforts across different projects.
  • Impact on the user experience.

19 of 33

Introducing: Slang’s Solidity Language Specification

20 of 33

  • Introducing a Language Specification:
    • Formal.
    • Versioned.
    • Comprehensive.
  • The official docs are a great starting point, but not enough.
  • Collaboration with the Solidity Language team.

Slang’s Solidity Language Specification

21 of 33

Slang’s Solidity Language Specification

  • Starting with the syntax.
  • Moving to the semantics.
  • Keeping it up to date.
  • Examples.

22 of 33

23 of 33

24 of 33

Introducing: Slang’s Modular Solidity Compiler APIs

25 of 33

Slang’s Modular Solidity Compiler APIs

Building on top of the specification:

  • Modular APIs, focused on tooling.
  • Covering all Solidity versions.
  • Extensible, and self-contained.
  • Built in Rust, distributed in multiple languages.

26 of 33

Our Alpha release is out:

  • Parser API for all language versions since 0.4.11.
  • Error recovery from incomplete/invalid input..
  • An accurate (byte-for-byte) Concrete Syntax Tree (CST).

Slang’s Modular Solidity Compiler APIs

27 of 33

Currently working on our Beta release:

  • A strongly-typed Abstract Syntax Tree (AST).
  • APIs for visiting, modifying, and converting source trees.
  • Type resolution and binding information.
  • Integration with our VS Code extension (Solidity by Nomic Foundation).

And last but not least, working with language tooling authors to integrate Slang, and build our roadmap based on user feedback.

Slang’s Modular Solidity Compiler APIs

28 of 33

Using Slang: Analyzing Solidity Contracts

1 import assert from "assert";

2 import {Language} from "@nomicfoundation/slang/language";

3 import {ProductionKind, RuleKind, TokenKind} from "@nomicfoundation/slang/kinds";

4

5 const source = "contract Foo {}";

6 const language = new Language("0.8.0");

7

8 const output = language.parse(ProductionKind.ContractDefinition, source);

9 assert(output.isValid);

10 assert(output.errors().length == 0);

29 of 33

Using Slang: Analyzing Solidity Contracts

12 // const source = "contract Foo {}";

13 const tree = output.tree();

14 assert(tree.kind == RuleKind.ContractDefinition);

15

16 const children = tree.children();

17 assert(children[0]!.kind == TokenKind.ContractKeyword); // "contract"

18 assert(children[1]!.kind == RuleKind.LeadingTrivia); // " "

19 assert(children[2]!.kind == TokenKind.Identifier); // "Foo"

20 assert(children[3]!.kind == RuleKind.LeadingTrivia); // " "

21 assert(children[4]!.kind == TokenKind.OpenBrace); // "{"

22 assert(children[5]!.kind == TokenKind.CloseBrace); // "}"

30 of 33

Using Slang: Analyzing Solidity Contracts

24 // const source = "contract Foo {}";

25 const cursor = output.createTreeCursor();

26

27 cursor.goToNthChild(2);

28 assert(cursor.node().kind == TokenKind.Identifier);

29

30 cursor.goToParent();

31 assert(cursor.node().kind == RuleKind.ContractDefinition);

32

33 const identifier = cursor.findTokenWithKind([TokenKind.Identifier]);

34 assert(identifier?.text == "Foo");

31 of 33

Useful Links

32 of 33

Please come chat with us after the talk. We would love to hear from you!

The Slang team at Nomic Foundation is currently three people, and we are hiring:

Questions?

Omar Tawfik

Igor Matuszewski

Antony Blakey

33 of 33

Slang’s Website and Documentation:

nomicfoundation.github.io/slang

Questions?

📘

Join us on our Telegram channel:

t.me/+pxApdT-Ssn5hMTFh