Skip to main content

How to bridge liquidity to Aurora?

· 2 min read
Slava Karkunov
Slava Karkunov
DevRel

In this article, we will discuss how to bridge liquidity to Aurora in the most convenient way. We will focus on stablecoins, explain why we have four types of these on Aurora, and take a look at how to bridge them in different ways. Note that this whole bridging process also applies to the ERC-20 tokens.

How to get your tokens from Bastion contracts?

· 3 min read
Slava Karkunov
Slava Karkunov
DevRel

Recently, we became aware of this issue and the lack of a way to do it in the Bastion UI, so we decided to create a tutorial for everyone to use independently. Big thanks to the people in the community who helped me create and test this tutorial and provided invaluable insights and feedback!

To formulate the problem more precisely, a user has some cUSDCcUSDTLP tokens and wants to convert these back to stables. The Bastion project's UI doesn't allow this today, so the only way is to call smart contracts directly.

We will go through the next steps:

  • What contracts should we call?
  • What method should we call, and how?
  • How to convert cUSDC and cUSDT into regular stables?

We will use the most convenient way for users to interact with smart contracts—the Explorer. However, devs can always write a script to perform the steps described in this article with Ethers or Web3.js.

Let's go!

Managing Aurora's Validator staking with 'near-cli-rs'

· 5 min read
Slava Karkunov
Slava Karkunov
DevRel

In this article, we will discuss how to manage your staking on the Aurora Validator. To recap quickly, Aurora is an EVM-compatible blockchain running as an L2 on the Near Protocol. In the heart of it is an Aurora Engine smart contract. That is why every transaction on Aurora is relayed to the Near and has the corresponding Near transaction. You can read more about this here. That is why Aurora doesn’t have its own validators – we’re just re-using the Near ones.

Plugins for smart contract devs building on Near

· 5 min read
Moritz Zielke
Moritz Zielke
Research Engineer

Some common functionality is required for many smart contracts. Examples are temporarily pausing certain features, staging and deploying a new version of the contract, and restricting access to contract methods. While such functionality is out of scope for an SDK like near-sdk-rs, ideally it is not implemented anew for every smart contract.

The most obvious benefits of an open-source library are reusability and the value it adds to the ecosystem. The smart contract features mentioned above can be tricky to implement and cumbersome to test. Without a library, developers might gloss over functionality that does not add business value but still is critical for security. As near-plugins is open-source and used by many developers, there are more engineering hours and eyeballs dedicated to it compared to a solution specific to a single smart contract.

Contract Callbacks in XCC

· 5 min read
Michael Birch
Michael Birch
Senior Research Engineer

In previous posts, we have written about the cross-contract calls (XCC) feature on Aurora. These include an overview, an application, and a deep dive into writing tests. In this post, we continue with the XCC technical deep dive by discussing in more detail handling XCC results using callbacks. In particular, we focus on the concrete example of needing to refund tokens to a user in the event of an error. Along the way, this example will reveal a bit of a “gotcha” which developers new to the XCC feature may come across, and we’ll discuss how to overcome it.

Practical ERC20 Burning

· 2 min read
Alexey Lapitsky
Alexey Lapitsky
Head of Engineering

Token burning is the act of permanently removing a certain number of tokens from circulation. This article delves into its intricacies and offers guidance based on my real-world experiences at Aurora

Integration tests for XCC communication

· 8 min read
Olga Kunyavskaya
Olga Kunyavskaya
Bridge Engineer

In this article, we will learn how to write local tests for the Aurora contracts, which use XCC calls to Near ecosystem. I will use a simple example to demonstrate it, step by step, we will write:

  1. A simple counter contract for Near blockchain.
  2. Contract on Aurora, which calls the contract on Near by using the XCC.
  3. One integration test in the sandbox.
  4. Setup the git action for running this test automatically.

The example described in this article: https://github.com/olga24912/AuroraToNearXCCExample

Counter contract on Near

I assume that you have already cloned a git repo locally or just created your own repo, in the case you want to add everything file by file to your project using this article.

We will start with creating a simple Counter contract on Near, which just has two functions: increment – for changing the value, and get_num – to return the current value.

