Using Aurora to deploy an Ethereum smart contract

In this tutorial, we'll walk through the flow for deploying a smart contract to Aurora, and discuss how Ethereum and NEAR can be used to interact with this smart contract.
In this tutorial, we are going to deploy an ERC-721 smart contract to Aurora testnet, and will be reproducing some of the steps used in the Deploying a Contract using Truffle Aurora Tutorial. Parts of this tutorial will be modified to use the Aurora testnet endpoints available via Infura.
Once the smart contract is deployed, we can bridge ETH or NEAR to Aurora, and use that bridged ETH and NEAR to pay for gas costs associated with minting tokens using the ERC-721 contract we have created. This example meant to illustrate how Aurora can be used to cheaply deploy a smart contract. Similar patterns could be used for DeFi applications (if using an ERC-20 token), DAO membership, gaming, and other use cases.
At this time, tokens that are minted on Ethereum can use the Rainbow Bridge to move to Aurora. Tokens minted on NEAR can also be bridged to Aurora using the Rainbow Bridge. At this time, tokens created on Aurora cannot yet be bridged to Ethereum or NEAR, but this is on the roadmap for Aurora.
Tokens minted on Aurora are not able to bridged to Ethereum or NEAR at this time.

Deploy an ERC-721 smart contract to Aurora testnet

This tutorial assumes familiarity and prior usage of the smart contract development suite Truffle. If this is your first use of Truffle, we recommend completing the "Pet Shop" tutorial in the Truffle documentation first before starting on this tutorial.

1. Create a project directory and initialize a Truffle project

In your terminal, create a new folder called aurora-721-example and initialize a truffle project within that directory
mkdir aurora-721-example
cd aurora-721-example
truffle init

2. Download the OpenZeppelin contracts

Within the aurora-721-example directory, download the OpenZeppelin contracts, as the smart contract we will deploy will import some of these contracts.
npm install @openzeppelin/contracts

3. Create an account to sign transactions

In order to sign transactions, we'll need an account to sign with. There are multiple ways to generate a wallet, and if this is your first time doing so, we encourage you to follow Step 3 of the ConsenSys Developer Portal. Alternatively, you can use Truffle Dashboard to connect an existing wallet and sign transactions without needing to put your mnemonic in a .env file.

4. Create the .env file

As we are using a .env file to store our Infura project ID, run following command in your terminal:
npm install --save dotenv
Create a file in the root level of your directory called .env and inside this file enter the following information, providing your Infura API key (without quotations), and, if needed, your mnemonic (with quotations):
NEVER PUSH A .env FILE TO GITHUB OR ANY PUBLIC LOCATION. For best practices on using a .env file and protecting your secrets as it relates to Infura please read How to Use .env to Enhance Basic Security Within Your DApp. General advice on protecting your secrets can found by reading at How to Avoid Uploading Your Private Keys to GitHub

5. Create your smart contract

Navigate to the Contracts folder and create a new contract called ClubToken.sol. Within that file, paste the following code:
SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract ClubToken is ERC721URIStorage {
uint256 private _tokensCount = 0;
address public minter = address(0);
modifier onlyMinter(){
minter == msg.sender,
'Invalid Minter'
constructor() ERC721("ClubToken", "CT") {
minter = msg.sender;
function mint(address to) external onlyMinter {
uint256 tokenId = _tokensCount + 1;
_mint(to, tokenId);
_tokensCount = tokenId;
function burn(uint256 tokenId) external {
_tokensCount -= 1;
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
require(minter == msg.sender || to == minter, 'Invalid Transfer');
safeTransferFrom(from, to, tokenId, "");
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
require(minter == msg.sender || to == minter, 'Invalid Transfer');
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);

6. Create the migrations script

Navigate to the migrations folder and create a file named 2_deploy_contracts.js and paste in the following code:
const ClubToken = artifacts.require("ClubToken.sol");
module.exports = function(deployer) {

7. Configure the Truffle settings

Now navigate to the truffle-config.js file and put the following information at the top of the file, assuming you are using a .env to store your Infura project ID and wallet mnemonic:
const HDWalletProvider = require("@truffle/hdwallet-provider");
Under the networks section of truffle-config.js paste in the following code:
auroratestnet: {
provider: () =>
new HDWalletProvider(
network_id: 0x4e454153, // Aurora testnet ID
gas: 10000000
Save this file. We will now use Truffle to deploy this smart contract to Aurora testnet.

8. Compile and deploy the smart contract to Aurora testnet

In your terminal, run the command:
truffle migrate --network auroratestnet
This will compile and migrate the smart contract to the Aurora testnet, and you will be able to see the deployed code using the testnet version of Aurorascan. We now have deployed a smart contract to Aurora testnet.
Compiling your contracts...
> Compiling ./contracts/ClubToken.sol
> Artifacts written to /Users/Code/aurora-721-example/build/contracts
> Compiled successfully using:
- solc: 0.8.11+commit.d7f03943.Emscripten.clang
Starting migrations...
> Network name: 'auroratestnet'
> Network id: 1313161555
> Block gas limit: 0 (0x0)
Deploying 'ClubToken'
> transaction hash: 0xe999cf28b54d11985f61d33aeb8cd11c269a45bdd28f389ad0ebb83101fddc4e
> Blocks: 11 Seconds: 8
> contract address: 0x12820Dc1283354CbB9f2478b6c044d4260E95e15
> block number: 84998829
> block timestamp: 1647289263
> account: 0xc94C5473073878FAFd500aFfb5495aDb2230Eeea
> balance: 0.001
> gas used: 2685442 (0x28fa02)
> gas price: 0 gwei
> value sent: 0 ETH
> total cost: 0 ETH
> Saving migration to chain.
> Saving artifacts
> Total cost: 0 ETH
> Total deployments: 1
> Final cost: 0 ETH
The Aurora documentation provides sample code to deploy dapps and move tokens between Ethereum and Aurora.