DecentralChainDecentralChain
  • Technologysubmenu
    Why DecentralChainWhat sets this chain apartHow the chain worksPublic blocks, public validatorsBlockchain featuresWhat is on, what is being voted onFinalityThe rollback bound, and what is unverifiedRIDEContracts that cannot run foreverFor machinesUnsigned transactions and RIDE in processSolana bridgePhantom and Solflare, mainnet onlyNetwork statusHeight, sync and peers, read live
  • Ecosystemsubmenu
    DCC public saleOpens 26 SeptemberDecentralCoinSupply, allocation and tokenomicsDecentral.ExchangeexternalDecentralPropDecentralScansoonCubensis ConnectDecentralAmericasoon
  • Developerssubmenu
    QuickstartRead, compile and composeREST APIEvery endpoint, no key, no accountSDK packages19 on npm, 5 in the workspaceSigningAuthorising without custodyMCP & AgentsThe chain, and the tools we have builtDecentralChain NodeRun a validator, and what LPoS pays
  • Communitysubmenu
    ChannelsTelegram, X and the reposDCC AirdropAllocated, not yet arrangedGovernanceWho can actually decide anythingBrand kitThe mark, and how to use it
  • Documentation
XGitHub
Start buildingarrow
DecentralChainDecentralChain

An open Layer-1 with Leased Proof of Stake.

Native token: DecentralCoin (DCC)

Fixed supply 100,000,000 DCC
Minted at genesis, never inflated

  • X
  • GitHub
  • Telegram

Build

  • Quickstart
  • REST API
  • SDK packages
  • Signing
  • MCP & Agents
  • Documentation

Ecosystem

  • DCC public sale
  • DecentralCoin
  • Decentral.Exchange
  • DecentralProp
  • DecentralSwap
  • Cubensis Connect

Network

  • Blockchain features
  • Finality
  • RIDE
  • Solana bridge
  • Run a node
  • Network status

Project

  • Community
  • DCC Airdrop
  • Governance
  • Brand kit
  • GitHub
mainnetHeight—Node—read from your browser
© 2026 DecentralChainOperated by DecentralExchange · Cédula Jurídica 3-102-956858
Jacó, Garabito, Costa Rica
TermsPrivacySecurityLicensingdecentralchain.io
Documentation/RIDE language

Syntax Basics

RIDE language

  • Syntax Basics
  • Data Types
  • Functions
  • Script Types
  • Structures
  • Iterations with FOLD<N>
  • dApp-to-App Invocation
  • Directives
  • Definitions
  • Expressions
  • Constants
  • Variables
  • Operators
  • Functions
  • Exceptions
  • Comments

Directives

Every Ride script should start with directives for the compiler. The directives define the script format and available functions, structures and variables. Directive format is as follows:

