When starting a new web3 project, it’s important to make the right choices about the blockchain and smart contract language. These choices can significantly impact the overall success of your project as well as your success as a developer.
In this article, we'll compare three popular smart contract programming languages:
- Solidity: used in Ethereum and other EVM-based platforms
- Cadence: used in the Flow blockchain
- Move: used in the Sui/Aptos blockchain
We'll explain the concepts and characteristics of each language in simple terms, making it easier for beginners to understand. Let’s dive in.
Solidity: The Foundation of Ethereum Smart Contracts
Solidity is a high-level, object-oriented language used to build smart contracts in platforms like Ethereum. Initially, Solidity aimed to be user-friendly, attracting developers by resembling JavaScript and simplifying learning. While it still values user-friendliness, its focus has shifted to enhancing security. Currently, Solidity has quite a few security pitfalls developers need to be aware of.
Some Solidity features include:
- Syntax and Simplicity: Solidity uses clear, explicit code with a syntax similar to JavaScript, prioritizing ease of understanding for developers.
- Security Focus: Solidity emphasizes secure coding practices and highlights risky constructs like gas usage.
- Statically Typed: The language enforces data type declarations for variables and functions.
- Inheritance and Libraries: Solidity supports features like inheritance, libraries, and complex user-defined types.
Cadence: Empowering Digital Assets on Flow
Cadence is designed by Flow, a blockchain known for helping to make web3 mainstream and working with major brands like Disney and the NBA. It ensures secure, clear, and approachable smart contract development.
Some Cadence features include:
Type Safety: The language enforces strict type checking to prevent common errors.
Resource-oriented Programming: Resources are unique, linear types that can only move between accounts and can’t ever be copied or implicitly discarded. If a function fails to store a Resource obtained from an account in the function scope during development, then semantic checks will flag an error. The run-time enforces the same strict rules in terms of allowed operations. Therefore, contract functions that do not properly handle Resources in scope before exiting will abort, reverting them to the original storage.
These Resource features make them perfect for representing both fungible and non-fungible tokens. Ownership is tracked according to where they are stored, and the assets can’t be duplicated or accidentally lost since the language itself enforces correctness.
- Capability-based Security: If one person wants to access another person's stored items, the first person needs a permission called a Capability. Using Capabilities allows you to let others access your stored items remotely.
There are two types of Capabilities: public and private. If someone wants to allow everyone to access their items, they can share a public Capability. For instance, an account can use a public Capability to accept tokens from anyone. On the other hand, someone can also give private Capabilities to specific people, allowing them to access certain features. For example, in a project that involves unique digital items, the project owners might give specific people an "administrator Capability" that lets them create new items.
(image from Guide for Solidity developers | Flow Developer Portal)
- Built-in Pre- and Post-Conditions: Functions have predefined conditions for safer execution.
- Optimized for Digital Assets: Cadence's focus on resource-oriented programming makes it ideal for managing digital assets in areas such as onchain games.
- Freedom from msg.sender: To grasp the importance of these new ideas, let's take a quick look at some history. In 2018, the Dapper Labs team began working on Cadence as a new programming language. They faced challenges with Solidity because of its limitations. The main frustration in building decentralized apps came from the way contracts were accessed using addresses, making it difficult to combine contracts.
Composability in Web3
Now, imagine contracts as Lego building blocks. Composability in web3 means one contract can be used as a foundation for others, adding their features together.
For instance, if a contract records game results on a blockchain, another contract can be built to show the best players. Another one could go even further and use past game results to predict future game odds for betting. But here's the catch: Because of how Solidity works, contracts can only talk to one another if the first contract has permission to access the second one, even if users can access both.
In Solidity, who can do what is controlled by protected functions in contracts. This means contracts know and check who is trying to access their protected areas.
(image from Guide for Solidity developers | Flow Developer Portal)
Cadence changes how access works. Instead of using the old way where contracts need permission, it uses Capabilities. When you have a Capability, you can use it to get to a protected item such as a function or resource. This means the contract no longer has to define who's allowed access. You can only get to the protected item if you have a Capability, which you can use with "borrow()". So, the old "msg.sender" way isn't needed anymore!
(image from Guide for Solidity developers | Flow Developer Portal)
The effects of composability are important. When contracts don't need to know beforehand who they're interacting with, users can easily interact with multiple contracts and their functions during a transaction if they have the right permissions (Capabilities). This also allows contracts to interact with one another directly, without needing special permissions or preparations. The only condition is that the calling contract must have the required Capabilities.
Move: Safeguarding Digital Assets on Sui/Aptos
Move, used in the Sui/Aptos blockchain, addresses challenges posed by established languages like Solidity. It ensures scarcity and access control for digital assets.
Move's features include:
- Preventing Double-spending: Move prevents the creation or use of assets more than once, ensuring robust blockchain applications.
- Ownership and Rights Control: Developers have precise control over ownership and associated rights.
- Module Structure: In Move, a smart contract is called a module, emphasizing modularity and organization.
- Bytecode Verifier: Move employs static analysis to reject invalid bytecode, enhancing security.
- Standard Library: Move includes a standard library for common transaction scripts.
Creating Smart Contracts
Let's illustrate the differences by comparing a simple smart contract that increments a value in Cadence, Solidity, and Move.
Solidity Example
In Solidity, creating a contract that increments a value involves defining a contract, specifying the count variable, and creating functions to manipulate it. It uses explicit syntax for variable visibility and function declarations.
// SPDC-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Counter {
uint public count;
// function to get the current count
function get() public view returns (uint) {
return count;
}
// function to increment count by 1
function inc() public {
count += 1;
}
// function to decrement count by 1
function dec() public {
count -=1;
}
}
Cadence Example
Cadence's approach to incrementing a value is similar but emphasizes clarity. It utilizes a resource-oriented structure and straightforward syntax, making it easier for developers to create and manage digital assets.
pub contract Counter {
pub var count: Int
// function to increment count by 1
pub fun increment() {
self.count = self.count +1
}
// function to decrement count by 1
pub fun decrement() {
self.count = self.count – 1
}
pub fun get(): Int {
return self.count
}
init() {
self.count = 0
}
}
Solidity versus Cadence Syntax Differences
In Solidity, the visibility keyword comes before or after variable/function names, whereas Cadence consistently follows the visibility-type-name sequence.
*Scalability and Upgradability *
Flow's network boasts higher transaction throughput than Ethereum, making Cadence more scalable. Additionally, Flow's support for contract updates enhances development.
Move Example
Move introduces new concepts like modules, resources, and ownership control. A Move module creates an Incrementer resource, requiring the owner's signature for operations.
module incrementer_addr::increment {
use aptos_framework::account;
use std::signer;
struct Incrementer has key {
count: u64,
}
public entry fun increment(account: &signer) acquires Incrementer {
let signer_address = signer::address_of(account);
let c_ref = &mut borrow_global_mut<Incrementer>(signer_address).count;
*c_ref = *c_ref +1
}
public entry fun create_incrementer(account: &signer){
let incrementer = Incrementer {
count: 0
};
move_to(account, incrementer);
}
}
*Composite Types and Turing Completeness *
All three languages support composite types, allowing complex types from simpler ones. All are Turing complete, meaning they can handle any computation given enough resources.
Resource-Oriented versus Object-Oriented
While Solidity and Move require compilation, Cadence is interpreted. Cadence and Move employ a resource-oriented approach, securing digital ownership in one location.
Conclusion: Choosing the Right Programming Language
When selecting a programming language like Solidity, Cadence, or Move, consider the needs of your project.
- Solidity: Solidity is commonly used, but it might not be very easy to work with. Developers need to be careful of the security pitfalls and understand best practices.
- Cadence: Mainly used for digital assets, Cadence is a newer language that focuses on security, is easy to understand, and provides developers with a superior experience.
- Move: Move is based on Rust, a more complex language. Rust can be more difficult to learn and understand. Move is a new language, and it doesn't have many tools, resources, or a big community.
Ultimately, your choice will impact your project's success, so make an informed decision and enjoy your journey as a web3 developer!
Top comments (0)