We should have the following directories and files in near folder:

AuroraToNearXCCExample: 
|-- near
| |-- contracts
| | |-- build.sh
| | |-- Cargo.toml
| | |-- src
| | | |-- lib.rs

Let's take a look at each of the files.

lib.rs:

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::{near_bindgen, PanicOnDefault};

#[near_bindgen]
#[derive(PanicOnDefault, BorshDeserialize, BorshSerialize)]
pub struct Counter {
val: u64,
}

#[near_bindgen]
impl Counter {
#[init]
pub fn new() -> Self {
Self{
val: 0
}
}

pub fn get_num(&self) -> u64 {
return self.val;
}

pub fn increment(&mut self, value: u64) {
self.val += value;
}
}

Cargo.toml:

[package]
name = "counter"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
near-sdk = "4.1.1"

For compiling the contract into a WASM file, we will use the script build.sh:

#!/bin/sh
set -e

rustup target add wasm32-unknown-unknown
RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release

To compile the contract run:

./build.sh

The target file: near/contracts/target/wasm32-unknown-unknown/release/counter.wasm

Counter contract on Aurora

We already created a counter contract for Near, and now let's create the counter contract on Aurora, which will have one method incrementXCC inside, which we will call the increment method in the Near Counter contract.

First, create the following folder structure and the Counter.sol file

AuroraToNearXCCExample:
|-- aurora
| |-- contracts
| | |-- src
| | | |-- Counter.sol
|-- near

Counter.sol file:

pragma solidity ^0.8.0;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {AuroraSdk, NEAR, PromiseCreateArgs} from "@auroraisnear/aurora-sdk/aurora-sdk/AuroraSdk.sol";

contract Counter {
using AuroraSdk for NEAR;
using AuroraSdk for PromiseCreateArgs;

uint64 constant COUNTER_NEAR_GAS = 10_000_000_000_000;

NEAR public near;
string counterAccountId;

constructor(address wnearAddress, string memory counterNearAccountId) {
near = AuroraSdk.initNear(IERC20(wnearAddress));
counterAccountId = counterNearAccountId;
}

function incrementXCC() external {
bytes memory args = bytes('{"value": 1}');
PromiseCreateArgs memory callCounter = near.call(
counterAccountId,
"increment",
args,
0,
COUNTER_NEAR_GAS
);
callCounter.transact();
}
}

More information about how the aurora contracts with XCC work can be found here, or in this game example, or in these official docs in aurora-contracts-sdk repo.

Install dependencies for counter contract on Aurora

For deploying the counter contract on Aurora in integration tests, we should install foundry and the dependencies. First, go to aurora folder and install aurora-sdk by running:

yarn init
yarn add @auroraisnear/aurora-sdk

For compiling aurora contracts in the test, we will use foundry. How to install foundry you can read here.

We should create foundry.toml in aurora/contracts folder.

AuroraToNearXCCExample:
|-- aurora
| |-- contracts
| | |-- src
| | |-- foundry.toml
| |-- integration-tests
|-- near

foundry.toml:

[profile.default]
src = 'src'
out = 'out'
libs = ['lib', '../node_modules']
allow_paths = []
solc = "0.8.17"

After that you need to run the next command from aurora/contracts folder:

rm -rf lib/aurora-contracts-sdk
forge install aurora-is-near/aurora-contracts-sdk --no-commit

After command execution in the aurora/contracts directory, the lib folder with aurora-contracts-sdk and all necessary files inside will be created.

Integration test

It is time to create an integration test! Go back to the aurora folder with cd .. and run (or just use already existing folder from repo):

cargo new --lib integration-tests

The integration-tests folder will be created. We should also create the following rust-toolchain file in this folder:

[toolchain]
channel = "1.66.1"

We need this because this channel is used in dependencies, and we should use the same channel to make contracts work properly. For people outside the Rust community, you can think about this as setting the Rust version, more info is here.

We should obtain this folder structure:

AuroraToNearXCCExample:
|-- aurora
| |-- contracts
| |-- integration-tests
| | |-- Cargo.toml
| | |-- src
| | | |-- lib.rs
| | |-- rust-toolchain
|-- near