{-# DIRECTIVE_NAME VALUE #-}

Directive List

There are three types of directives, with different possible values.

{-# STDLIB_VERSION 5 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}

{-# STDLIB_VERSION 5 #-} sets the version of the standard library. The latest version currently in production is 5.

{-# CONTENT_TYPE DAPP #-} sets the type of the file you're working on. There are different content types, DAPP and EXPRESSION. The DAPP type allows you to define functions and finish execution with certain actions which result in account balances, asset properties, and entries in the dApp account data storage. The EXPRESSION type should always return a boolean value, since it’s used as a predicate for transaction validation.

{-# SCRIPT_TYPE ACCOUNT #-} sets the entity type we want to add to the script to change its default behavior. Ride scripts can be attached to either an ACCOUNT or ASSET.

Examples

For a dApp script:

{-# STDLIB_VERSION 5 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}

For an account script:

{-# STDLIB_VERSION 5 #-}
{-# CONTENT_TYPE EXPRESSION #-}
{-# SCRIPT_TYPE ACCOUNT #-}

For an asset script:

{-# STDLIB_VERSION 5 #-}
{-# CONTENT_TYPE EXPRESSION #-}
{-# SCRIPT_TYPE ASSET #-}

Not all combinations of directives are correct. The example below will not work, because DAPP content type is allowed only for accounts:

# Wrong example, will not work

{-# STDLIB_VERSION 5 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ASSET #-}

Definitions

A definition is a linking of the name to the value or to the function body.

Examples

Linking the name to the value.

let x = 5 + 5

Linking the name to the function body.

func f(x: Int) = {
 x + 5
}

Expressions

An expression is a combination of one or more constants, variables, operators and function calls.

Expression Result

An expression result is a value, which is obtained by the fold of the syntactic tree of the expression. Ride interprets the expression and calculates its result.

Expression Type

An expression type is a data type of the expression result.

Examples

The expression that consists of a single constant.

7

The expression that consists of a single variable.

7 + x * size("apple")  

The expression that consists of the constant 7, operators + and \*, variable x and the size function call.

7 + x * size("apple")

Constants

A constant is a value that cannot be changed by the program during its execution.

Examples

Below 7 and "apple" are constants.

7 + x + size("apple")

Variables

These are declared and initialized with the let keyword.

let a = "Bob"
let b = 1

In Ride, you can only declare a variable along with a value assignment. The = sign must be followed by an expression. The value of the variable is the expression result. Ride variables are immutable: the value of a variable cannot be changed after it is defined. Ride is strongly typed and the variable's type is inferred from the value. Ride allows you to define variables globally, inside any function, or even inside a variable definition.

func lazyIsGood() = {
 let a = "Bob"
 let b = {
    let x = 1
    "Alice"
   }  
 true
}

Lazy Variables

Let keyword defines a variable with lazy evaluation: the value of a variable is evaluated the first time it is used. Let's see an example:

let a = 42                 # Integer variable definition
let b = "Ride!"  # String variable definition

Ride allows you to define variables globally, inside any function, or even inside a variable definition.

func lazyIsGood() = {
 let c = {
    let d = 1
    true
   }  
 c
}

The function above returns true, but variable d won't be initialized because unused lazy variables are not evaluated. Since a function is a definition and not an expression, you can assign a function value to a variable but not the function itself.

let result = lazyIsGood()  # result is true

Strict Variables

The strict keyword defines a variable with strict (eager) evaluation. Unlike lazy variables defined with let, a strict variable is evaluated immediately when script execution reaches it, that is, before the next expression. Strict variables can only be used inside another definition, for example, inside the body of a function. A strict variable will not be evaluated if it is defined inside another definition that is not used: for example, inside a function that has not been called. Strict variables are suitable for dApp-to-dApp invocation as they ensure executing callable functions and applying their actions in the right order. Let's see an example:

func foo() = {
  ...
  strict balanceBefore = decentralchainBalance(this).regular
  strict z = invoke(dapp2,"bar",args,[AttachedPayment(unit,100000000)])
  strict balanceAfter = decentralchainBalance(this).regular

  if(balanceAfter < balanceBefore) then ... else...
}

In this example, balanceBefore and balanceAfter may differ because payments to dApp2 and actions performed by the bar callable function can affect the balance.

Built-in Variables

The Standard library defines built-in variables that can be used in scripts.

Built-in Variables
#NameDescription
1BuyOrder type.
2\1) CEILING. 2) DOWN. 3) FLOOR. 4) HALFEVEN. 5) HALFUP.Rounding methods used in the math functions fraction, log, pow.
3heightBlockchain height at the script execution time.
4lastBlockInformation about the last block of the blockchain at the script execution time.
5nilVariable that contains an empty list. The variable is used for creating lists. For example, instead of: let a = [5,6].
6\1) NOALG. 2) MD5. 3) SHA1. 4) SHA224. 5) SHA256. 6) SHA384. 7) SHA512. 8) SHA3224. 9) SHA3256. 10) SHA3384. 11) SHA3512.Variables that are passed as the first parameter to the rsaVerify function.
7SellOrder type.
8this\1) For a dApp script or an account script: the Address structure. 2) For an asset script: the asset structure.
9txTransaction or order.
10unitVariable that contains an object of Unit type.

Operators

Arithmetic Operators

Arithmetic Operators
OperatorDescription
\+Addition
\-Subtraction
\*Multiplication
/Division
%Remainder

The / operator uses the FLOOR rounding method.

Comparison Operators

Comparison Operators
OperatorDescription
<Less than
>Greater than
<=Less than or equal
>=Greater than or equal

Equality Operators

Equality Operators
OperatorDescription
==Equality
!=Inequality

Local Definition Operators

Local Definition Operators
OperatorDescription
funcFunction local definition.
letLazy definition of a variable.
strictStrict definition of a variable.

Conditional Operators

Conditional Operators
OperatorDescription
if-then-elseConditional statement.
match-caseSpot a type from union.

List Operators

List Operators
OperatorDescription
++Concatenation.
:+Adding the element to the end of the list.
\:\:Adding the element to the beginning of the list.

