Skip to main content

11 posts tagged with "Tutorials"

Longer posts talking about the subject in detail

View All Tags

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.

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.

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?

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.