Edit now lib.rs:

#[cfg(test)]
mod tests {
use aurora_sdk_integration_tests::tokio;

#[tokio::test]
async fn counter_test() {

}
}

and Cargo.toml:

[package]
name = "integration-tests"
version = "0.1.0"
edition = "2021"

[dependencies]
aurora-sdk-integration-tests = { git = "https://github.com/aurora-is-near/aurora-contracts-sdk.git" }
near-sdk = "4.1.1"

The command for running the test should run this succesfully:

cargo test

You should see output like this afterwards:

Compiling integration-tests v0.1.0 (/Users/aurora/Projects/AuroraToNearXCCExample/aurora/integration-tests)
Finished test [unoptimized + debuginfo] target(s) in 2.86s
Running unittests src/lib.rs (target/debug/deps/integration_tests-307b69604bee401f)

running 1 test
test tests::counter_test ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00ss

Deploy Near contract in integration tests

Let's start writing our test with compiling and deploying the Counter contract on Near inside the sandbox. To do this we will: create the sandbox workspace with workspaces::sandbox(), compile near contract by using build.sh script (as we did above in section Create Counter contract on Near), deploy the contract with worker.dev_deploy and call the constructor with near_counter.call("new").

All of that is inside the deploy_near_counter function, which we will use now directly in our counter_test. The full code is below:

#[cfg(test)]
mod tests {
use aurora_sdk_integration_tests::{tokio, workspaces, {utils::process}};
use aurora_sdk_integration_tests::workspaces::Contract;
use std::path::Path;


#[tokio::test]
async fn counter_test() {
let worker = workspaces::sandbox().await.unwrap();
let near_counter = deploy_near_counter(&worker).await;
}

async fn deploy_near_counter(
worker: &workspaces::Worker[workspaces::network::Sandbox](workspaces::network::Sandbox),
) -> Contract {
let contract_path = Path::new("../../near/contracts");
let output = tokio::process::Command::new("bash")
.current_dir(contract_path)
.args(["build.sh"])
.output()
.await
.unwrap();

process::require_success(&output).unwrap();

let artifact_path =
contract_path.join("target/wasm32-unknown-unknown/release/counter.wasm");
let wasm_bytes = tokio::fs::read(artifact_path).await.unwrap();
let near_counter = worker.dev_deploy(&wasm_bytes).await.unwrap();

near_counter.call("new").transact().await.unwrap().into_result().unwrap();

near_counter
}
}

You can run cargo test to check if your code is working at this stage.

Deploy Aurora Engine and wNEAR

Now, let's deploy the Aurora Engine contract itself to the sandbox. Also, we will need to deploy wNEAR in Aurora. It is the ERC-20 on Aurora which corresponds to the Near token on Near. We will use this token later for the payment.

#[cfg(test)]
mod tests {
use aurora_sdk_integration_tests::{tokio, workspaces, {utils::process}, aurora_engine, wnear, workspaces::Contract};
use aurora_sdk_integration_tests::workspaces::Contract;
use std::path::Path;

#[tokio::test]
async fn counter_test() {
let worker = workspaces::sandbox().await.unwrap();
let near_counter = deploy_near_counter(&worker).await;

let engine = aurora_engine::deploy_latest(&worker).await.unwrap();
let wnear = wnear::Wnear::deploy(&worker, &engine).await.unwrap();
}
...
}

Deploy counter contract on Aurora in integration tests

Moving to deploying counter contract to Aurora. We are creating a new user account and function to deploy the counter. This function takes: (1) aurora engine, (2) user account, (3) wNear address on aurora, (4) Counter Account ID on Near.

Let's add new dependencies first:

#[cfg(test)]
mod tests {
use aurora_sdk_integration_tests::{tokio, workspaces, {utils::process}, aurora_engine, wnear, ethabi};
use aurora_sdk_integration_tests::workspaces::Contract;
use std::path::Path;

use aurora_sdk_integration_tests::aurora_engine_types::types::{Address};
use aurora_sdk_integration_tests::aurora_engine::AuroraEngine;
use aurora_sdk_integration_tests::utils::forge;
use aurora_sdk_integration_tests::utils::ethabi::DeployedContract;
...

Now let's define deploy_aurora_counter function and add it to out test:

//....
#[tokio::test]
async fn counter_test() {
//....

let user_account = worker.dev_create_account().await.unwrap();
let aurora_counter = deploy_aurora_counter(&engine, &user_account, wnear.aurora_token.address, &near_counter).await;
}

async fn deploy_aurora_counter(engine: &AuroraEngine,
user_account: &workspaces::Account,
wnear_address: Address,
near_counter: &Contract) -> DeployedContract {
//....
}

To deploy aurora contract we should first compile and deploy aurora_sdk_lib, and corresponding dependencies:

async fn deploy_aurora_counter(engine: &AuroraEngine,
user_account: &workspaces::Account,
wnear_address: Address,
near_counter: &Contract) -> DeployedContract {
let contract_path = "../contracts";

let aurora_sdk_path = Path::new("../contracts/lib/aurora-contracts-sdk/aurora-solidity-sdk");
let codec_lib = forge::deploy_codec_lib(&aurora_sdk_path, engine).await.unwrap();
let utils_lib = forge::deploy_utils_lib(&aurora_sdk_path, engine).await.unwrap();
let aurora_sdk_lib = forge::deploy_aurora_sdk_lib(&aurora_sdk_path, engine, codec_lib, utils_lib).await.unwrap();

//....
}

After that, we can compile and deploy the counter contract itself:

    //....

let constructor = forge::forge_build(
contract_path,
&[format!(
"@auroraisnear/aurora-sdk/aurora-sdk/AuroraSdk.sol:AuroraSdk:0x{}",
aurora_sdk_lib.encode()
)],
&["out", "Counter.sol", "Counter.json"]).await.unwrap();

let deploy_bytes = constructor.create_deploy_bytes_with_args(&[
ethabi::Token::Address(wnear_address.raw()),
ethabi::Token::String(near_counter.id().to_string()),
]);

let address = engine
.deploy_evm_contract_with(user_account, deploy_bytes)
.await
.unwrap();

constructor.deployed_at(address)
}

Mint wNEAR for user

When we use XCC for the first time in our setup, the implicit contract on the Near will be created. You can read more about it here. We also could call this implicit contract as sub-account. The overall scheme could be presented as:

Creation of a sub-account will cost you 2 NEAR tokens. That is why we need to mint 2 wNEAR for our user on Aurora after approving the spending of the wNear by counter contract.

///....
use aurora_sdk_integration_tests::aurora_engine_sdk::types::near_account_to_evm_address;
use aurora_sdk_integration_tests::aurora_engine_types::{U256, types::Wei};

#[tokio::test]
async fn counter_test() {
//....

let user_address = near_account_to_evm_address(user_account.id().as_bytes());
const NEAR_DEPOSIT: u128 = 2 * near_sdk::ONE_NEAR;

engine.mint_wnear(&wnear, user_address, NEAR_DEPOSIT).await.unwrap();

let evm_call_args = wnear
.aurora_token
.create_approve_call_bytes(aurora_counter.address, U256::MAX);

let result = engine
.call_evm_contract_with(
&user_account,
wnear.aurora_token.address,
evm_call_args,
Wei::zero()).await.unwrap();
aurora_engine::unwrap_success(result.status).unwrap();
}

Call incrementXCC method in counter contract on Aurora

In this section, we will write a function that calls the incrementXCC method in the Counter contract on Aurora. incrementXCC method is calling inside the increment method from the Near contract and counter is incremented on Near.

Let's write increment function in our test now, which will call the incrementXCC from the Aurora's contract. We'll provide as input: (1) aurora engine contract deployed in the sandbox, (2) the near account of the user which will sign the transaction, (3) the counter contract deployed on aurora.

Notice that we're going to call the method in the aurora contract, but in this function, the user account ID on Near is provided. We can do this because it is possible to call the aurora's counter contract method by using call method from the Aurora Engine contract. In that case, the near user will sign a transaction, but inside the Aurora Engine, there is an implicit mapping between the near account ID and aurora addresses. And it is precisely how we will communicate with the contract in our test.

