🌴Sway from Solidity: Program Types

ztzt
4 min read

Sway is the smart contract language for FuelVM. In this article, I listed major differences between Sway programs and Solidity programs. I hope this article helps people with a Solidity background to get started with sway quickly and easily.

Solidity only has two types of programs, Contract and Library. Sway also has two additional program types besides Contract and Library - Predicate and Script.

The major differences are outlined below:

Contract

  • Sway contract must define or import an ABI declaration and implement all the methods defined in the ABI implementation.

  • No contract inheritance.

  • Sway contract cannot create new contracts from a contract.

    • In solidity, you can create new contracts using create or create2 from a contract.

    • However, you can check if a deployed contract matches the code by checking the bytecode root. (example)

  • All the storage variables must be defined in Storage{}.

  • Apart from variables defined in Storage{}, variables are immutable by default.

    • To make them mutable, you need to mark the variable with mut.

        let mut amount = 7u8;
      
  • There is no constructor in Sway contract

    • You need to define a function to initialize the contract
  • No auto-generated getter for storage variables.

    • You need to define getter functions yourself.
  • There are no external, public or internal functions in Sway.

    • All functions defined in ABI must be implemented

    • All the implemented functions are visible to the public

    • Functions defined outside of the ABI implementation are not accessible to the public. It works like internal/private functions in Solidity.

  • Functions are pure by default in sway

    • If you want to define whether a function can read/write storage, use storage attribute

        #[storage(read)]
        fn get_amount() -> u64 {
            ...
        }
      
        #[storage(read, write)]
        fn increment_amount(increment: u64) -> u64 {
            ...
        }
      
  • From 0.33.0, methods without the payable attribute cannot accept coins.

      #[storage(write), payable]
      fn deposit() -> u64 {
          ...
      }
    
      #[payable]
      fn receive() -> u64 {
          ...
      }
    
  • No fallback/receive function

  • Asset/Token work as native assets in Fuel

    • In the sway token contract, you can define how the tokens can be minted or burnt. As it works as a native asset, you cannot limit the token transfer in the token contract.

    • In sway, you can only get the asset balance of a ContractID. You cannot get the asset balance of an Address

  • There are two types of Identity: Address and ContractId

    • In solidity, it's not easy to tell if an account is an EOA or a contract.

    • In Sway, an account is either an Address (EOA) or a ContractId (contract). If you are not sure what type of address you will interact with, you can just use Identity.

        // https://github.com/FuelLabs/sway/blob/master/sway-lib-std/src/identity.sw
        pub enum Identity {
            Address: Address,
            ContractId: ContractId,
        }
      
  • Detecting Reentrancy (stack is transparent)

    • In FuelVm, each tx will be allocated with a fixed-size memory space.
      calls to external contracts are pushed to the memory space as a call frame. they can only modify the state of the call frame they belong to.
      Inside this context, you are aware of everything that happens here (know what call frames are pushed to the memory space before you)

    • By checking if the contract is called in previous call frames, you can know if the contract is reentered or not

    • Reentrancy library

  • There can only be one contract per project.

  • In FuelVM, SafeMath check is enforced at the VM level

    • Safemath checks in Solidity are done at the bytecode level only. Overflow can still happen if you cast a big number into a smaller type.

    • You can also turn off/on the check by using this library.

Library

Similar to libraries in Solidity, you can define some common behaviours such as utils functions, structs and ABI in the library.

Predicate

  • Predicate contains a main function that returns a boolean value.

  • Predicate can not be deployed on-chain. It appears as an address on-chain, which is derived from the hash of its bytecode.

    • It's stateless and independent of on-chain status. But it can access data in the tx.

    • It has no persistent storage (Storage{} cannot be used).

  • Users can send coins to the predicate address.

  • The coins in the predicate address can only be unlocked by making the predicate main function return true.

  • An OTC Swap example

Script

  • Similar to predicates, it cannot be deployed on-chain either.

  • It is state-aware. It can access on-chain status and call other contracts.

  • It has no persistent storage.

    • Storage{} cannot be used.
  • It contains one main() function with no return value.


References


Follow me on twitter for more about smart contract development and security

0
Subscribe to my newsletter

Read articles from zt directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

zt
zt