ivan pantuyev

Don't bring your own language: why general-purpose languages for smart contract development are a marketing trick

A few months ago I stumbled upon a tweet by @pranay01 that went like this:

Question: Why can’t Ethereum smart contracts be programmed in mainstream languages like JS, Go or Python? Why a new language(solidity) was developed and even now a different language (viper) is being developed. Though it is similar to Python, it is NOT python.

Pranay is not the only person to wonder the same. I have participated in multiple discussions on reddit where people expressed confusion, lament or outright animosity toward Ethereum’s choice to not invest in compilers for, say, C++. Vitalik replied to Pranay, but due to the terseness of Twitter communication I wanted to expand on Vitalik’s response. I want to argue that any blockchain project that presents the ability to write smart contracts in C++ or any other general-purpose language as a strength is being at least somewhat dishonest or simply incompetent.

Programmers have to switch languages

I often hear arguments that go like this: “surely it’d be beneficial for a developer to be able to write a smart contract in the language that they are already familiar with!” I think this reasoning suggests that the speaker has little or no experience with software development. Let me explain why.

At my last place of employment (a large HR software company) I have had to interview potential candidates and give them coding challenges. Our team wrote very large web applications in Typescript and JS. What language would you guess we demanded that the challenges be written in? Any. Our office was not unique in thinking that if you are focused only on one language (“I am a Python programmer”) and cannot in reasonable time pick-up some C-like language, then you should probably not be working on an application of any complexity at all.

Whether a language uses curly braces or not should not determine if you can use it. The language that should be used is one that’s right for the job or that your team is already using. After all, the language that a project is using today might be superseded tomorrow by a completely different one. Sure, it would be convenient to write a contract in Python if you already know Python, but individual convenience is of minimal importance in programming world.

Different domains have their specific requirements

Proliferation of programming bootcamps and ubiquity of self-taught programmers seem to have given birth to the idea that programming is easy. By “easy” I mean that one does not need decades of experience to make something that people use. That is true to a certain extent, but programming a web application on top of a well laid-out framework is one thing, another thing is developing software that controls fuel delivery to the engines of an airplane or a phone switch. The security and reliability considerations in such niche applications are so different from what an average programmer has to deal with that they warrant the use of special-purpose tools and languages. Immutable smart contracts that potentially manage large amounts of money are more like airplane software than a web application.

Solidity is an attempt at a safer and more easily auditable language

Solidity, the much maligned language in a lot of smart contract language discussions, is surely no walk in the park. But there are very good reasons why the Ethereum foundation (and some other projects, of course) have chosen to develop their own language. It is not like they have too much time on their hands and have created a language for their edification (although some on people social media claim so). As the few high profile smart contract hacks shown (The DAO, Parity multisig wallet, etc.) - much is at stake when writing a smart contract. Solidity was developed in hopes that it would help write more secure and more auditable applications. If you talk to people with experience coding in the language you will often hear them complaining that Solidity is not specialized enough and not high-level enough. In other words it resembles a general-purpose language too much - it suffers from resembling C++, Python, JS and other languages that have no features and auditability requirements specific to writing smart contracts.

The future

Most recent round of Ethereum grants has awarded a sum of money to a little known project - Flint language. To most people it will look like a freak language, but it is born out of experience. Flint is still very much in development and, honestly, I am a bit wary of some of its syntax, but the features it introduces are very exciting and give a glimpse of what contract languages of the future might look like.

The infamous The DAO hack and the more recent Spankchain hack are both examples of the reentrancy vulnerability, where a contract the user trusts executes code in a separate contract, which in turn uses it’s trust to execute unsafe code in the original calling contract. The Ouroboros hack. Flint has multiple features which would have saved everybody a lot of drama if The DAO was written in the language.

One of those features is “caller protection”. (By the way, the documentation for Flint is still limited, so perhaps I misunderstand some features, like in this case whether tx.origin or msg.sender are checked. I certainly assume the latter, but don’t throw rocks at me if I am wrong. In any case it’s not the only feature that is designed to prevent this attack).

contract Bank {
  var manager: Address
}

// Functions are declared in protection blocks,
// which specify which users are allowed to call them.
Bank :: (manager) { // manager is a state property.

  // Only `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
  }
}

I assume the code should be mostly self-explanatory. But the idea is this: the developer is forced to decide who is able to call a method and to explicitly specify the address. Just this simple feature would get rid of a lot of potential bugs, including reentrancy (unless, of course, the develope puts any over every function, in which case their involvement in writing contracts should be reconsidered). Funky? Perhaps. Safer? Yeaaaah.

Another thing that irks me about Solidity and essentially every other contract language is that a variable that tracks the amount of cryptocurrency that a contract is storing is just that - a regular variable. And it is up to the developer to keep the mapping between the contract’s funds and their actual owners in sync. The potential for error is vast, as exemplified by, once again, The DAO hack. The feature of Flint that addresses this is called “Assets”.

Bank :: account <- (balances.keys) {
  @payable
  mutating func deposit(implicit value: inout Wei) {
    // Omitting this line causes 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])
  }
}

Now, this code might be a bit confusing but the most important line is this:

    // balances[account] is automatically set to 0
    // before transferring.
    send(account, &balances[account])

If one was to write asset transfer code in some other language two steps would have been required: firstly the developer would need to subtract the value from a contract variable and then forward the asset to their destination. If the two actions are ever reversed you’d be setting yourself up for attack. Flint makes such an operation atomic, saving the developer time and mental effort and making reentrancy a thing of the past. Loud applause from the developer section.

Conclusion

Cryptosphere is big. There are lots of concepts, lots of news and events. It is easy to get lost. Plenty of cryptocurrencies exploit the learning curve by spreading if not lies, then misrepresentation of facts. One of those marketing strategies is the advertising of an array of general-purpose languages as options for contract development. Sometimes this is also coupled with mocking of other projects who have chosen a domain-specific language. I encourage you to be cautious of such behavior. I am certain that general-purpose languages have no future on the blockchain.