Now, let's first encode the arguments for the call method in the AuroraEngine contract on Near and after that – submit a transaction and check its result:

//....
use aurora_sdk_integration_tests::aurora_engine_types::parameters::engine::{CallArgs, FunctionCallArgsV1};

#[tokio::test]
async fn counter_test() {
//....

increment(&engine, &user_account, aurora_counter).await;
}

async fn increment(
engine: &AuroraEngine,
user_account: &workspaces::Account,
aurora_counter: DeployedContract
) {

let contract_args = aurora_counter.create_call_method_bytes_without_args("incrementXCC");

let result = engine
.call_evm_contract_with(
&user_account,
aurora_counter.address,
ContractInput(contract_args),
Wei::zero(),
)
.await
.unwrap();

aurora_engine::unwrap_success(result.status).unwrap();
}

Check counter value on Near

Let’s check that the counter has been incremented at the Counter contract on Near. For that, call the get_num view method at the counter and check that the result equals 1.

#[tokio::test]
async fn counter_test() {
//....

let counter_val: u64 = near_counter.view("get_num").await.unwrap().json().unwrap();
assert_eq!(counter_val, 1);
}

Run final test

Now, when everything is ready, let's go to aurora/integration-tests/ directory and run to check that we have the expected results:

cargo test

Git Action

Now, let's set up the git action so that the test runs automatically every time we push changes. To set it up, we must create .github/workflow/test.yml and Makefile.

AuroraToNearXCCExample:
|-- aurora
|-- near
|-- Makefile
|-- .github/workflow/test.yml

The .github/workflows/test.yml contains the git action description. In our case, we are going to run it on push events. First, we install foundry for compiling our Solidity contracts, second, we checkout the repository with all submodules, and in the end, run the script from Makefile.

name: aurora-to-near-xcc-example test automatically

on: [push]

jobs:
test-counter:
runs-on: ubuntu-latest
name: Test counter
steps:
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Clone the repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Test
run: |
make test-counter

Now, let’s take a closer look at the Makefile . First, we go to the aurora directory and install dependencies, second, we compile near contracts, and in the end, run our integration test.

test-counter:
cd aurora && \\
yarn add @auroraisnear/aurora-sdk && \\
cd ../near/contracts && \\
./build.sh && \\
cd ../../aurora/integration-tests && \\
cargo test --all --jobs 4 -- --test-threads 4

That is it, we have set up the git action! Now, our integration test will run automatically after each push to our GitHub repo.

Conclusion

In this article, we have created a simple contract on Aurora, which calls the function from Near contract. We have learned how it is possible to test such contracts inside the sandbox locally. And in the end, we have set up the git action to make the test run automatically.

I hope this article will make it easier for you to develop contracts on Aurora with XCC to Near.

Happy development! In a case you will have any questions about this article, feel free to contract our DevSupport team on our Discord server.

The example from this article you can find in this repo: https://github.com/olga24912/AuroraToNearXCCExample

Turning Smart Contracts into Indexers

· 5 min read
Michael Birch
Michael Birch
Senior Research Engineer

Recently, Michael Birch gave a talk at a virtual Rust conference about some work we have done here at Aurora to enable our technology. In case you missed it, this blog post is a written version of the talk. That talk was aimed at a more general audience, giving background about Aurora, Near, and blockchain technology in general. However, this post assumes you are already familiar with most of the Aurora/Near/blockchain background (you are here on our website, after all) and instead focuses more on the Rust side of things.

How to get USDC tokens on Aurora testnet

· 4 min read
Olga Kunyavskaya
Olga Kunyavskaya
Bridge Engineer

When you develop a contract, quite often you need ERC-20 tokens for testing. If your contract is rather small and doesn't use cross-contract calls, most likely, you don't need official USDC tokens or any other specific tokens. In that case, the best solution is just to take the standard ERC-20 contract, deploy it, and mint as many test tokens as you wish.

