Skip to main content

Core concepts

Let's first explore some core concepts of development in Solidity and see how they translate to Rell before we get into practical examples. We will cover these topics which introduce the foundations of blockchain development:

  • Setting up your smart contracts and dapps
  • Declaring state variables and models
  • Interacting with your dapp/smart contract
  • Using internal functions
  • Querying for data

Smart contract and dapp states

We'll start by defining a contract in Solidity, adding a struct and a state variable, and then do the same in Rell.

Solidity:

Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract CompanyManager {
// Define struct for our data
struct Company {
string name;
string full_address;
}

// Declare a state variable holding our companies in an array
Company[] public companies;
}

Rell:

Rell
module;

entity company {
name: text;
address: text;
}

The code looks pretty similar, right? However, in Rell, we don't need to declare any variable for companies. This is because defining an entity in Rell automatically includes it in the state of your dapp upon deployment.

As a Solidity developer, declaring an array and storing data in the contract might seem daunting due to Gas Fees. However, with Rell, this is not an issue. An instance of an entity in Rell is stored on-chain in a relational database without incurring any gas fees. Chromia adopts a unique approach to resource management and fees, allowing developers to lease containers with a fixed amount of resources (vCPU, RAM, storage, and I/O) similar to traditional cloud service providers. This means there are no transaction fees (gas fees) for users, as the costs are covered by leasing these resources, making it possible to design user experiences similar to traditional Web2 applications.

To dig deeper, a table named company will be created in your dapp's state along with the attributes name and address. This is similar to how a database table is created using an ORM with a code-first approach. Read more about entities here.

Interacting with a dapp or smart contract

In Solidity, interaction with a smart contract is done by calling functions marked as public. This serves as the entry point for executing logic within a contract. Let's add an example to our smart contract:

Solidity
function addCompany(string memory _name, string memory _address) public {
Company memory newCompany = Company(_name, _address);
companies.push(newCompany);
}

In Rell, you interact with a dapp using operations, which are similar to public functions in Solidity. Operations are executed by signing and sending a transaction with the operation name and supplied parameters. The Chromia platform then executes the logic in the body of the operation, which can modify the state of your dapp. Here's how you can add a new company to your dapp state in Rell:

Rell
operation create_company(name: text, address: text) {
create company( name, address );
}

Inside the operation, we use the keyword create to add a new entry to the company entity in the dapp state. Conceptually, this is similar to creating a new instance of a Company and pushing it to the array of companies in Solidity. Rell's approach to defining operations allows for straightforward and efficient manipulation of the state without the complexities of managing gas fees, as Chromia does not have gas fees. This makes developing using Chromia both cost-effective and user-friendly. For more information on Rell operations, you can read the full documentation here.

Internal functions

In Solidity, when you want a function that is only accessible from within the smart contract, you use the private keyword. Let's add a simple validation of the company name as a private function:

Solidity
function isValidName(string memory _name) private returns (bool) {
return bytes(_name).length > 0; // Simple check: name is not empty
}

Similarly, in Rell, we can use functions to encapsulate reusable logic, such as validation or data retrieval. Functions in Rell can only be accessed from within your dapp; they can be called from operations, queries, and other functions. If a function is called from an operation, it can also alter the state of your dapp, allowing for well-structured code with reusable logic.

Rell
function is_valid_name(name: text) {
not name.empty();
}

Let's put together what we have so far in our examples for both Solidity and Rell:

Rell
module;

entity company {
name: text;
address: text;
}

operation create_company(name: text, address: text) {
require(is_valid_name(name), "Invalid name");
create company( name, address );
}

function is_valid_name(name: text) {
not name.empty();
}

As you can see, we call the validation function to check that the name is valid in both Solidity and Rell. Both languages use the require function to check the validation result. If the validation fails, an error will be thrown, and the transaction and state changes will be rolled back. For more detailed information about functions, you can read here.

Querying data

In Solidity, retrieving data from a smart contract's state typically involves using public getter functions. Solidity automatically creates getter functions for public state variables, but you can also write custom public functions to return more complex data or computed results. These functions can be marked as viewed if they do not modify the contract's state, ensuring that they do not consume any gas when called externally. Here's an example where we return a company struct by supplying the index of the company:

Soldity
function getCompany(uint _index) public view returns (Company memory) {
return companies[_index]; // Returns the Company struct at the given index
}

In Rell, we use queries to fetch data, similar to Solidity's public view functions. Queries in Rell cannot modify the database state but are used to retrieve data. Combined with Rell's built-in query language, this becomes very powerful.

Rell
query get_company(id: rowid) {
return company @ { .rowid == id };
}

In this example, we use the query language in Rell to fetch the company using row_id as its identifier. This method is efficient and simple, allowing for powerful data retrieval operations. For more detailed information on queries, you can read here.

Summary

This concludes our introduction to transitioning from Solidity to Chromia and Rell. We have covered several basic concepts to get you started. In the next sections, we will showcase various examples illustrating different concepts to help Solidity developers get up and running on Chromia.