See examples of the list article.

Unary Operators

Unary Operators
OperatorDescription
\-Unary minus
!Logical negation

Logical Operators

Logical Operators
OperatorDescription
&&Logical AND
||Logical OR

Match-Case

match-case operator is used to spot a certain type from union or any type . The spotting is required to perform certain operations. Let's review the following example.

match tx {
 case _: TransferTransaction|ExchangeTransaction => t.amount > 100 && sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
 case _ => false
}

In this example, if:

  • The type of transaction is transfer transaction or exchange transaction.
  • Amount field value is greater than 100.

Then it will be sent to the blockchain. If the transaction has a different type and/or amount field value is lesser than 100, then it will be rejected.

Possible Issue

Let's review the following code.

{-# STDLIB_VERSION 2 #-}
{-# CONTENT_TYPE EXPRESSION #-}
{-# SCRIPT_TYPE ACCOUNT #-}

match (tx) {
 case t: TransferTransaction|ExchangeTransaction|MassTransferTransaction|Order => false   # Prohibit any transfer of funds from the account

 case _ => sigVerify(...)
}

In this example we are using version 2 of Ride standard library, STDLIB_VERSION 2, and we want to reject any funds transfer from our account. In order to do this, we are returning false for:

  • TransferTransaction
  • ExchangeTransaction
  • MassTransferTransaction

Transactions of other types (for example transactions that do not transfer funds) are being sent to the blockchain. But Ride is developing rapidly, and new transaction types are emerging. Features of invoke script transaction which is not supported by Ride v2 include attaching payments to transfer tokens to the account of the called dApp. This means that the InvokeScriptTransaction won't be caught by the first case. It will pass to the default branch case _ => and sent to blockchain. As a result, the funds could be transferred from the account instead of the transfers being prohibited like we wanted.

Solution

To prevent the reviewed issue, it is recommended to return false inside of the default case. Then for the entities, not listed in previous branches, sending information to the blockchain will be prohibited. Below is the sample of script which rejects any funds transfer from account, but allows all other transactions existing in Ride v2. Usage of case _ => false rejects any other transactions, not supported by the Ride v2 (i.e. invoke script transaction).

{-# STDLIB_VERSION 2 #-}
{-# CONTENT_TYPE EXPRESSION #-}
{-# SCRIPT_TYPE ACCOUNT #-}
 
match tx {
 case t: TransferTransaction|ExchangeTransaction|MassTransferTransaction|Order => false   # Prohibit any transfer of funds from the account
 case _: Transaction => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) # Allow all other known transaction types as long as the signature is correct
 case _ => false  # Reject all other (new, unknown) entity types, since they are not in the version of the language used at the moment
}

Functions

Functions in Ride can only be used after they are declared.

func greet(name: String) = {
  "Hello, " + name
}

func add(a: Int, b: Int) = {
  func m(a:Int) = a
  m(a) + b
}

The type (Int, String, etc) comes after the argument’s name.

As in many other languages, functions should not be overloaded. It helps to keep the code simple, readable and maintainable.

func calc() = {
  42
}

func do() = { 
  let a = calc()
  true
}

The callable function will not be called either, because variable a is unused.

Unlike most languages, variable shadowing is not allowed. Declaring a variable with a name that is already used in a parent scope will result in a compilation error.

Functions should be defined before they are used. Functions can be invoked in prefix and postfix order:

let list = [1, 2, 3]
let a1 = list.size()
let a2 = size(list)

let b1 = getInteger(this, “key”)
let b2 = this.getInteger(“key”)

In these examples a1 is the same as a2 and b1 is the same as b2.

Learn more about functions.

Exceptions

There is no exception handling in Ride: after an exception has been thrown, the script execution fails. The transaction can be either discarded or saved on the blockchain as failed, see the transaction validation article for details The throw function will terminate script execution immediately, with the provided text. There is no way to catch thrown exceptions.

throw("Here is exception text")

The idea of throw is to stop execution and send useful feedback to the user.

let a = 12
if (a != 100) then
 throw ("a is not 100, actual value is " + a.toString())
 else throw("A is 100")

Comments

To write comments use the pound sign.

let month = 7 # Sets the month

There are no multi-line comments.

NextData Typesarrow

Elsewhere on this site

RIDE on DecentralChainarrowWhat the language guarantees, and why a script is priced before it deploys.SDK packagesarrowThe compiler and the SDKs, published to npm and runnable in a browser.