However, sometimes the easier solution for testing can be to get official testing tokens. For example, if your contract is use difficult cross-contract calls and dependencies contracts are already deployed on testnet and support only limited numbers of tokens. When I tested the fast-bridge I use the USDC tokens on testnet. The fast-bridge is dependent on the classical rainbow bridge, which has a lot of components and is already deployed on the testnet. In this case it was much easier to use tokens, which are already supported by the classical rainbow bridge.

In this article, I will explain how to get official native Ethereum ERC-20 tokens on your Aurora testnet account in the example of USDC tokens. This method will work with other popular native Ethereum ERC-20 as well, and it will be clear how to get these tokens also in Goerli Ethereum and in Near testnet.

EVM gas vs. Near gas on Aurora

· 6 min read
Michael Birch
Michael Birch
Senior Research Engineer

A core piece of Aurora’s technology is the Aurora Engine smart contract, which is an Ethereum Virtual Machine (EVM) implementation deployed as a smart contract on Near. Therefore, Aurora sits at the intersection of both EVM and Near runtimes. It naturally draws us to think about comparisons between EVM and Near.

For example, the concept of “gas” exists in both the EVM and Near’s runtime. The reason is because of the famous halting problem, which says we cannot know in advance if an arbitrary computer program will finish in a finite time. In the context of a smart contract platform, this means we must measure (and limit) the computation the contract does at runtime. In both the EVM and Near, “gas” is the unit that is used to measure the computational work done by a smart contract.

Even though EVM gas and Near gas both measure the same thing, they are not identical. One analogy is miles and kilometers; both measure distance, but the numerical value of the same physical distance will be different depending on which unit is used. Computation is a more abstract concept than distance, but this analogy leads us to expect some kind of approximately linear relationship between EVM gas and Near gas, similar to how 1 mile equals 1.61 kilometers.

In this blog post, we explore this question and discuss the implications for developers building on Aurora.

Fast Rainbow Bridge: How it works?

· 8 min read
Olga Kunyavskaya
Olga Kunyavskaya
Bridge Engineer

The classical Rainbow Bridge makes it possible to transfer tokens from the NEAR blockchain (or the Aurora Blockchain) to Ethereum. However, it is important to note that these transactions may have longer processing times, typically ranging from 4 to 8 hours, and the final transaction cost remains unpredictable at the time of initiation. These attributes significantly impact the overall user experience, and in certain scenarios, transaction speed becomes a critical factor.

In this article, we introduce the innovative Fast Rainbow Bridge. This groundbreaking solution enables the transfer of tokens from NEAR to Ethereum with just a few minutes of delay. As an added advantage, this bridge also provides the ability to determine the transfer cost during its initialization stage.

Aurora Cloud: Borealis Business

· 6 min read
Boris Polania
Boris Polania
DevRel

Since its inception, the Aurora Protocol has continued to break boundaries in the blockchain world. Its latest innovation is a service known as Borealis Business, aimed at solving one of the most significant challenges for users of Web3 products – the concept of transaction fees.

Getting started with Aurora

· 9 min read
Olga Kunyavskaya
Olga Kunyavskaya
Bridge Engineer

This article is a practical guide for beginners who want to learn how to work with the Aurora blockchain. It covers various aspects such as the connection of Aurora with Ethereum and Near blockchains, setting up an account on the Aurora's testnet using MetaMask, writing a small smart contract, and interacting with it using the Hardhat. Additionally, it includes writing a simple test and exploring different explorers to view transaction details.

The article assumes no prior knowledge of Ethereum or experience working with it. However, it does expect basic programming skills, familiarity with the command line, and a general understanding of blockchain and smart contracts. All commands provided in the article will be specific to the Linux operating system.

Spinning up your own Aurora node

· 4 min read
Oleksii Krasynskyi
Oleksii Krasynskyi
Head of Infrastructure

At Aurora Labs, we encourage everyone to use mainnet.aurora.dev or testnet.aurora.dev to build and deploy their apps. Those endpoints are scalable and reliable. When registering at https://aurora.plus you can even get a bunch of free transactions (soon through the Aurora Pass wallet). That said, many dapps that are deployed on Aurora rely on running their own JSON-RPC Etherium-compatible server. Here we call this server – a relayer. You've probably already read the details about our new version of it in How the Aurora Relayer 2.0 works?

Aurora Chains: Code Overview

· 8 min read
Slava Karkunov
Slava Karkunov
DevRel

The main goal of this article is to understand the Aurora Chain code.  In a future post, we will discuss how it embellishes the Aurora Engine and how the advantages of an Aurora Chain correspond to different parts of code and Aurora architecture.

Building a game using Near, Aurora and BOS

· 7 min read
Michael Birch
Michael Birch
Senior Research Engineer

In this blog post, we explore building a simple Tic Tac Toe game using the Near ecosystem’s tech stack. This includes using Aurora for a seamless onboarding experience (free transactions), Near for complex smart contract logic, and BOS for the front end. The final result is a free-to-use, fully decentralized application that anyone can pick up and play.

Aurora Chains: Walkthrough

· 5 min read
Slava Karkunov
Slava Karkunov
DevRel

Aurora Chains are dedicated blockchains that go beyond mere Ethereum compatibility through a set of industry-first innovations like:

  • custom token & fee mechanics (e.g., gasless transactions; paying for gas with a custom token; some percentage of any transaction value to be stored in Aurora Chain Treasury, etc.);
  • custom access control (public vs private chain, who can transact, who can deploy contracts? e.g., NFT-based access to the blockchain, private chain can be built by using a private NEAR shard – Calimero);
  • seamless interoperability with Aurora, NEAR, and any other Aurora Chains: you can freely move your assets using Rainbow Bridge, call contracts via cross-contract calls, etc.; This is the main difference between Chains and other solutions (like Avalanche or Cosmos). There is no disjointness in between. You can call any smart contract in any other Chain or Near and interact with it freely.
  • *tremendous transaction throughput – *we can provide you with dozens of millions of transactions daily for your ecosystem.

Every Aurora Chain is based upon the Aurora smart contract. Aurora Chain is just another instance of it that can be configured in way that will work in the best way possible to be aligned with your business model and goals. The Aurora Labs team will gladly help you maintain and support your chain.


If you feel your business could benefit from its own blockchain, please do not hesitate to contact us at hello@auroracloud.dev.

Let's do a walkthrough demo of Aurora Innovation Chain to see how it benefits your users.

Cross-Ecosystem Communication

· 5 min read
Boris Polania
Boris Polania
DevRel

Aurora’s infrastructure is built upon an innovative combination—our Ethereum Virtual Machine (EVM) operates as a smart contract running atop the powerful NEAR protocol. Harnessing NEAR's innate ability for smart contracts to communicate with one another, we seamlessly route EVM-compatible transactions to any smart contract deployed within NEAR. By doing so, developers are granted unparalleled access to the best of both ecosystems - from a rich collection of sound and robust Solidity libraries to the groundbreaking NEAR accounts model and an ever-growing, expansive user base.

How the Aurora Relayer 2.0 works?

· 4 min read
Oleksii Krasynskyi
Oleksii Krasynskyi
Head of Infrastructure

In the blockchain world, relayers are off-chain facilitators of data exchange and transactions between blockchain networks and/or layers. They are used primarily in decentralized finance applications, cross-chain communication, and Layer 2 solutions, like sidechains or state channels. In general, relayers listen for events and transactions from one point and then submit the corresponding data or transactions to another. For that, they can charge fees for their services, incentivizing them to operate and maintain their infrastructure.

Initially developed in-house at NEAR, the Aurora EVM is the official EVM for the NEAR ecosystem. Powered by the SputnikVM, it accomplishes a 1:1 experience with the Ethereum protocol. This compatibility between Aurora and Ethereum is achieved by the **Aurora Relayer, a **JSON-RPC compatible server with Ethereum's Web3 API for the Aurora Engine. It has its own internal database to serve multiple read methods and an indexer that is constantly following the head and indexing blocks, transactions and logs to that internal database

Relayer 2.0

As mentioned above, the Aurora Relayer has two main components. First, an implementation of Ethereum’s JSON-RPC specification—a standard collection of methods that all clients must implement and the canonical interface between users and the Ethereum network—on Aurora’s Ethereum Virtual Machine (EVM), a.k.a. the Aurora Engine. Second, an indexer that continuously reads the NEAR network for blocks and other relevant information relevant to Aurora. 

The Relayer had its first version deployed in October 2021. Developed in Typescript and JavaScript. It has been deprecated and replaced by version 2.0, with a JSON-RPC server written in go-lang and the indexer developed in go-lang and rust.

Relayer 2.0 was motivated by the necessity of migrating from Javascript to a more reliable language like golang that is designed for concurrency and is particularly good at managing multiple connections and resource-intensive tasks, making it very well-suited for the type of high-performance RPC systems required in blockchains. Additionally, it required migrating to a more efficient database system, so it was migrated from PostgreSQL to badger-db an embedded key-value database. As a result, there is now a relayer with faster execution speed,  lower machine resource usage, and lower data latency that is easier to code, debug, optimize, and deploy. Now, let’s have a general overview of some of the internals of the Relayer.

The JSON-RPC

Written in go-lang, it exposes endpoints that implement the methods of Ethereum’s JSON-RPC protocol, commonly known as the Web3 API. This middleware leverages a messaging system that forwards JSON-PRC calls to the NEAR network and vice versa. Its source code is open and available to developers, contributors, and anyone who would like to build, run and experiment with it natively. A list of all the implemented methods and the server's source code can be found in the GitHub repo. Also, there is a standalone version available here.

The Database

Embedded databases are a better choice for applications that don't require complex querying planning, as it provides a lightweight solution with fewer dependencies. They are also well-suited for applications that benefit from local data storage with low latency and need single-process concurrency for concurrent read and write operations without external coordination.

BadgerDB—our database of choice—is an embeddable, persistent, fast key-value (KV) database written in pure Go. It is ideal for JSON-RPC servers as most methods grab data by key while benefitting from better data compression and lower latency. In addition, other teams inside Aurora are also using it, therefore, the required competencies and know-how were already there.

The Indexer

The new embedded indexer continuously reads JSON files generated by the Aurora Refiner that populate a local database. The refiner allows users to download all NEAR Blocks and get all information relevant to Aurora. NEAR Blocks data can be consumed from two different sources: the NEAR data lake— a repository of blocks and events from the NEAR network as JSON files on AWS — and an archival instance, the NEARCore. In general, Aurora Relayer infrastructure implements an indexer of NEAR blocks, an indexer of blocks from tar backups and an indexer of pre-history blocks (height < 34 mln). An open-source repository for the Aurora Refiner can be found here.

And more…

In addition, and due to the nature of Aurora’s relayer infrastructure and its interactions with the NEAR network, it was possible to upgrade our internal infrastructure to use our relayer with additions that allow the implementation–among other things–of complex multi-tenant, rule-based accounting systems that support virtually any possible way to account for transactions, to enforce gas prices, pre- or post-run transactions, etc. So it is possible to have users with prepaid fees, prepaid gas, no gas, and many other configurations for distributing gas and fees between relayers, users, and owners of smart contracts. This means that anyone willing to spin a relayer will have access to more sophisticated economic mechanisms for its users or on behalf of others, thus acting the same way ERC-4337 bundlers do, i.e., as validators who earn incentives for completing transactions. 

The Future of User Experience

By improving efficiency and reliability and by adding innovative functionality into the relayer, Aurora builders and developers can offer faster, more robust applications and significant improvements to the user’s experience where — among other things — per-transaction fees could be eliminated and accounts could be detached from keys. Therefore, the Aurora Relayer stands as a groundbreaking innovation in the world of decentralised blockchain technologies. Furthermore, as we continue to see rapid advancements and increasing adoption, the Aurora Relayer sets the stage for a more interconnected and efficient future with the potential to unlock unprecedented levels of usability, scalability, security, and cost-effectiveness, ultimately contributing to a more accessible landscape for all types of users.

If you are interested in getting to know Aurora Relayers in more depth, in our next post, we will teach you how to modify and launch a stand-alone version of the relayer that can be called by a smart contract that can execute functions without charging gas to its callers, stay tuned!