diff --git a/content/rsk-devportal/develop/tutorials/ethereum-devs/index.md b/content/rsk-devportal/develop/tutorials/ethereum-devs/index.md index c0edc67a65..0a610bee2a 100644 --- a/content/rsk-devportal/develop/tutorials/ethereum-devs/index.md +++ b/content/rsk-devportal/develop/tutorials/ethereum-devs/index.md @@ -1,442 +1,474 @@ ---- -section_title: For Ethereum developers -menu_order: 300 -menu_title: Port Ethereum dApps -layout: rsk -title: Port Ethereum dApps -tags: tutorial, rsk, ethereum dapps, ethereum, solidity -description: "How to port an Ethereum dApp to RSK, using Truffle framework connected to RSK testnet" -render_features: "custom-terminals" ---- - - - -Smart contracts for RSK are written using Solidity (a Javascript like programming language) and are fully compatible with Ethereum Smart Contracts, so you can migrate your existing Ethereum Smart Contract to RSK without changing the smart contract. - -### Translations - -#### Portuguese - Português - -Este artigo está disponível em Português: [Migrando dApps do Ethereum para RSK](https://rsk.solange.dev/#/pt/port-ethereum-dapps/readme "Migrando dApps do Ethereum para RSK"). - -E também fizemos um [webinar](/webinars/202007-006/ "Migrando dApps do Ethereum para RSK") sobre o assunto, veja o [vídeo](https://youtu.be/-7Oi9_BDr5k) - -### Solidity - -New to Solidity? You can learn more using the [Solidity docs](https://solidity.readthedocs.io/). - -## Requirements - -* Code editor -* Node.js and NPM (Node Package Manager) -* Truffle Framework - -### Code editor - -You can edit Solidity using any text editor but it is a good idea to use more advanced tools, the following is a list of some of them: - -- [Visual Studio Code - VS Code](https://code.visualstudio.com/) -- [Atom](https://atom.io/) -- [Sublime Text](https://www.sublimetext.com/) - -### Node.js and NPM - -Another dependency is NPM, which comes bundled with Node.js. If you need it, go to [Node.js](https://nodejs.org/en/) install. - -Note that NPM is usually installed together with Node.js, so after installing Node.js, there's no need to install it separately. - -If you want to have more than one version installed, -the most fuss-free way to install and manage multiple versions of `node` on your computer is via [nvm](https://github.com/nvm-sh/nvm). - -### Truffle Framework - -Truffle is an open source framework that facilitates the testing and development of smart contracts. It allows you to connect to a local RSK node and call the compiler, run unit tests, and publish your smart contracts easily. Check out [this tutorial](https://github.com/rsksmart/truffle-integration) which demonstrates the usage of Truffle and Ganache with a local RSK node. - -In this tutorial, we will use Truffle for compiling and publishing our smart contracts. - -Enter the following command in the terminal to install truffle on your local machine: - -```shell -npm install -g truffle -``` - -## Step 1 : Import Existing Code - -First, you need to create a project. - -### Initialize an empty Truffle project - -Create a new folder and a Truffle project using the commands below: - -```shell -mkdir rsk-truffle-example -cd rsk-truffle-example -truffle init -``` - -The init command will create 3 folders and a configuration file for this project. The solidity files are in the contracts folder. - -### Install HD wallet provider - -To connect to the RSK network, we are going to use a provider that allows us to connect to any network by unlocking an account locally. We are going to use `@truffle/hdwallet-provider`. -This can be used to sign transactions for addresses derived from a 12 or 24 word mnemonic. - -> You need to have Node >= 7.6 installed. - -In the terminal, inside the project folder, install the HD wallet provider with this command: - -```shell -npm install -E @truffle/hdwallet-provider@1.0.34 -``` - -This `truffle package` comes with many dependencies, and can take a long time to complete. -A successful installation message is shown if everything works fine. - -### Copy Ethereum Contract Code - -In this tutorial, we are going to use the token contract code from [Consensys/Token] (https://github.com/ConsenSys/Tokens) as the example. - -In the `contracts` folder, create two files named `EIP20.sol` and `EIP20Interface.sol`. - -#### EIP20Interface.sol - -``` -pragma solidity ^0.4.21; - -contract EIP20Interface { - /* This is a slight change to the ERC20 base standard. - function totalSupply() constant returns (uint256 supply); - is replaced with: - uint256 public totalSupply; - This automatically creates a getter function for the totalSupply. - This is moved to the base contract since public getter functions are not - currently recognised as an implementation of the matching abstract - function by the compiler. - */ - /// total amount of tokens - uint256 public totalSupply; - - /// @param _owner The address from which the balance will be retrieved - /// @return The balance - function balanceOf(address _owner) public view returns (uint256 balance); - - /// @notice send `_value` token to `_to` from `msg.sender` - /// @param _to The address of the recipient - /// @param _value The amount of token to be transferred - /// @return Whether the transfer was successful or not - function transfer(address _to, uint256 _value) public returns (bool success); - - /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` - /// @param _from The address of the sender - /// @param _to The address of the recipient - /// @param _value The amount of token to be transferred - /// @return Whether the transfer was successful or not - function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); - - /// @notice `msg.sender` approves `_spender` to spend `_value` tokens - /// @param _spender The address of the account able to transfer the tokens - /// @param _value The amount of tokens to be approved for transfer - /// @return Whether the approval was successful or not - function approve(address _spender, uint256 _value) public returns (bool success); - - /// @param _owner The address of the account owning tokens - /// @param _spender The address of the account able to transfer the tokens - /// @return Amount of remaining tokens allowed to spent - function allowance(address _owner, address _spender) public view returns (uint256 remaining); - - // solhint-disable-next-line no-simple-event-func-name - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); -} -``` - -#### EIP20.sol - -``` -pragma solidity ^0.4.21; - -import "./EIP20Interface.sol"; - -contract EIP20 is EIP20Interface { - - uint256 constant private MAX_UINT256 = 2**256 - 1; - mapping (address => uint256) public balances; - mapping (address => mapping (address => uint256)) public allowed; - /* - NOTE: - The following variables are OPTIONAL vanities. One does not have to include them. - They allow one to customise the token contract & in no way influences the core functionality. - Some wallets/interfaces might not even bother to look at this information. - */ - string public name; //fancy name: eg Simon Bucks - uint8 public decimals; //How many decimals to show. - string public symbol; //An identifier: eg SBX - - function EIP20( - uint256 _initialAmount, - string _tokenName, - uint8 _decimalUnits, - string _tokenSymbol - ) public { - balances[msg.sender] = _initialAmount; // Give the creator all initial tokens - totalSupply = _initialAmount; // Update total supply - name = _tokenName; // Set the name for display purposes - decimals = _decimalUnits; // Amount of decimals for display purposes - symbol = _tokenSymbol; // Set the symbol for display purposes - emit Transfer(msg.sender, msg.sender, 0); - emit Approval(msg.sender, msg.sender, 0); - } - - function transfer(address _to, uint256 _value) public returns (bool success) { - require(balances[msg.sender] >= _value); - balances[msg.sender] -= _value; - balances[_to] += _value; - emit Transfer(msg.sender, _to, _value); //solhint-disable-line indent, no-unused-vars - return true; - } - - function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { - uint256 allowance = allowed[_from][msg.sender]; - require(balances[_from] >= _value && allowance >= _value); - balances[_to] += _value; - balances[_from] -= _value; - if (allowance < MAX_UINT256) { - allowed[_from][msg.sender] -= _value; - } - emit Transfer(_from, _to, _value); //solhint-disable-line indent, no-unused-vars - return true; - } - - function balanceOf(address _owner) public view returns (uint256 balance) { - return balances[_owner]; - } - - function approve(address _spender, uint256 _value) public returns (bool success) { - allowed[msg.sender][_spender] = _value; - emit Approval(msg.sender, _spender, _value); //solhint-disable-line indent, no-unused-vars - return true; - } - - function allowance(address _owner, address _spender) public view returns (uint256 remaining) { - return allowed[_owner][_spender]; - } -} -``` - -We also need to create a migration script in the migrations folder: -`migrations/2_deploy_tokens.js` - -``` -const EIP20 = artifacts.require('./EIP20.sol'); - -module.exports = (deployer) => { - deployer.deploy(EIP20, 10000, 'Simon Bucks', 1, 'SBX'); -}; -``` - -## Step 2 : Deploy Solidity Code as RSK Smart Contract - -We are going to deploy the example smart contract on to the RSK Testnet. - -### Testnet and Faucet - -First, we need to obtain an account on RSK Testnet and get some tRBTC from the Testnet faucet. - -**Create new Account with MetaMask** - -1. Open MetaMask Chrome extension -1. In the network options, choose `custom RPC` -1. Enter RSK Testnet as the Network Name -1. Enter https://public-node.testnet.rsk.co as the RPC URL -1. Enter RBTC as SymbolPut and Save -1. Copy the account address - -Configure MetaMask for RSK Testnet - -**Get tRBTC** - -Visit the [faucet](https://faucet.rootstock.io/) to gain some tRBTC to use in the Testnet. - -Enter the account address from MetaMask and wait for several seconds for MetaMask to refresh the new balance. - - - -### Testnet Explorer - -You will be able to check the Testnet's transactions and blocks in real time at -[explorer.testnet.rsk.co](https://explorer.testnet.rsk.co/) - -### Get the current gas price of testnet - -Get the current gas price of the testnet network, and save to `.gas-price-testnet.json`. - -In your project folder, run this cURL command: - -```shell -curl https://public-node.testnet.rsk.co/ -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}' > .gas-price-testnet.json -``` - -You should receive a response similar to the following in the file: - -```json -{"jsonrpc":"2.0","id":1,"result":"0x3938700"} -``` - -The result value is presented in hexadecimal. - -### Truffle Configuration - -Edit the `truffle-config.js` to be same as the code below. The `truffle-config.js` file directs Truffle to connect to the public Testnet node. - -```javascript -var HDWalletProvider = require('@truffle/hdwallet-provider') - -var mnemonic = 'thing tuition ranch ... YOUR MNEMONIC' -var publicTestnetNode = 'https://public-node.testnet.rsk.co/' - -const fs = require('fs'); -const gasPriceTestnetRaw = fs.readFileSync(".gas-price-testnet.json").toString().trim(); -const gasPriceTestnet = parseInt(JSON.parse(gasPriceTestnetRaw).result, 16); -if (typeof gasPriceTestnet !== 'number' || isNaN(gasPriceTestnet)) { - throw new Error('unable to retrieve network gas price from .gas-price-testnet.json'); -} -console.log("Gas price Testnet: " + gasPriceTestnet); - -module.exports = { - networks: { - rskTestnet: { - provider: () => new HDWalletProvider(mnemonic, publicTestnetNode), - network_id: 31, - gasPrice: Math.floor(gasPriceTestnet * 1.1), - networkCheckTimeout: 1e9 - } - }, - compilers : { - solc: { - version: "0.4.24", - evmVersion: "byzantium" - } - } -} -``` - -### Truffle Console connected to RSK network - -Truffle has its own console to run commands, and can be connected on any network previously configured in `truffle-config.js` file. To connect Truffle console to a network, you need to specify the network. - -In the terminal, inside the `rsk-truffle-example` folder, run this command to connect to RSK testnet: - -```shell -truffle console --network rskTestnet -``` - -It may take a while to establish the connection. -This will open a new console, with this prompt: - -```windows-command-prompt -truffle(rskTestnet)> -``` - -### Compile and Deploy - -Enter the following commands in the Truffle console to compile and deploy the contracts. - -```shell -compile -migrate -``` - -## Step 3 : Execute the Smart Contract - -Once the deployment is successful. We can call smart contract methods directly in the truffle console. - -**Check Account Balance** - -Enter the following command into the truffle console. - -```javascript -EIP20.deployed().then((instance=>instance.balanceOf("0x7073F4af7bcBDd63aCC8Cb1D62877d3c7a96Ef52"))) -``` - -EIP20 is the name of our contract. This command will print out the balance of account address `0x7073F4af7bcBDd63aCC8Cb1D62877d3c7a96Ef52` as a big number. To see it as an integer, change the command to - -```javascript -EIP20.deployed().then((instance=>instance.balanceOf("0x7073F4af7bcBDd63aCC8Cb1D62877d3c7a96Ef52").then(b=>b.toNumber()))) -``` - -The balance is 0. - -**Transfer Token Directly Between Two Accounts** - -Now use the following command to transfer 1 token from the minter's account to the previous account - -```shell -EIP20.deployed().then((instance=>instance.transfer("0x7073F4af7bcBDd63aCC8Cb1D62877d3c7a96Ef52", 1))) -``` - -After its successful execution, check account `0x7073F4af7bcBDd63aCC8Cb1D62877d3c7a96Ef52` again to see the change in balance. - -```javascript -EIP20.deployed().then((instance=>instance.balanceOf("0x7073F4af7bcBDd63aCC8Cb1D62877d3c7a96Ef52").then(b=>b.toNumber()))) -``` - -## Step 4 : Deploy to Mainnet - -Deploying Smart Contracts to RSK Mainnet can follow the same steps as the Testnet. - -#### Mainnet Node - -The [public node](/rsk/public-nodes) of RSK Main Net is https://public-node.rsk.co - -#### Gasprice in Mainnet - -Get the current gas price of the mainnet network, and save to `.gas-price-mainnet.json`. - -In your project folder, run this cURL command: - -```shell -curl https://public-node.rsk.co/ -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}' > .gas-price-mainnet.json -``` - -#### Update truffle-config - -In the `truffle-config.js` file, add the following code after the testnet part: - -```javascript -var publicMainnetNode = 'https://public-node.rsk.co/' - -const gasPriceMainnetRaw = fs.readFileSync(".gas-price-mainnet.json").toString().trim(); -const gasPriceMainnet = parseInt(JSON.parse(gasPriceMainnetRaw).result, 16); -if (typeof gasPriceMainnet !== 'number' || isNaN(gasPriceMainnet)) { - throw new Error('unable to retrieve network gas price from .gas-price-mainnet.json'); -} -console.log("Gas price Mainnet: " + gasPriceMainnet); -``` - -Also include this configuration at `network` section: - -```javascript - rskMainnet: { - provider: () => new HDWalletProvider(mnemonic, publicMainnetNode), - network_id: 30, - gasPrice: Math.floor(gasPriceMainnet * 1.01), - networkCheckTimeout: 1e9 - }, -``` - -#### Mainnet Explorer - -You will be able to check the Mainnet's transactions and blocks in real time on -[explorer.rsk.co/](https://explorer.rsk.co/) - -#### Get RBTC through Powpeg - -To deploy onto Mainnet, we need to get some [RBTC](/rsk/rbtc/). - -- You can check the [Powpeg](/rsk/architecture/powpeg/) mechanism between BTC and RBTC. -- Or you can buy in these [exchanges](/rsk/rbtc/#exchanges) +--- +section_title: For Ethereum developers +menu_order: 300 +menu_title: Port Ethereum dApps +layout: rsk +title: Port Ethereum dApps +tags: tutorial, rsk, ethereum dapps, ethereum, solidity +description: "How to port an Ethereum dApp to RSK, using Hardhat framework connected to RSK testnet" +render_features: "custom-terminals" +--- + + + +Smart contracts for RSK are written using Solidity, a programming language similar to JavaScript, and are fully compatible with Ethereum Smart Contracts. This means you can migrate your existing Ethereum Smart Contracts to RSK without modifying the smart contract code. To develop and test your smart contracts on RSK, you can use Hardhat, a development environment that facilitates building, testing, and deploying smart contracts. Hardhat is designed to offer a flexible and powerful framework with advanced features such as console.log debugging, customizable build pipelines, and native TypeScript support. + +### Solidity + +New to Solidity? You can learn more using the [Solidity docs](https://solidity.readthedocs.io/). + +## Requirements + +* Code editor +* Node.js and NPM (Node Package Manager) +* Hardhat development environment + +### Code editor + +You can edit Solidity using any text editor but it is a good idea to use more advanced tools, the following is a list of some of them: + +- [Visual Studio Code - VS Code](https://code.visualstudio.com/) +- [Atom](https://atom.io/) +- [Sublime Text](https://www.sublimetext.com/) + +### Node.js and NPM + +Another dependency is NPM, which comes bundled with Node.js. If you need it, go to [Node.js](https://nodejs.org/en/) install. + +Note that NPM is usually installed together with Node.js, so after installing Node.js, there's no need to install it separately. + +If you want to have more than one version installed, the most fuss-free way to install and manage multiple versions of `node` on your computer is via [nvm](https://github.com/nvm-sh/nvm). + +### Hardhat Framework + +Hardhat is an advanced development environment for Ethereum, designed to help developers manage and automate the task of compiling, deploying, and testing smart contracts. It supports connecting to local and remote networks, making it easy to work with networks like RSK. For more information visit Hardhat's extensive [documentation](https://hardhat.org/docs). + +In this tutorial, we'll utilize Hardhat for compiling, testing, and deploying our smart contracts. + +## Step 1 : Import Existing Code + +First, you need to create a project. + +### Initialize an Empty Hardhat Project + +Create a new folder for your project and initialize it as a Hardhat project with the following commands: + +```shell +mkdir rsk-hardhat-example +cd rsk-hardhat-example +npm init -y +npm install --save-dev hardhat +npx hardhat +``` + +When you run `npx hardhat`, select "Create an empty hardhat.config.js" by following the prompts. This command sets up an empty Hardhat project. + +### Copy Ethereum Contract Code + +In this tutorial, we are going to use the token contract code from [Consensys/Token] (https://github.com/ConsenSys/Tokens) as the example. + +To create a `contracts` folder for your project, execute the following command in your terminal: + +```shell +mkdir contracts +``` + +Create two files named `EIP20.sol` and `EIP20Interface.sol`. + +#### EIP20Interface.sol + +``` +pragma solidity ^0.4.21; + +contract EIP20Interface { + /* This is a slight change to the ERC20 base standard. + function totalSupply() constant returns (uint256 supply); + is replaced with: + uint256 public totalSupply; + This automatically creates a getter function for the totalSupply. + This is moved to the base contract since public getter functions are not + currently recognised as an implementation of the matching abstract + function by the compiler. + */ + /// total amount of tokens + uint256 public totalSupply; + + /// @param _owner The address from which the balance will be retrieved + /// @return The balance + function balanceOf(address _owner) public view returns (uint256 balance); + + /// @notice send `_value` token to `_to` from `msg.sender` + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + /// @return Whether the transfer was successful or not + function transfer(address _to, uint256 _value) public returns (bool success); + + /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` + /// @param _from The address of the sender + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + /// @return Whether the transfer was successful or not + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); + + /// @notice `msg.sender` approves `_spender` to spend `_value` tokens + /// @param _spender The address of the account able to transfer the tokens + /// @param _value The amount of tokens to be approved for transfer + /// @return Whether the approval was successful or not + function approve(address _spender, uint256 _value) public returns (bool success); + + /// @param _owner The address of the account owning tokens + /// @param _spender The address of the account able to transfer the tokens + /// @return Amount of remaining tokens allowed to spent + function allowance(address _owner, address _spender) public view returns (uint256 remaining); + + // solhint-disable-next-line no-simple-event-func-name + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _owner, address indexed _spender, uint256 _value); +} +``` + +#### EIP20.sol + +``` +pragma solidity ^0.4.21; + +import "./EIP20Interface.sol"; + +contract EIP20 is EIP20Interface { + + uint256 constant private MAX_UINT256 = 2**256 - 1; + mapping (address => uint256) public balances; + mapping (address => mapping (address => uint256)) public allowed; + /* + NOTE: + The following variables are OPTIONAL vanities. One does not have to include them. + They allow one to customise the token contract & in no way influences the core functionality. + Some wallets/interfaces might not even bother to look at this information. + */ + string public name; //fancy name: eg Simon Bucks + uint8 public decimals; //How many decimals to show. + string public symbol; //An identifier: eg SBX + + function EIP20( + uint256 _initialAmount, + string _tokenName, + uint8 _decimalUnits, + string _tokenSymbol + ) public { + balances[msg.sender] = _initialAmount; // Give the creator all initial tokens + totalSupply = _initialAmount; // Update total supply + name = _tokenName; // Set the name for display purposes + decimals = _decimalUnits; // Amount of decimals for display purposes + symbol = _tokenSymbol; // Set the symbol for display purposes + emit Transfer(msg.sender, msg.sender, 0); + emit Approval(msg.sender, msg.sender, 0); + } + + function transfer(address _to, uint256 _value) public returns (bool success) { + require(balances[msg.sender] >= _value); + balances[msg.sender] -= _value; + balances[_to] += _value; + emit Transfer(msg.sender, _to, _value); //solhint-disable-line indent, no-unused-vars + return true; + } + + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { + uint256 allowance = allowed[_from][msg.sender]; + require(balances[_from] >= _value && allowance >= _value); + balances[_to] += _value; + balances[_from] -= _value; + if (allowance < MAX_UINT256) { + allowed[_from][msg.sender] -= _value; + } + emit Transfer(_from, _to, _value); //solhint-disable-line indent, no-unused-vars + return true; + } + + function balanceOf(address _owner) public view returns (uint256 balance) { + return balances[_owner]; + } + + function approve(address _spender, uint256 _value) public returns (bool success) { + allowed[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); //solhint-disable-line indent, no-unused-vars + return true; + } + + function allowance(address _owner, address _spender) public view returns (uint256 remaining) { + return allowed[_owner][_spender]; + } +} +``` + +## Step 2 : Deploy Solidity Code as RSK Smart Contract + +We are going to deploy the example smart contract on to the RSK Testnet. + +### Setting Up a New Account with MetaMask + +To begin interacting with the network, it's essential to establish an account on the Metamask wallet. Please confirm that the Metamask extension is correctly installed in your browser. Additionally, it's crucial to adopt secure practices for managing your mnemonic phrase. A widely recommended strategy involves utilizing a `.env` file alongside the dotenv package for enhanced security. If you opt for this method, commence by integrating dotenv into your project with the following command: + +```shell +npm install --save-dev dotenv +``` + +After installation, generate a `.env` file at your project's root. This file is critical for safeguarding your mnemonic and must be excluded from version control by listing it in your `.gitignore`. Populate the `.env` file with your mnemonic as shown below: + +``` +MNEMONIC=your_mnemonic_here +``` + +This setup ensures your account's mnemonic is securely stored and managed, paving the way for a seamless interaction with the network through Metamask. + +### Testnet and Faucet + +First, we need to obtain an account on RSK Testnet and get some tRBTC from the Testnet faucet. + +1. Open MetaMask Chrome extension +2. In the network options, choose `custom RPC` +3. Enter RSK Testnet as the Network Name +4. Enter https://public-node.testnet.rsk.co as the RPC URL +5. Enter RBTC as SymbolPut and Save +6. Copy the account address + +Configure MetaMask for RSK Testnet + +**Get tRBTC** + +Visit the [faucet](https://faucet.rootstock.io/) to gain some tRBTC to use in the Testnet. + +Enter the account address from MetaMask and wait for several seconds for MetaMask to refresh the new balance. + + + +### Testnet Explorer + +You will be able to check the Testnet's transactions and blocks in real time at [explorer.testnet.rsk.co](https://explorer.testnet.rsk.co/) + +### Fetch the Current Gas Price of Testnet + +First, obtain the current gas price from the RSK Testnet network by running the following command in your project's root directory: + +```shell +curl https://public-node.testnet.rsk.co/ -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}' > .gas-price-testnet.json +``` + +### Update Hardhat Configuration + +We will incorporate the `hardhat-toolbox` extension, strategically crafted to significantly boost the efficiency and streamline the processes involved in blockchain development workflows. + +```shell +npm i @nomicfoundation/hardhat-toolbox +``` + +Next, you'll adjust your Hardhat setup to dynamically use the fetched gas price for transactions and configure the connection to the RSK testnet. Modify hardhat.config.js to include the RSK testnet configuration and to automatically use the fetched gas price: + +```javascript +require("@nomicfoundation/hardhat-toolbox"); +require('dotenv').config(); +const { MNEMONIC } = process.env; +const fs = require('fs'); + +// Load the gas price from the previously saved file +const gasPriceTestnetRaw = fs.readFileSync(".gas-price-testnet.json").toString().trim(); +const gasPriceTestnet = parseInt(JSON.parse(gasPriceTestnetRaw).result, 16); +if (typeof gasPriceTestnet !== 'number' || isNaN(gasPriceTestnet)) { + throw new Error('Unable to retrieve network gas price from .gas-price-testnet.json'); +} +console.log("Gas price Testnet: " + gasPriceTestnet); + +module.exports = { + solidity: "0.4.21", + networks: { + rskTestnet: { + url: "https://public-node.testnet.rsk.co/", + accounts: { mnemonic: MNEMONIC }, + gasPrice: Math.floor(gasPriceTestnet * 1.1), // Adjusts the gas price + chainId: 31 + } + }, +}; +``` + +### Compile and Deploy Contracts + +With Hardhat, you can compile and deploy your smart contracts using simple commands. + +#### Compile Contracts + +To compile your smart contracts, run: + +```shell +npx hardhat compile +``` + +This will process all contracts within your `contracts` directory. + +#### Deploy Contracts + +Create a `scripts` folder at the root of your Hardhat project: + +```shell +mkdir scripts +``` + +Inside the `scripts` folder, create a new file named `deploy.js` (or any other name you prefer). This script will manage the deployment of your contracts. + +Open `deploy.js` and add the following deployment script. Adjust parameters like initial token amount, name, decimals, and symbol as needed for the EIP20 contract. + +```javascript +// scripts/deploy.js +async function main() { + const [deployer] = await ethers.getSigners(); + console.log("Deploying contracts with the account:", deployer.address); + // Deploy EIP20 + const EIP20 = await ethers.getContractFactory("EIP20"); + const eip20 = await EIP20.deploy( + 10000, // Initial supply + "Token Name", // Token name + 18, // Decimals + "TOKEN" // Symbol + ); + await eip20.waitForDeployment(); + console.log("EIP20 deployed to:", await eip20.getAddress()); +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); +``` + +Finally, run your deployment script: + +```shell +npx hardhat run scripts/deploy.js --network rskTestnet +``` + +This utilizes the network configuration specified in `hardhat.config.js` to deploy your contracts to the RSK Testnet. + +#### Interact with Your Contracts + +Hardhat provides a console for interacting with deployed contracts and the blockchain. To open the Hardhat console connected to the RSK Testnet, use: + +```shell +npx hardhat console --network rskTestnet +``` +Inside the console, you can run scripts, interact with contracts, or query the blockchain directly. + +## Step 3 : Execute the Smart Contract + +After your contract has been successfully deployed, you can interact with it directly using Hardhat's console or scripting capabilities. Here's how to perform the specified operations: + +**Check Account Balance** + +First, enter the Hardhat console connected to your desired network: + +```shell +npx hardhat console --network rskTestnet +``` + +Once inside the console, you can use the following commands to interact with your deployed EIP20 contract. Assume you've deployed your contract and know its address. You'd interact with it as follows (note that you need to replace `contractAddress` with your contract's actual deployed address): + +```javascript +contract = await ethers.getContractAt("EIP20", "contractAddress") // Replace with contract address +balance = await contract.balanceOf("deployerAddress") // Replace with deployer address +console.log(balance.toString()) +``` + +**Transfer Tokens Directly Between Two Accounts** + +To transfer tokens, you would typically need to ensure the account performing the transfer has enough tokens and is properly authorized (e.g., it's the account that deployed the contract or has been given approval to transfer tokens). Here's how you can initiate a transfer: + +```javascript +const tx = await contract.transfer("0x7073F4af7bcBDd63aCC8Cb1D62877d3c7a96Ef52", 1) +await tx.wait() +``` + +This sends 1 token from the signer's account (default account in Hardhat's ethers plugin) to the specified account. Ensure you're connected to the correct network and using the right account that owns the tokens. + +**Check the Account Balance Again** + +After the transfer, to check the balance of the account again: + +```javascript +const newBalance = await contract.balanceOf("0x7073F4af7bcBDd63aCC8Cb1D62877d3c7a96Ef52") +console.log(newBalance.toNumber()) +``` + +## Step 4 : Deploy to Mainnet + +Deploying Smart Contracts to RSK Mainnet can follow the same steps as the Testnet. + +#### Mainnet Node + +The [public node](/rsk/public-nodes) of RSK Main Net is https://public-node.rsk.co + +#### Gas Price on Mainnet + +To ensure your transactions are processed, obtain the current gas price on the RSK Mainnet and save it locally: + +```shell +curl https://public-node.rsk.co/ -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}' > .gas-price-mainnet.json +``` + +#### Update Hardhat Configuration + +In your Hardhat project, update the `hardhat.config.js` file to include the RSK Mainnet configuration and adjust the script for fetching the mainnet gas price similar to how you did for Testnet. + +```javascript +require("@nomicfoundation/hardhat-toolbox"); +require('dotenv').config(); +const { MNEMONIC } = process.env; +const fs = require('fs'); + +// Load the gas price from the previously saved file +const gasPriceMainnetRaw = fs.readFileSync(".gas-price-mainnet.json").toString().trim(); +const gasPriceMainnet = parseInt(JSON.parse(gasPriceMainnetRaw).result, 16); +if (typeof gasPriceMainnet !== 'number' || isNaN(gasPriceMainnet)) { + throw new Error('Unable to retrieve network gas price from .gas-price-mainnet.json'); +} +console.log("Gas price Mainnet: " + gasPriceMainnet); +const gasPriceTestnetRaw = fs.readFileSync(".gas-price-testnet.json").toString().trim(); +const gasPriceTestnet = parseInt(JSON.parse(gasPriceTestnetRaw).result, 16); +if (typeof gasPriceTestnet !== 'number' || isNaN(gasPriceTestnet)) { + throw new Error('Unable to retrieve network gas price from .gas-price-testnet.json'); +} +console.log("Gas price Testnet: " + gasPriceTestnet); + +module.exports = { + solidity: "0.4.21", + networks: { + rskMainnet: { + url: "https://public-node.rsk.co", + accounts: { mnemonic: MNEMONIC }, + chainId: 30, + gasPrice: Math.floor(gasPriceMainnet * 1.1), // Adjusts the gas price + }, + rskTestnet: { + url: "https://public-node.testnet.rsk.co/", + accounts: { mnemonic: MNEMONIC }, + gasPrice: Math.floor(gasPriceTestnet * 1.1), // Adjusts the gas price + chainId: 31 + } + }, +}; +``` + +#### Mainnet Explorer + +After deploying your contracts to the Mainnet, you can monitor transactions and block confirmations in real-time using the RSK Mainnet explorer at [explorer.rsk.co/](https://explorer.rsk.co/). + +#### Acquiring RBTC for Deployment + +To deploy contracts on the RSK Mainnet, you need [RBTC](/rsk/rbtc/) to pay for transaction fees: + +- RBTC can be obtained by converting BTC to RBTC using the [Powpeg](/rsk/architecture/powpeg/) mechanism. Visit [RSK's Powpeg documentation](/rsk/architecture/powpeg/) for more information. +- Alternatively, you can purchase RBTC directly from supported exchanges. A list of exchanges offering RBTC is available at [RSK's official RBTC page](/rsk/rbtc/#exchanges) diff --git a/content/rsk-devportal/develop/tutorials/ethereum-devs/setup-truffle-oz.md b/content/rsk-devportal/develop/tutorials/ethereum-devs/setup-truffle-oz.md index 29eee4968e..2b2b4ee6b3 100644 --- a/content/rsk-devportal/develop/tutorials/ethereum-devs/setup-truffle-oz.md +++ b/content/rsk-devportal/develop/tutorials/ethereum-devs/setup-truffle-oz.md @@ -1,840 +1,639 @@ ---- -menu_title: Setup a project with Truffle and OpenZeppelin -layout: rsk -title: How to create a new project using Truffle and OpenZeppelin connected to RSK network -tags: tutorial, rsk, openzeppelin, truffle -description: "How to create a new blockchain project, using Truffle framework and Open Zeppelin library connected to a RSK local node and RSK testnet" -render_features: "custom-terminals" ---- - -> Sunsetting Truffle: Truffle has been sunsetted, see [Consensys Announcement](https://consensys.io/blog/consensys-announces-the-sunset-of-truffle-and-ganache-and-new-hardhat). Rootstock will no longer support Truffle and encourage immediate migration to [Hardhat](/tools/hardhat/). - -In this tutorial, I will show you step-by-step how to create a new blockchain project, using Truffle framework and Open Zeppelin smart contracts library, connected to a RSK local node or RSK testnet. - -It does not matter whether you are an experienced developer, or just learning to code, you do not need to be a blockchain expert to follow along. - -# Overview - -Here is a summary of the steps to be taken to build our project: - -1. Installation requirements; -2. Run a RSK local node; -3. Initialize a project using Truffle; -4. Install Open Zeppelin smart contracts in our project; -5. Install HD wallet provider; -6. Create a wallet mnemonic; -7. Configure Truffle to connect to RSK networks; -8. Use Truffle console; -9. Get some testnet RBTCs from the RSK faucet; - -## Translations - -This article is also available in -[Português](https://rsk.solange.dev/#/pt/setup-truffle-open-zeppelin/readme "Como criar um projeto utilizando Truffle e OpenZeppelin conectado à rede RSK"). - -# Requirements - -* POSIX compliant shell -* Curl -* Java -* Node.js and NPM (Node Package Manager) -* Code editor: Visual Studio Code (VSCode) or any other editor of your choice -* Truffle - -## POSIX compliant shell - -The **Portable Operating System Interface (POSIX)** is a family of standards specified by the IEEE Computer Society for maintaining compatibility between operating systems. POSIX defines the application programming interface (API), along with command line shells and utility interfaces, for software compatibility with variants of Unix and other operating systems. -Source: [Wikepidia](https://en.wikipedia.org/wiki/POSIX) - -* Mac OSX and Linux distributions: Use the standard terminal -* Windows: If you use the standard cmd terminal, or PowerShell, the commands here may not work. - Consider installing [Git for Windows](https://gitforwindows.org/), which comes with Git Bash bundled. - Here is a [tutorial on installing and using Git Bash](https://www.atlassian.com/git/tutorials/git-bash). - -## cURL - -This is a system command that is likely already installed on your system, -which allows you to make network requests, such as HTTP requests, -from your command line. - -If `curl --version` displays an error, -[download curl](https://curl.haxx.se/download.html). - -## Java - -You will need Java 8 in order to run RSKj. - -Check if you already have Java installed: - -```shell -java -version -``` - -```windows-command-prompt -C:\>java version -java version "1.8.0_241" -Java(TM) SE Runtime Environment (build 1.8.0_241-b07) -Java HotSpot(TM) Client VM (build 25.241-b07, mixed mode) - -C:\> -``` - -If `java -version` displays an error, -or displays a version other than 1.8, -you will need to install it. - -### Install Java on Windows - -Go to the official [Java download](https://www.java.com/en/download/) page, -download, and run the installer from there. - -![Java Download](/assets/img/tutorials/setup-truffle-oz/image-02.png) - -### Install Java on Mac OSX and Linux - -There are a variety of ways to do this, and SDKman is one which allows you to install and switch between multiple versions as needed: - -```shell -curl -s "https://get.sdkman.io/" | bash -source "$HOME/.sdkman/bin/sdkman-init.sh" -# to get a filtered list of available java versions -sdk list java | grep "8\." # copy a selection for use below - -# install the version of java copied above -# (replace accordingly) -sdk install java 8.0.242.j9-adpt - -# show installed versions, and switch to the selected one -# (replace accordingly) -sdk list java | grep installed -sdk use java 8.0.242.j9-adpt -java -version -``` - -## Node.js and NPM - -Another dependency is NPM, which comes bundled with Node.js. - -To check if you have node already installed, enter this command into your terminal: - -```shell -node --version -npm --version -``` - -```windows-command-prompt -C:\>node --version -v10.16.3 - -C:\>npm --version -v6.9.0 - -C:\> -``` - -If there's no output like that in the image above, go to [Node.js](https://nodejs.org/en/) install. - -Note that NPM is usually installed together with Node.js, so after installing Node.js, there's no need to install it separately. - -If you want to have more than one version installed, -the most fuss-free way to install and manage multiple versions of `node` on your computer is [nvm](https://github.com/nvm-sh/nvm). - -## Code editor - -We need some software that is able to edit text files. -Preferably one that has support for syntax highlighting for both Solidity and Javascript. - -[VS Code](https://code.visualstudio.com/) is a good choice if you don't already have one. - -### Visual Studio Code (VS Code) - -In this tutorial, we will use VS Code to create our project. - -To use VS Code [download it here](https://code.visualstudio.com/download). - -Verify if your VS Code installation was successful by typing the following command into the terminal: - -```shell -code -v -``` - -![vscode version](/assets/img/tutorials/setup-truffle-oz/image-04.png) - -## Truffle - -Truffle is a popular development framework with a mission to make smart contract development easier for developers. Amongst its features, it has a smart contract lifecycle management, scriptable deployment & migrations, automated contract testing and simple network management. - -It also makes developing on RSK easier, with the ability to configure custom networks for RSK. - -To install Truffle, input the command below into the terminal and press `enter` at your project location: - -```shell -npm install -g truffle -``` - -![truffle install](/assets/img/tutorials/setup-truffle-oz/image-05.png) - -When the installation is finished, close the terminal, open it again and check the Truffle version: - -```shell -truffle version -``` - -![truffle version](/assets/img/tutorials/setup-truffle-oz/image-06.png) - -For more info: - -[trufflesuite.com/truffle](https://www.trufflesuite.com/truffle) - -# RSK regtest (Local node) - -When we develop a project using Truffle Framework, we need a blockchain node running locally. This is better for development, and running tests. We'll connect to the RSK network via this local node. - -There are several ways to set up a RSK local node. Here, we will download a JAR file and run it using the Java SDK that has been installed. - -### Download - -Go to the [releases page](https://github.com/rsksmart/rskj/releases) and click on the most recent to download it. - -You need to click on the JAR file, in the end of the post about the lastest release. -It's name should be `rskj-core-*.jar`: - -![Download last RSK release](/assets/img/tutorials/setup-truffle-oz/image-07.png) - -### Verify authenticity - -When installing and running the RSKj node, -it is always a good idea to verify that your copy is legitimate. - -In the folder where you download the JAR file, go to a POSIX terminal and run this command: - -```shell -sha256sum rskj-core-3.1.0-IRIS-all.jar -``` - -For this version, it looked like this: - -```shell -43149abce0a737341a0b063f2016a1e73dae19b8af8f2e54657326ac8eedc8a0 *rskj-core-3.1.0-IRIS-all.jar -``` - -![Verify authenticity](/assets/img/tutorials/setup-truffle-oz/image-08.png) - -> Note that if you are using Windows, you will need a POSIX compliant shell for this. -> See instructions [about using Git Bash](#posix-compliant-shell) above. - -For more information about verifying that your copy is legitimate, -including signature verification, check out the -[full instructions](/rsk/node/security-chain/ "Verify authenticity of RskJ source code and its binary dependencies") -on how to do this. - -### Run - -To run the node: - -```shell -java -cp -Drpc.providers.web.cors=* co.rsk.Start --regtest -``` - -(Replace with your path to the JAR file). - -I am using a Windows OS and I saved the file at `C:\RSK\node`, -so for me the full path is `C:\RSK\node\rskj-core-3.1.0-IRIS-all.jar`. - -The commands required to run the RSK node are: - -#### On Windows terminal - -```shell -java -cp C:\RSK\node\rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest -``` - -#### Using Git Bash - -```shell -java -cp C:/RSK/node/rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest -``` - -#### On Linux and Mac - -```shell -java -cp ~/RSK/node/rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest -``` - -If you see no output - that is a good thing: -Its output is directed to a log file. - -> Note the flag provided above: `-Drpc.providers.web.cors=*` -> This disables cross origin resource sharing protection, -> effectively allowing any web page to access it. -> As we want to make JSON-RPC requests from a browser, -> such as a DApp, we need this flag. - -This is the result in the terminal in Windows OS: - -![Run local node](/assets/img/tutorials/setup-truffle-oz/image-09.png) - -**Important:** - -> Do not close this terminal/console window, -> if closed the local node will stop running. - -### Check if the node is running using cURL - -Open a new terminal window. - -Issue a JSON-RPC request to the RSK node's HTTP server. - -This is an example using cURL: - -```shell -curl localhost:4444/1.1.0/ -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' -``` - -![local node eth_blockNumber](/assets/img/tutorials/setup-truffle-oz/image-10.png) - -The response should look similar to this: - -```json -{"jsonrpc":"2.0","id":1,"result":"0x2991b"} -``` - -The `result` property is the number of the latest block that has been synced. Note that this value (`0x2991b`) is the block number in hexadecimal (base 16), so the output above indicates that the current block number is `170267` in decimal (base 10). - -* To get more information about this process: - Check out [set up RSKj with Java](/rsk/node/install/java/). -* If you encounter any problems, check if your system meets the - [minimum requirements](/rsk/node/install/requirements/). -* There are other ways to install an RSK node, in other supported platforms: - Check out [installing RSKj](/rsk/node/install/). - -# RSK Testnet - verify the connection - -In addition to using the local node, we want to publish smart contracts to the testnet. Before it, let's check if the connection is working. - -This is an example using cURL. Enter the following command into your terminal. - -```shell -curl https://public-node.testnet.rsk.co/ -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' -``` - -This is a very simple query that simply asks what the latest block number is. - -You should receive a response similar to the following: - -```json -{"jsonrpc":"2.0","id":1,"result":"0xc3f9b"} -``` - -![testnet eth_blockNumber](/assets/img/tutorials/setup-truffle-oz/image-11.png) - -The result field is presented in hexadecimal. `0xc3f9b` is the block number, and it's decimal equivalent is: `802715`. -You can consult [testnet explorer](https://explorer.testnet.rsk.co/) and verify that it is the same result for block number. - -![explorer testnet block number](/assets/img/tutorials/setup-truffle-oz/image-12.png) - -# Initialize a Truffle project - -We have two options for initializing a project: - -1. An empty project -2. A project based in a Truffle Box - -## 1 - Initialize an empty Truffle project - -Create a new folder. For example, `myproject`, and navigate to the folder in the terminal. - -```shell -mkdir myproject -cd myproject -``` - -For example, I will create a folder at this location - `C:\RSK\` (I'm using Windows). - -My project can be located in the folder `C:\RSK\myproject`. - -![myproject folder](/assets/img/tutorials/setup-truffle-oz/image-13.png) - -In your project folder, start an Truffle project by typing the command below into the terminal: - -```shell -truffle init -``` - -![truffle init](/assets/img/tutorials/setup-truffle-oz/image-14.png) - -Open the folder in VS Code to view the file structure like this: - -![truffle file structure](/assets/img/tutorials/setup-truffle-oz/image-15.png) - -* `./contracts`: All our smart contracts will be stored in this folder. -* `./migrations`: Deployment scripts will be stored in this folder. -* `./test`: Test scripts will be stored in this folder. -* `./truffle-config.js`: This is Truffle's configuration file used to configure networks, including RSK networks. - -Note that the following files were also created: - -* `Migrations.sol`: Keeps track of which migrations were done on the current network. -* `1_initial_migration.js`: Deployment instructions for `Migrations.sol`. - -### Initialize an npm project - -When we initialize an empty Truffle project, we also need to initialize an npm project. - -Start an npm project in the `myproject` folder by typing the following commands below into the terminal: - -```shell -npm init -y -``` - -![npm init](/assets/img/tutorials/setup-truffle-oz/image-16.png) - -## 2 - Initialize a project based in a Truffle Box - -> Note: Only do this if you have not done option 1. - -Truffle Boxes are templates. -In addition to Truffle, -Truffle Boxes can contain other helpful modules, such as Solidity smart contracts, libraries, front-end views, and more. - -In option 1, when we use `truffle init`, we used a special kind of truffle box. -Check out other [boxes] (https://www.trufflesuite.com/boxes). - -Also we have some of them already configured for RSK, [check it out here](https://developers.rsk.co/tutorials/truffle-boxes/). - -## Install Open Zeppelin - -Open Zeppelin Contracts is a set of libraries of Solidity smart contracts for Ethereum and other blockchains. -These libraries will install not only the main libraries required for our token, -but also libraries for ownership, safe math, and many other utilities. -It's worth mentioning that these libraries have been reviewed and audited to accomplish high standards of security, -so contracts that depend on them are less susceptible to hacking when used correctly. - -In the terminal, inside `myproject` folder, install Open Zeppelin libraries using this command: - -```shell -npm install -E @openzeppelin/contracts@2.5.0 -``` - -The option `-E` is to save dependencies with an exact version rather than the latest version published on npm. - -![openzeppelin install](/assets/img/tutorials/setup-truffle-oz/image-17.png) - -> Some contracts may change over time, so it is important to set the version. This tutorial was written using this specific version. - -For more info: - -[openzeppelin.com/contracts](https://openzeppelin.com/contracts/) - -# Install HD wallet provider - -To connect to the RSK network, we are going to use a provider that allows us to connect to any network by unlocking an account locally. We are going to use `@truffle/hdwallet-provider`. -This can be used to sign transactions for addresses derived from a 12 or 24 word mnemonic. - -> You need to have Node >= 7.6 installed. - -In the terminal, inside the `myproject` folder, install the HD wallet provider with this command: - -```shell -npm install -E @truffle/hdwallet-provider@1.0.34 -``` - -![hd wallet provider install](/assets/img/tutorials/setup-truffle-oz/image-18.png) - -This `truffle package` comes with many dependencies, -and so can take a long time to complete. -A successful installation message is shown if everything works fine. - -![hd wallet provider successful installation](/assets/img/tutorials/setup-truffle-oz/image-19.png) - -# Check package.json - -`package.json` is a file created by npm with some configurations, -including the packages which we installed before using the command `npm init -y`. - -After the installations, -I will open the project folder named `myproject` in VS Code and verify the file `package.json`. -Let's take a look at the dependencies in the file: - -![package.json](/assets/img/tutorials/setup-truffle-oz/image-20.png) - -# Create a wallet - -To use testnet, we need tRBTC and an address to store them. -The best way is to create a wallet from a mnemonic, using the pattern defined at [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) - -There are a few ways to do this. - -One is to create using a web wallet, such as [Metamask](https://metamask.io/). -These wallets generate the mnemonic for you. -If you wanted to create using Metamask, you can get the instructions here: - -- [using Remix and Metamask with RSK testnet](/tutorials/ethereum-devs/remix-and-metamask-with-rsk-testnet/) - -## iancoleman.io/bip39 - -Another way is using this web app: - -[iancoleman.io/bip39](https://iancoleman.io/bip39/) - -> Note: In this tutorial, the method used to store the mnemonic is not recommended to be used for any 'real' wallet because it's not secure enough to generate a private key in a website, however we will use this here for learning purposes, and because we're using the Testnet, so no real amounts are at stake. - -In the `Generate a random mnemonic` field, select `12 words` and click on the `generate` button. - -![Generate a random mnemonic](/assets/img/tutorials/setup-truffle-oz/image-21.png) - -The result appears in the `BIP39 Mnemonic` field. -They should be 12 random words like the words in the image: - -![BIP39 Mnemonic](/assets/img/tutorials/setup-truffle-oz/image-22.png) - -My mnemonic is: - -``` -energy knife ice mouse merge track cram brown decorate atom rule virus -``` - -Copy these 12 words, we'll use it later in this tutorial. - -## mnemonics module - -Another alternative is using package [mnemonics](https://github.com/itinance/mnemonics), -which is a simple utility that can be used to generate [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonics. - -To install `mnemonics` globally, input the command below into the terminal and press `enter` at your project location: - -```shell -npm install -g mnemonics@1.1.3 -``` - -Use this to generate a 12-word BIP39 mnemonic, by entering this command: - -```shell -mnemonics > .secret -``` - -This saves a new mnemonic in the file named `.secret`, which is the next step. - -# Create .secret file - -In the terminal, inside the `myproject` folder, create a file named `.secret`. - -Do you remember your mnemonic? -Paste your mnemonic in this file and save it. - -![dot secret](/assets/img/tutorials/setup-truffle-oz/image-23.png) - -# Configure Truffle to connect to RSK networks - -Open `truffle-config.js` file in your Truffle project and overwrite it with the following code: - -```javascript -const HDWalletProvider = require('@truffle/hdwallet-provider'); - -const fs = require('fs'); -const mnemonic = fs.readFileSync(".secret").toString().trim(); -if (!mnemonic || mnemonic.split(' ').length !== 12) { - throw new Error('unable to retrieve mnemonic from .secret'); -} - -module.exports = { - networks: { - }, - compilers: { - solc: { - } - } -} -``` - -The `hdwallet-provider` allows us to connect to any network by unlocking an account locally, including the RSK networks. - -Also we are loading the mnemonic stored in file `.secret`, and saving it at variable mnemonic. - -## Configure Truffle to connect to RSK regtest (local node) - -In the `truffle-config.js` file, include this configuration at `network` section: - -```javascript - development: { - host: "127.0.0.1", - port: 4444, - network_id: "*" - }, -``` - -This is the result: - -![network development](/assets/img/tutorials/setup-truffle-oz/image-24.png) - -## Get the current gas price of testnet - -Get the current gas price of the testnet network, and save to `.gas-price-testnet.json`. - -In your project folder, run this cURL command: - -```shell -curl https://public-node.testnet.rsk.co/ -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}' > .gas-price-testnet.json -``` - -![gas price result](/assets/img/tutorials/setup-truffle-oz/image-25.png) - -You should receive a response similar to the following in the file: - -```json -{"jsonrpc":"2.0","id":1,"result":"0x3938700"} -``` - -![gas-price-testnet.json](/assets/img/tutorials/setup-truffle-oz/image-26.png) - -The result value is presented in hexadecimal. - -Modify the `truffle-config` file again to use the updated gas price. After mnemonic part, include this: - -```javascript -const gasPriceTestnetRaw = fs.readFileSync(".gas-price-testnet.json").toString().trim(); -const gasPriceTestnet = parseInt(JSON.parse(gasPriceTestnetRaw).result, 16); -if (typeof gasPriceTestnet !== 'number' || isNaN(gasPriceTestnet)) { - throw new Error('unable to retrieve network gas price from .gas-price-testnet.json'); -} -console.log("Gas price Testnet: " + gasPriceTestnet); -``` - -## Configure Truffle to connect to RSK testnet - -In the `truffle-config.js` file, include this configuration at `network` section: - -```javascript - testnet: { - provider: () => new HDWalletProvider(mnemonic, 'https://public-node.testnet.rsk.co/'), - network_id: 31, - gasPrice: Math.floor(gasPriceTestnet * 1.1), - networkCheckTimeout: 1e9 - }, -``` - -## Truffle config with local and testnet RSK networks - -This is the final `truffle-config.js` file with configurations for both networks: - -```javascript -const HDWalletProvider = require('@truffle/hdwallet-provider'); - -const fs = require('fs'); -const mnemonic = fs.readFileSync(".secret").toString().trim(); -if (!mnemonic || mnemonic.split(' ').length !== 12) { - throw new Error('unable to retrieve mnemonic from .secret'); -} - -const gasPriceTestnetRaw = fs.readFileSync(".gas-price-testnet.json").toString().trim(); -const gasPriceTestnet = parseInt(JSON.parse(gasPriceTestnetRaw).result, 16); -if (typeof gasPriceTestnet !== 'number' || isNaN(gasPriceTestnet)) { - throw new Error('unable to retrieve network gas price from .gas-price-testnet.json'); -} -console.log("Gas price Testnet: " + gasPriceTestnet); - -module.exports = { - networks: { - development: { - host: "127.0.0.1", - port: 4444, - network_id: "*" - }, - testnet: { - provider: () => new HDWalletProvider(mnemonic, 'https://public-node.testnet.rsk.co/'), - network_id: 31, - gasPrice: Math.floor(gasPriceTestnet * 1.1), - networkCheckTimeout: 1e9 - }, - }, - compilers: { - solc: { - } - } -} -``` - -Check out the VS Code image too: - -![truffle-config](/assets/img/tutorials/setup-truffle-oz/image-27.png) - -# Truffle Console connected to RSK network - -Truffle has its own console to run commands, and can be connected on any network previously configured in `truffle-config.js` file. - -## Connect to RSK regtest (local node) - -Let's open a Truffle console to connect to our local node. - -In the terminal, inside the `myproject` folder, run this command: - -```shell -truffle console -``` - -![Truffle console development](/assets/img/tutorials/setup-truffle-oz/image-28.png) - -> Any network defined with the name `development` is considered the default network. - -## Connect to RSK testnet - -Thus far we have only connected to a blockchain that runs using just 1 node, that runs on your own computer. -Let's now switch to interacting with a "real" blockchain, which is running on multiple nodes distributed across multiple computers! - -To connect Truffle console in another network, you need to specify the network: - -Open up a new terminal. - -In the new terminal, inside the `myproject` folder, run this command: - -```shell -truffle console --network testnet -``` - -It takes a little longer to establish this connection when compared to the local node. -This will open a new console: - -![truffle console network testnet](/assets/img/tutorials/setup-truffle-oz/image-29.png) - -## Test the connection to RSK network - -On any of the networks, run this commands in the Truffle console: - -### Block number - -Shows the last block number. - -```javascript -(await web3.eth.getBlockNumber()).toString() -``` - -![getBlockNumber](/assets/img/tutorials/setup-truffle-oz/image-30.png) - -### Network ID - -To get the network ID, run this command: - -```javascript -(await web3.eth.net.getId()).toString() -``` - -For the local node, the network ID is `33`. - -![getId local](/assets/img/tutorials/setup-truffle-oz/image-31.png) - -And for testnet, it is `31`. - -![getId testnet](/assets/img/tutorials/setup-truffle-oz/image-32.png) - -## Exit Truffle console - -In the Truffle console, enter this command to exit the terminal: - -```shell -.exit -``` - -![exit Truffle console](/assets/img/tutorials/setup-truffle-oz/image-33.png) - -# Get addresses - -We will use a special instruction in Truffle console to get the first 10 addresses in our hierarchical deterministic wallet for the RSK Testnet network, that are generated from our mnemonic. - -In the terminal, inside the `myproject` folder, go to the Truffle console connected to testnet: - -```shell -truffle console --network testnet -``` - -And run this command to save the addresses at variable `accounts`: - -```javascript -const accounts = Object.keys(web3.currentProvider.wallets) -``` - -See the addresses after it by entering the command below: - -```javascript -accounts -``` - -![list accounts](/assets/img/tutorials/setup-truffle-oz/image-34.png) - -Now we will write them to a file named `.accounts` - -```javascript -await require('fs').promises.writeFile('.accounts', accounts.join('\n')) -``` - -![create file .accounts](/assets/img/tutorials/setup-truffle-oz/image-35.png) - -And we can check the file: - -![file .accounts](/assets/img/tutorials/setup-truffle-oz/image-36.png) - -## Check balance - -To check the balance of an account, for example, the first account of our list (`account[0]`), run this command in Truffle console: - -```javascript -(await web3.eth.getBalance(accounts[0])).toString() -``` - -![getBalance accounts 0](/assets/img/tutorials/setup-truffle-oz/image-37.png) - -The balance is 0 and we need some tRBTC to pay gas fees, -which will be used to publish smart contracts and interact with them. -We shall obtain some in the next step. - -# TestNet Faucet - -You can get some tRBTC from the [RSK Testnet faucet](https://faucet.testnet.rsk.co/). - -Copy the first address from `.accounts` file. In my case, it is - -``` -0xe16f6abdd5815f3d24b4e5c29138f863933b000a -``` - -Enter your wallet address and pass the CAPTCHA. - -![faucet.testnet.rsk.co](/assets/img/tutorials/setup-truffle-oz/image-38.png) - -Wait a few seconds… - -![Wait a few seconds](/assets/img/tutorials/setup-truffle-oz/image-39.png) - -![Received some RBTCs](/assets/img/tutorials/setup-truffle-oz/image-40.png) - -You can see the transaction hash: - -[0x4a2bf1f65c525219020c3a1215a29453c20f4ced90575d9a7d13f8fe666d05b4](https://explorer.testnet.rsk.co/tx/0x4a2bf1f65c525219020c3a1215a29453c20f4ced90575d9a7d13f8fe666d05b4) - -Now I have 0.05 RBTC! - -## Recheck balance - -To check balance again, run this command in the Truffle console: - -```javascript -(await web3.eth.getBalance(accounts[0])).toString() -``` - -![getBalance accounts 0 again](/assets/img/tutorials/setup-truffle-oz/image-41.png) - -Great! Now I have 50000000000000000, which means that I have 0.05 tRBTC with 18 decimal places of precision. - -# Where to go from here - -At this point, we have installed all requirements and created an empty project using Truffle framework and Open Zeppelin smart contracts library, -connected to both an RSK local node (Regtest) and the RSK Testnet. - -We have not developed anything yet, -but you are now ready to move on to the next tutorials, -where we will develop some very cool projects! - -Choose any of these to tutorials to begin: - -- [Create your first Token](https://developers.rsk.co/tutorials/tokens/create-a-token/) -- [Petshop](https://developers.rsk.co/tutorials/truffle-boxes/pet-shop-box/) -- [Create your own collectable token](https://developers.rsk.co/tutorials/tokens/create-a-collectable-token/) +--- +menu_title: Setup a project with Hardhat and OpenZeppelin +layout: rsk +title: How to create a new project using Hardhat and OpenZeppelin connected to RSK network +tags: tutorial, rsk, openzeppelin, hardhat +description: "How to create a new blockchain project, using Hardhat framework and Open Zeppelin library connected to a RSK local node and RSK testnet" +render_features: "custom-terminals" +--- + +In this tutorial, I will show you step-by-step how to create a new blockchain project, using Hardhat framework and Open Zeppelin smart contracts library, connected to a RSK local node or RSK testnet. + +It does not matter whether you are an experienced developer, or just learning to code, you do not need to be a blockchain expert to follow along. + +# Overview + +Here is a summary of the steps to be taken to build our project: + +1. Requirements; +2. Run a RSK local node; +3. Initialize a project using Hardhat; +4. Configure Hardhat to connect to RSK networks; +5. Get some testnet RBTCs from the RSK faucet; + +# Requirements + +* POSIX compliant shell +* Curl +* Java +* Node.js and NPM (Node Package Manager) +* Code editor: Visual Studio Code (VSCode) or any other editor of your choice +* Hardhat + +## POSIX compliant shell + +The **Portable Operating System Interface (POSIX)** is a family of standards specified by the IEEE Computer Society for maintaining compatibility between operating systems. POSIX defines the application programming interface (API), along with command line shells and utility interfaces, for software compatibility with variants of Unix and other operating systems. +Source: [Wikepidia](https://en.wikipedia.org/wiki/POSIX) + +* Mac OSX and Linux distributions: Use the standard terminal +* Windows: If you use the standard cmd terminal, or PowerShell, the commands here may not work. + Consider installing [Git for Windows](https://gitforwindows.org/), which comes with Git Bash bundled. + Here is a [tutorial on installing and using Git Bash](https://www.atlassian.com/git/tutorials/git-bash). + +## cURL + +This is a system command that is likely already installed on your system, +which allows you to make network requests, such as HTTP requests, +from your command line. + +If `curl --version` displays an error, +[download curl](https://curl.haxx.se/download.html). + +## Java + +You will need Java 8 in order to run RSKj. + +Check if you already have Java installed: + +```shell +java -version +``` + +```windows-command-prompt +C:\>java version +java version "1.8.0_241" +Java(TM) SE Runtime Environment (build 1.8.0_241-b07) +Java HotSpot(TM) Client VM (build 25.241-b07, mixed mode) + +C:\> +``` + +If `java -version` displays an error, +or displays a version other than 1.8, +you will need to install it. + +### Install Java on Windows + +Go to the official [Java download](https://www.java.com/en/download/) page, +download, and run the installer from there. + +![Java Download](/assets/img/tutorials/setup-truffle-oz/image-02.png) + +### Install Java on Mac OSX and Linux + +There are a variety of ways to do this, and SDKman is one which allows you to install and switch between multiple versions as needed: + +```shell +curl -s "https://get.sdkman.io/" | bash +source "$HOME/.sdkman/bin/sdkman-init.sh" +# to get a filtered list of available java versions +sdk list java | grep "8\." # copy a selection for use below + +# install the version of java copied above +# (replace accordingly) +sdk install java 8.0.242.j9-adpt + +# show installed versions, and switch to the selected one +# (replace accordingly) +sdk list java | grep installed +sdk use java 8.0.242.j9-adpt +java -version +``` + +## Node.js and NPM + +Another dependency is NPM, which comes bundled with Node.js. + +To check if you have node already installed, enter this command into your terminal: + +```shell +node --version +npm --version +``` + +```windows-command-prompt +C:\>node --version +v21.6.2 + +C:\>npm --version +10.2.4 + +C:\> +``` + +If there's no output like that in the image above, go to [Node.js](https://nodejs.org/en/) install. + +Note that NPM is usually installed together with Node.js, so after installing Node.js, there's no need to install it separately. + +If you want to have more than one version installed, +the most fuss-free way to install and manage multiple versions of `node` on your computer is [nvm](https://github.com/nvm-sh/nvm). + +## Code editor + +We need some software that is able to edit text files. +Preferably one that has support for syntax highlighting for both Solidity and Javascript. + +[VS Code](https://code.visualstudio.com/) is a good choice if you don't already have one. + +### Visual Studio Code (VS Code) + +In this tutorial, we will use VS Code to create our project. + +To use VS Code [download it here](https://code.visualstudio.com/download). + +Verify if your VS Code installation was successful by typing the following command into the terminal: + +```shell +code -v +``` + +![vscode version](/assets/img/tutorials/setup-truffle-oz/image-04.png) + +# Run a RSK local node + +When we develop a project using Hardhat Framework, we need a blockchain node running locally. This is better for development, and running tests. We'll connect to the RSK network via this local node. + +There are several ways to set up a RSK local node. Here, we will download a JAR file and run it using the Java SDK that has been installed. + +## Download + +Go to the [releases page](https://github.com/rsksmart/rskj/releases) and click on the most recent to download it. + +You need to click on the JAR file, in the end of the post about the lastest release. +It's name should be `rskj-core-*.jar`: + +![Download last RSK release](/assets/img/tutorials/setup-truffle-oz/image-07.png) + +### Verify authenticity + +When installing and running the RSKj node, it is always a good idea to verify that your copy is legitimate. + +In the folder where you download the JAR file, go to a POSIX terminal and run this command: + +```shell +sha256sum rskj-core-3.1.0-IRIS-all.jar +``` + +For this version, it looked like this: + +```shell +43149abce0a737341a0b063f2016a1e73dae19b8af8f2e54657326ac8eedc8a0 *rskj-core-3.1.0-IRIS-all.jar +``` + +![Verify authenticity](/assets/img/tutorials/setup-truffle-oz/image-08.png) + +> Note that if you are using Windows, you will need a POSIX compliant shell for this. +> See instructions [about using Git Bash](#posix-compliant-shell) above. + +For more information about verifying that your copy is legitimate, +including signature verification, check out the +[full instructions](/rsk/node/security-chain/ "Verify authenticity of RskJ source code and its binary dependencies") +on how to do this. + +## Run + +To run the node: + +```shell +java -cp -Drpc.providers.web.cors=* co.rsk.Start --regtest +``` + +(Replace with your path to the JAR file). + +I am using a Windows OS and I saved the file at `C:\RSK\node`, +so for me the full path is `C:\RSK\node\rskj-core-3.1.0-IRIS-all.jar`. + +The commands required to run the RSK node are: + +#### On Windows terminal + +```shell +java -cp C:\RSK\node\rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest +``` + +#### Using Git Bash + +```shell +java -cp C:/RSK/node/rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest +``` + +#### On Linux and Mac + +```shell +java -cp ~/RSK/node/rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest +``` + +If you see no output - that is a good thing: +Its output is directed to a log file. + +> Note the flag provided above: `-Drpc.providers.web.cors=*` +> This disables cross origin resource sharing protection, +> effectively allowing any web page to access it. +> As we want to make JSON-RPC requests from a browser, +> such as a DApp, we need this flag. + +This is the result in the terminal in Windows OS: + +![Run local node](/assets/img/tutorials/setup-truffle-oz/image-09.png) + +**Important:** + +> Do not close this terminal/console window, +> if closed the local node will stop running. + +### Check if the node is running using cURL + +Open a new terminal window. + +Issue a JSON-RPC request to the RSK node's HTTP server. + +This is an example using cURL: + +```shell +curl localhost:4444/1.1.0/ -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' +``` + +![local node eth_blockNumber](/assets/img/tutorials/setup-truffle-oz/image-10.png) + +The response should look similar to this: + +```json +{"jsonrpc":"2.0","id":1,"result":"0x2991b"} +``` + +The `result` property is the number of the latest block that has been synced. Note that this value (`0x2991b`) is the block number in hexadecimal (base 16), so the output above indicates that the current block number is `170267` in decimal (base 10). + +* To get more information about this process: + Check out [set up RSKj with Java](/rsk/node/install/java/). +* If you encounter any problems, check if your system meets the + [minimum requirements](/rsk/node/install/requirements/). +* There are other ways to install an RSK node, in other supported platforms: + Check out [installing RSKj](/rsk/node/install/). + +## RSK Testnet - verify the connection + +In addition to using the local node, we want to publish smart contracts to the testnet. Before it, let's check if the connection is working. + +This is an example using cURL. Enter the following command into your terminal. + +```shell +curl https://public-node.testnet.rsk.co/ -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' +``` + +This is a very simple query that simply asks what the latest block number is. + +You should receive a response similar to the following: + +```json +{"jsonrpc":"2.0","id":1,"result":"0xc3f9b"} +``` + +![testnet eth_blockNumber](/assets/img/tutorials/setup-truffle-oz/image-11.png) + +The result field is presented in hexadecimal. `0xc3f9b` is the block number, and it's decimal equivalent is: `802715`. +You can consult [testnet explorer](https://explorer.testnet.rsk.co/) and verify that it is the same result for block number. + +![explorer testnet block number](/assets/img/tutorials/setup-truffle-oz/image-12.png) + +# Initialize a project using Hardhat + +Hardhat is a cutting-edge development environment designed for Ethereum application development. It aims to bring developers a robust framework for building, testing, and deploying smart contracts with ease. Key features of Hardhat include advanced Ethereum Virtual Machine (EVM) manipulation and debugging, comprehensive testing libraries, and seamless network management. + +Hardhat enhances the developer experience by allowing for the creation of local Ethereum networks, simulating how contracts interact in a real-world environment, and pinpointing errors with stack traces. This environment is particularly beneficial for intricate development workflows and offers detailed insights during the contract creation phase. + +For more detailed information and documentation, visit: + +[https://hardhat.org/](https://github.com/nvm-sh/nvm) + +## Create the project directory + +Create a new directory for your project. As an example, we'll name it `myproject`. Navigate to your desired location, such as `C:\RSK\` on Windows, and create the directory: + +```shell +mkdir C:\RSK\myproject +cd C:\RSK\myproject +``` + +Your project will be located in `C:\RSK\myproject`. + +## Initialize an npm Project + +It's also recommended to initialize an npm project within your `myproject` folder to manage dependencies: + +```shell +npm init -y +``` + +This creates a `package.json` file in your project directory. + +## Starting with Hardhat + +To get started with Hardhat, run the following command in your project's root directory: + +```shell +npm install --save-dev hardhat +``` + +This command sets up your Hardhat project and prepares it for development. You'll be prompted to create a sample project, including configuration and sample scripts, to kick-start your development process. + +Check the version of Hardhat installed with: + +```shell +npx hardhat --version +``` + +![myproject folder](/assets/img/tutorials/setup-truffle-oz/image-13.png) + +To initiate a Hardhat project in your `myproject` directory, enter the following command in the terminal: + +```shell +npx hardhat init +``` + +Upon initialization, Hardhat will prompt you to create a sample project or start from scratch. Choose to create a sample project to automatically generate a basic project structure and configuration files. + +## Explore the Project Structure + +After initializing your Hardhat project, you can open the folder in an IDE like VS Code to see the file structure, which should include: + +- `contracts/`: Directory for Solidity smart contracts. +- `scripts/`: Contains scripts for deployment and interaction with your contracts. +- `test/`: Directory for test files to test your contracts and scripts. +- `hardhat.config.js`: Hardhat's configuration file. + +Note: Since Hardhat version `2.22.0` Hardhat Toolbox adds `Hardhat Ignition` as the default deployment system. It replaces the folder `scripts/` for `ignition/`. Hardhat Ignition is a declarative system for deploying smart contracts on Ethereum. It enables you to define smart contract instances you want to deploy, and any operation you want to run on them. + +### Install OpenZeppelin Contracts + +OpenZeppelin Contracts is a library of secure and community-reviewed smart contracts for Ethereum and other EVM and eWASM blockchains. To install OpenZeppelin Contracts in your project, use the following command: + +```shell +npm install @openzeppelin/contracts +``` + +Note: + +### Verify `package.json` + +After installing your dependencies, open your `package.json` file to verify the installations. You should see `@openzeppelin/contracts` and the Hardhat-related packages listed under `dependencies` or `devDependencies`. + +### Executing the Project's Test Suite + +To verify the contract's functionality using the internal Hardhat network, execute the following command: + +```shell +npx hardhat test +``` + +This command initiates the testing process, leveraging the Hardhat framework to compile your contracts and deploy them onto the internal network. Subsequently, it runs the test suite defined within your project, ensuring the integrity and functionality of your smart contracts. + +# Configure Hardhat to connect to RSK networks + +## Connect to RSK Regtest (local node) + +In Hardhat, network configurations are managed within the `hardhat.config.js` file. To connect to the RSK regtest (local node), you will modify this configuration file accordingly. + +Open your `hardhat.config.js` file and include the RSK regtest network configuration within the networks section. If you're starting from a default Hardhat setup, you might need to add the networks key to the module exports object. + +Here's how to add the RSK regtest configuration: + +```javascript + require("@nomicfoundation/hardhat-toolbox"); + + module.exports = { + solidity: "0.8.24", + networks: { + rskRegtest: { + url: "http://127.0.0.1:4444/", + chainId: 33, // RSK regtest chainId + } + } + }; +``` + +This configuration specifies that the RSK regtest network is accessible through HTTP at 127.0.0.1 on port 4444, which is the default configuration for a local RSK node. The chainId for RSK regtest is 33. Make sure that your local RSK node is running and accessible at these settings. + +After adding the configuration, your `hardhat.config.js` file should look similar to the example provided, albeit with possible differences in Solidity version or additional configurations depending on your project's requirements. + +## Connect to RSK testnet + +### Create a Wallet for Testnet Usage + +For interacting with testnets, you'll need a wallet with testnet ETH. You can generate a new mnemonic (a 12-word seed phrase) for your wallet using online tools like iancoleman.io/bip39 for educational purposes or by using a secure wallet application like MetaMask. + +### Store Your Mnemonic Securely + +First, make sure you are securely managing your mnemonic. One common approach is to use a `.env` file and dotenv package. If you choose this method, first install dotenv: + +```shell +npm install --save-dev dotenv +``` + +Then, create a .env file at the root of your project (this file should be added to your .gitignore to keep your mnemonic secure) and add your mnemonic: + +``` +MNEMONIC=your_mnemonic_here +``` + +Next, modify your hardhat.config.js to use the .env file and configure the RSK testnet connection: + +```javascript +require("@nomicfoundation/hardhat-toolbox"); +require('dotenv').config(); + +const { MNEMONIC } = process.env; + +module.exports = { + solidity: "0.8.24", + networks: { + rskRegtest: { + url: "http://127.0.0.1:4444/", + chainId: 33, // RSK regtest chainId + }, + testnet: { + url: 'https://public-node.testnet.rsk.co/', + accounts: { + mnemonic: MNEMONIC, + }, + chainId: 31 + } + } +}; +``` + +This configuration uses the mnemonic from your .env file to generate accounts for transactions on the RSK testnet. + +## Hardhat console connected to RSK network + +Hardhat has its own console to run commands, and can be connected on any network previously configured in `hardhat.config.js` file. + +### Connect to RSK regtest (local node) + +Let's open a Hardhat console to connect to our local node. To start the Hardhat console you can use the --network flag followed by the name of the network you've configured in your hardhat.config.js file. For example, to connect to the RSK Testnet, you would run: + +```shell +npx hardhat console --network rskRegtest +``` + +![Truffle console development](/assets/img/tutorials/setup-truffle-oz/image-28.png) + +This command starts an interactive session where you can execute commands and interact with your smart contracts deployed on the RSK Testnet. Here are a few examples of what you can do within the Hardhat console: + +```javascript +const Lock = await ethers.getContractFactory("Lock"); +const JAN_1ST_2030 = 1893456000; +const ONE_GWEI = 1_000_000_000n; +const lock = await Lock.deploy(JAN_1ST_2030); +const lock_address = await lock.getAddress(); +console.log("Lock deployed to:", lock_address); +``` + +Interact with a deployed contract: + +```javascript +const lock_contract = await ethers.getContractAt("Lock", "REPLACE_WITH_CONTRACT_ADDRESS"); +const tx = await lock_contract.withdraw(); +result = tx.wait(); +``` + +The result of this transaction is an error message containing 'Error: transaction execution reverted'. This is an expected behavior, the contract has a time lock in order to allow withdrawing the funds deposited.. + +Send transactions and query balances: + +```javascript +const [owner] = await ethers.getSigners(); +const balance = await ethers.provider.getBalance(owner.address); +console.log("Address: ", owner.address, "Balance: ", ethers.formatEther(balance)); +``` + +Thus far we have only connected to a blockchain that runs using just 1 node, that runs on your own computer. + +### Connect to RSK testnet + +Let's now switch to interacting with a "real" blockchain, which is running on multiple nodes distributed across multiple computers! + +To connect Hardhat console in another network, you need to specify the network: + +Open up a new terminal. + +In the new terminal, inside the `myproject` folder, run this command: + +```shell +npx hardhat console --network testnet +``` + +It takes a little longer to establish this connection when compared to the local node. +This will open a new console: + +![truffle console network testnet](/assets/img/tutorials/setup-truffle-oz/image-29.png) + +### Test the connection to RSK network + +On any of the networks, run this commands in the Hardhat console: + +#### Block number + +Shows the last block number. + +```javascript +(await ethers.provider.getBlockNumber()).toString() +``` + +![getBlockNumber](/assets/img/tutorials/setup-truffle-oz/image-30.png) + +#### Get addresses + +We will use a special instruction in Hardhat console to get the address in our wallet for the RSK Testnet network, it is generated from our mnemonic. + +```javascript +// Import ethers from the Hardhat environment +const ethers = hre.ethers; + +// Define the mnemonic. You can paste your MNemonic here to use your current wallet. +const mnemonic = "test test test test test test test test test test test junk"; + +// Get address +const address = ethers.Wallet.fromPhrase(mnemonic).address; +console.log(address); +``` + +![list accounts](/assets/img/tutorials/setup-truffle-oz/image-34.png) + +#### Check balance + +To check the balance of an account run this command in Hardhat console: + +```javascript +const balance = await ethers.provider.getBalance(address); +console.log(ethers.formatEther(balance)); +``` + +![getBalance accounts 0](/assets/img/tutorials/setup-truffle-oz/image-37.png) + +The balance is 0 and we need some tRBTC to pay gas fees, which will be used to publish smart contracts and interact with them. We shall obtain some in the next step. + +#### Exit Hardhat console + +In the Hardhat console, enter this command to exit the terminal: + +```shell +.exit +``` + +```shell +Ctrl+C +``` + +![exit Truffle console](/assets/img/tutorials/setup-truffle-oz/image-33.png) + +# Get some testnet RBTCs from the RSK faucet + +You can get some tRBTC from the [RSK Testnet faucet](https://faucet.testnet.rsk.co/). + +Copy the address from the account. In my case, it is + +``` +0xe16f6abdd5815f3d24b4e5c29138f863933b000a +``` + +Enter your wallet address and pass the CAPTCHA. + +![faucet.testnet.rsk.co](/assets/img/tutorials/setup-truffle-oz/image-38.png) + +Wait a few seconds… + +![Wait a few seconds](/assets/img/tutorials/setup-truffle-oz/image-39.png) + +![Received some RBTCs](/assets/img/tutorials/setup-truffle-oz/image-40.png) + +You can see the transaction hash: + +[0x4a2bf1f65c525219020c3a1215a29453c20f4ced90575d9a7d13f8fe666d05b4](https://explorer.testnet.rsk.co/tx/0x4a2bf1f65c525219020c3a1215a29453c20f4ced90575d9a7d13f8fe666d05b4) + +Now I have 0.05 RBTC! + +## Recheck balance + +To check balance again, run this command in the Hardhat console: + +```javascript +const address = '0xe16f6abdd5815f3d24b4e5c29138f863933b000a'; +const balance = await ethers.provider.getBalance(address); +console.log(ethers.formatEther(balance)); +``` + +![getBalance accounts 0 again](/assets/img/tutorials/setup-truffle-oz/image-41.png) + +Great! Now I have 50000000000000000, which means that I have 0.05 tRBTC with 18 decimal places of precision. + +# Where to go from here + +At this point, we have installed all requirements and created a project using Hardhat framework and Open Zeppelin smart contracts library, connected to both an RSK local node (Regtest) and the RSK Testnet. + +We have not developed anything yet, but you are now ready to move on to the next tutorials, where we will develop some very cool projects! + +Choose any of these to tutorials to begin: + +- [Create your first Token](https://developers.rsk.co/tutorials/tokens/create-a-token/) +- [Petshop](https://developers.rsk.co/tutorials/truffle-boxes/pet-shop-box/) +- [Create your own collectable token](https://developers.rsk.co/tutorials/tokens/create-a-collectable-token/) diff --git a/content/rsk-devportal/develop/tutorials/ethereum-devs/truffle-test.md b/content/rsk-devportal/develop/tutorials/ethereum-devs/truffle-test.md index af2875f71a..14f1775c09 100644 --- a/content/rsk-devportal/develop/tutorials/ethereum-devs/truffle-test.md +++ b/content/rsk-devportal/develop/tutorials/ethereum-devs/truffle-test.md @@ -1,415 +1,280 @@ ---- -menu_title: Truffle test -layout: rsk -title: Testing smart contracts using Truffle -tags: tutorial, rsk, truffle, test -description: "How to create and run tests on your RSK smart contracts using Truffle." -render_features: "custom-terminals" ---- - -> Sunsetting Truffle: Truffle has been sunsetted, see [Consensys Announcement](https://consensys.io/blog/consensys-announces-the-sunset-of-truffle-and-ganache-and-new-hardhat). Rootstock will no longer support Truffle and encourage immediate migration to [Hardhat](/tools/hardhat/). - -In this tutorial, I will show you step-by-step how to create and run tests in smart contracts using Truffle framework connected to an RSK local node. - -# Overview - -Here is a summary of the steps to be taken: - -1. Installation requirements; -2. Run a RSK local node (regtest); -3. Create the Register project; -4. Configure Truffle framework; -5. Create a smart contract; -6. Compile; -7. Testing without deploy; -8. Deploy on RSK local node; -9. Testing a deployed smart contract; - -## Translations - -This article is also available in -[Português](https://rsk.solange.dev/#/pt/truffle-tests/readme "Testando smart contracts utilizando Truffle na rede RSK"). - -# Requirements - -1. POSIX compliant shell -2. Java -3. Editor: Visual Studio Code (VSCode) ou outro editor de sua escolha -4. Truffle - -All requirements are explained in detail in the tutorial link below: - -* [Setup a project with Truffle and OpenZeppelin](/tutorials/ethereum-devs/setup-truffle-oz/) - -# RSK Local node - regtest - -When we develop a project using Truffle Framework, we need a blockchain node running locally. This is better for development, and running tests. We'll run a local node, also known as regtest. - -There are several ways to set up an RSK local node. To know how to download a JAR file and run it using the Java SDK, check out the tutorial: - -* [Setup a project with Truffle and OpenZeppelin](/tutorials/ethereum-devs/setup-truffle-oz/) - -## Run - -To run the node: - -[](#top "multiple-terminals") -- Linux, Mac OSX - ```shell - $ java -cp -Drpc.providers.web.cors=* co.rsk.Start --regtest - ``` -- Windows - ```windows-command-prompt - C:\> java -cp -Drpc.providers.web.cors=* co.rsk.Start --regtest - ``` - -Replace `` with your path to the JAR file. As an example: - -[](#top "multiple-terminals") -- Linux, Mac OSX - ```shell - $ java -cp C:/RskjCode/rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest - ``` -- Windows - ```windows-command-prompt - C:\> java -cp C:\RSK\node\rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest - ``` - -If you see no output - that is a good thing: -Its output is directed to a log file. - -**Important:** - -> Do not close this terminal/console window, -> if closed the local node will stop running. - -# Create the register project - - -1. Create a new folder named `Register`, and navigate to the folder in the terminal; -2. Initialize an empty Truffle project; -3. Initialize an npm project - -```shell -mkdir Register -cd Register -truffle init -npm init -y -``` - -If you would like more details about this step, you can see the tutorial previously mentioned: - -* [Setup a project with Truffle and OpenZeppelin](/tutorials/ethereum-devs/setup-truffle-oz/) - -Open the project in VS Code. - -```shell -code . -``` - -# Configure Truffle to connect to RSK local node - -Open `truffle-config.js` file in your Truffle project and overwrite it with the following code: - -```javascript -module.exports = { - networks: { - development: { - host: "127.0.0.1", - port: 4444, - network_id: "*" - }, - }, - compilers: { - solc: { - version: "0.5.16", - } - } -} -``` - -Check out the VS Code image: - -![truffle-config](/assets/img/tutorials/truffle-test/image-04.png) - -# Smart contract - -In your terminal, inside the project folder, run this command: - -```shell -truffle create contract Register -``` - -This command creates a 'skeleton' smart contract. See the results in the `contracts` folder: - -![truffle create contract Register](/assets/img/tutorials/truffle-test/image-05.png) - -Overwrite it with the following code: - -```javascript -pragma solidity 0.5.16; - -contract Register { - string private info; - - function setInfo(string memory _info) public { - info = _info; - } - - function getInfo() public view returns (string memory) { - return info; - } -} -``` - -Check out the VS Code image: - -![VS Code Register.sol](/assets/img/tutorials/truffle-test/image-06.png) - -## Register.sol - -This smart contract has: - -* A variable `info` to store a string -* A function `getInfo()` to return the string stored at variable info -* A function `setInfo()` to change the string stored at variable info - -# Compile the smart contract - -Run this command in the terminal: - -``` -truffle compile -``` - -```windows-command-prompt -C:\RSK\Register>truffle compile - -Compiling your contracts... -=========================== -> Compiling .\contracts\Migrations.sol -> Compiling .\contracts\Register.sol -> Artifacts written to C:\RSK\Register\build\contracts -> Compiled successfully using: - - solc: 0.5.16+commit.9c3226ce.Emscripten.clang - -C:\RSK\Register> -``` - -# Testing without deployment - -It is possible to test a smart contract which is not published in any network yet. - -In the `test` folder, create a file named `register_new.js` - -Copy and paste this source code: - -```javascript -const Register = artifacts.require('Register'); - -contract('Test new Register', (accounts) => { - it('should store an information', async () => { - const RegisterInstance = await Register.new(); - // Set information "RSK" - await RegisterInstance.setInfo("RSK", { from: accounts[0] }); - // Get information value - const storedData = await RegisterInstance.getInfo(); - assert.equal(storedData, "RSK", 'The information RSK was not stored.'); - }); -}); -``` - -Check out the VS Code image: - -![VSCode register_new](/assets/img/tutorials/truffle-test/image-08.png) - -> To do tests in a smart contract which is not published in any network, use `.new()`. It will create a new smart contract instance for run the tests. - -## Running tests - -In the terminal, run this command: - -``` -truffle test -``` - -Check out the result: - -![truffle test](/assets/img/tutorials/truffle-test/image-09.png) - -Our test passed :) - -# Deploy on RSK local node - -Firstly, we need to create a file in the Truffle structure with instructions to deploy the smart contract. - -## Create file 2_deploy_contracts.js - -The `migrations` folder has JavaScript files that help you deploy contracts to the network. -More about [running migrations](https://www.trufflesuite.com/docs/truffle/getting-started/running-migrations) - -In the `migrations` folder, create the file `2_deploy_contracts.js` - -Copy and paste this source code: - -```javascript -const Register = artifacts.require("Register"); - -module.exports = function(deployer) { - deployer.deploy(Register); -}; -``` - -Check out the VS Code image: - -![2_deploy_contracts.js](/assets/img/tutorials/truffle-test/image-10.png) - -## Migrate - -In the terminal, run this command: - -``` -truffle migrate -``` - -Since the default configuration of `truffle-config.js` is for a local node, it only takes a few seconds for the transactions of the publication of the smart contract to be included in the Blockchain. - -The migrate command will compile the smart contract again if necessary. - -```windows-command-prompt -C:\RSK\Register>truffle migrate - -Compiling your contracts... -=========================== -> Compiling .\contracts\Migrations.sol -> Compiling .\contracts\Register.sol -> Artifacts written to C:\RSK\Register\build\contracts -> Compiled successfully using: - - solc: 0.5.16+commit.9c3226ce.Emscripten.clang -``` - -First, it deploys the smart contract `Migrations.sol`, file generated by Truffle: - -```windows-command-prompt -Starting migrations... -====================== -> Network name: 'development' -> Network id: 33 -> Block gas limit: 6800000 (0x67c280) - -1_initial_migration.js -====================== - - Deploying 'Migrations' - ---------------------- - > transaction hash: 0xafb91cbad70f3c5fde615b01e4a288b63919c68a6e84c69275e0898f4f07f2bb - > Blocks: 0 Seconds: 0 - > contract address: 0x32c9e33F4D8FD5C763B6e6ee2f958A7048b20AbE - > block number: 179468 - > block timestamp: 1593741541 - > account: 0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826 - > balance: 999999999999.424664 - > gas used: 188419 (0x2e003) - > gas price: 20 gwei - > value sent: 0 ETH - > total cost: 0.00376838 ETH - - > Saving migration to chain. - > Saving artifacts - ------------------------------------- - > Total cost: 0.00376838 ETH -``` - -And then it deploys our smart contract `Register.sol`: - -```windows-command-prompt -2_deploy_contracts.js -===================== - - Deploying 'Register' - -------------------- - > transaction hash: 0xa25ba50d5831e49c4e3e2a42bc1b3a92158ca57e30a8a72e171b3a3bfa35e7e4 - > Blocks: 0 Seconds: 0 - > contract address: 0xD156852128F3625d816F2d4257c0e961B1a0a33a - > block number: 179472 - > block timestamp: 1593741545 - > account: 0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826 - > balance: 999999999999.41858098 - > gas used: 262150 (0x40006) - > gas price: 20 gwei - > value sent: 0 ETH - > total cost: 0.005243 ETH - - > Saving migration to chain. - > Saving artifacts - ------------------------------------- - > Total cost: 0.005243 ETH - -Summary -======= -> Total deployments: 2 -> Final cost: 0.00901138 ETH -``` - -# Testing a deployed smart contract - -Let's create a new test file for the published smart contract. - -In the terminal, inside the project folder, run this command: - -```shell -truffle create test Register -``` - -This command creates a `test` file, related to the smart contract `Register`, in the `test` folder. This file has a test that checks whether the published smart contract can be instantiated. - -Check out the VS Code image: - -![truffle create test Register](/assets/img/tutorials/truffle-test/image-14.png) - -Let's replace the file with the instructions to execute the same tests we did before, but now for the `deployed` smart contract: - -```javascript -const Register = artifacts.require('Register'); - -contract('Test deployed Register', (accounts) => { - it('should store an information', async () => { - const RegisterInstance = await Register.deployed(); - // Set information "RSK" - await RegisterInstance.setInfo("RSK", { from: accounts[0] }); - // Get information value - const storedData = await RegisterInstance.getInfo(); - assert.equal(storedData, "RSK", 'The information RSK was not stored.'); - }); -}); -``` - -![Test deployed Register](/assets/img/tutorials/truffle-test/image-15.png) - -## Running the test - -The `truffle test` command performs tests on all files found in the` test` directory. -Now we have 2 files with tests. -To run tests on only one file, specify the name in the `test` directory. - -We will run the tests of the `register.js` file. In the terminal, execute this command: - -``` -truffle test test/register.js -``` - -Check out the result: - -![truffle test register.js](/assets/img/tutorials/truffle-test/image-16.png) - -Our test passed again :) - -# Final considerations - -In this tutorial I showed you how to use the Truffle framework to run tests on smart contracts, connected to a RSK local node. - -Our goal is to join forces and give options to people who believe in the power of smart contracts, and also believe in the security of Bitcoin, through RSK. - -I hope this tutorial has been helpful and I’d appreciate your feedback. -Happy with this tutorial? -Share it if you like it :) +--- +menu_title: Hardhat test +layout: rsk +title: Testing smart contracts using Hardhat +tags: tutorial, rsk, hardhat, test +description: "How to create and run tests on your RSK smart contracts using Hardhat." +render_features: "custom-terminals" +--- + +In this tutorial, I will show you step-by-step how to create and run tests on smart contracts using the Hardhat framework connected to an RSK local node. + +# Overview + +Here is a summary of the steps to be taken: + +1. Installation requirements; +2. Run a RSK local node (regtest); +3. Create the Register project; +4. Configure Hardhat; +5. Create a smart contract; +6. Compile; +7. Testing without deploy; +8. Deploy on RSK local node; +9. Testing a deployed smart contract; + +# Requirements + +1. POSIX compliant shell +2. Java +3. Node.js and npm +4. Editor: Visual Studio Code (VSCode) or another editor of your choice +5. Hardhat + +All requirements are explained in detail in the tutorial link below: + +* [Setup a project with Hardhat](/tutorials/ethereum-devs/setup-hardhat/) + +# RSK Local node - regtest + +When we develop a project using Hardhat, we need a blockchain node running locally. This is better for development and for running tests. We'll run a local node, also known as regtest. + +There are several ways to set up an RSK local node. For instructions on downloading a JAR file and running it using the Java SDK, check out the tutorial: + +* [Setup a project with Hardhat](/tutorials/ethereum-devs/setup-hardhat/) + +## Run + +To run the node: + +[](#top "multiple-terminals") +- Linux, Mac OSX + ```shell + $ java -cp -Drpc.providers.web.cors=* co.rsk.Start --regtest + ``` +- Windows + ```windows-command-prompt + C:\> java -cp -Drpc.providers.web.cors=* co.rsk.Start --regtest + ``` + +Replace `` with your path to the JAR file. As an example: + +[](#top "multiple-terminals") +- Linux, Mac OSX + ```shell + $ java -cp C:/RskjCode/rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest + ``` +- Windows + ```windows-command-prompt + C:\> java -cp C:\RSK\node\rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest + ``` + +If you see no output - that is a good thing: +Its output is directed to a log file. + +**Important:** + +> Do not close this terminal/console window, +> if closed the local node will stop running. + +# Create the register project + +1. Create a new folder named `Register`, and navigate to the folder in the terminal; +2. Initialize an empty Hardhat project; +3. Initialize an npm project + +```shell +mkdir Register +cd Register +npm init -y +npm install --save-dev hardhat +npx hardhat init +``` + +If you would like more details about this step, you can see the tutorial previously mentioned: + +* [Setup a project with Hardhat and OpenZeppelin](/tutorials/ethereum-devs/setup-hardhat-oz/) + +Open the project in VS Code. + +```shell +code . +``` + +# Configure Hardhat to connect to RSK local node + +Open `hardhat.config.js` file in your Hardhat project and overwrite it with the following code: + +```javascript +require("@nomicfoundation/hardhat-toolbox"); + +module.exports = { + solidity: "0.8.24", + networks: { + hardhat: { + chainId: 33 // This is the RSK regtest chain ID + }, + rskLocal: { + url: "http://127.0.0.1:4444/", + chainId: 33 // This is the RSK regtest chain ID + } + } +}; +``` + +This configuration sets up Hardhat to connect to the RSK local node for deployment and testing purposes. It specifies the Solidity version to use for compiling your contracts and configures the `rskLocal` network with the URL of your running RSK local node and its chain ID. + +Check out the VS Code image: + +![truffle-config](/assets/img/tutorials/truffle-test/image-04.png) + +# Smart contract Register.sol + +Inside the `contracts` folder create a file named `Register.sol`. You can use the following command: + +```shell +touch Register.sol +``` +Now, open the Register.sol file in your text editor and overwrite it with the following Solidity code: + +```javascript +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +contract Register { + string private info; + + function setInfo(string memory _info) public { + info = _info; + } + + function getInfo() public view returns (string memory) { + return info; + } +} +``` + +This smart contract includes: + +- A private state variable `info` to store a string. +- A function `setInfo(string memory _info)` that allows writing a new string to the `info` variable. +- A function `getInfo()` that reads and returns the current value of the `info` variable. + +This simple contract serves as a basic example of how to write and read to a state variable in Solidity. + +![VS Code Register.sol](/assets/img/tutorials/truffle-test/image-06.png) + +# Compile the smart contract + +To compile your smart contract using Hardhat, run the following command in the terminal: + +```shell +npx hardhat compile +``` + +You should see output similar to this, indicating that your contract has been compiled successfully: + +``` +Compiling 1 file with 0.8.4 +Compilation finished successfully +``` +This process compiles the `Register.sol` contract, and the output will be stored in the `artifacts` directory of your project. Hardhat automatically handles the compilation process, looking for Solidity files in the `contracts` folder, compiling them according to the Solidity version specified in `hardhat.config.js`, and saving the compiled artifacts. + +# Testing without deployment + +To test a smart contract that hasn't been deployed to any network using Hardhat, follow these steps: + +1. In the `test` folder of your project, create a file named `register_new.js`. +2. Copy and paste the following test code into `register_new.js`: + +```javascript +const { expect } = require("chai"); +const { ethers } = require("hardhat"); + +describe("Register contract", function () { + it("Should store and retrieve information", async function () { + const Register = await ethers.getContractFactory("Register"); + const register = await Register.deploy(); + await register.waitForDeployment(); + + // Set information to "RSK" + await register.setInfo("RSK"); + // Get stored information + const storedInfo = await register.getInfo(); + + expect(storedInfo).to.equal("RSK"); + }); +}); +``` + +This test script does the following: + +- It uses Hardhat's `ethers` library to interact with Ethereum and its testing environment. +- The `describe` block groups together the "Register contract" tests. +- Inside the `describe` block, the `it` function defines a single test, "Should store and retrieve information". +- The test deploys a new instance of the `Register` contract, then calls the `setInfo` function to store the string "RSK". +- It retrieves the stored information using `getInfo` and asserts that the stored information is equal to "RSK". + +To run the tests, use the following command in the terminal: + +```shell +npx hardhat test register_new.js +``` + +After running this command, you should see output indicating that the test has passed, demonstrating that the smart contract's `setInfo` and `getInfo` functions are working as expected, without having deployed the contract to any blockchain network. + +# Deploy on RSK local node + +To deploy your smart contract to the RSK local node using Hardhat, follow these steps: + +## Create the deployment script + +1. In the `ignition/modules` folder of your Hardhat project, create a file named `Register.js`. +2. Copy and paste the following deployment script into `Register.js`: + +```javascript +const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules"); + +module.exports = buildModule("RegisterModule", (m) => { + const register = m.contract("Register"); + + return { register }; +}); +``` + +## Deploy the contract + +To deploy the contract to the RSK local node, run the deploy ignition module using: + +```shell +npx hardhat ignition deploy ignition/modules/Register.js --network rskLocal +``` + +This command specifies that you want to run the `Register.js` script on the `rskLocal` network, which you should have defined in your `hardhat.config.js` file. + +After running the command, you will see output similar to the following, indicating that your contract has been deployed: + +``` +Hardhat Ignition 🚀 + +Deploying [ RegisterModule ] + +Batch #1 + Executed RegisterModule#Register + +[ RegisterModule ] successfully deployed 🚀 + +Deployed Addresses + +RegisterModule#Register - [Register Contract Address] +``` + +This output confirms that the `Register` contract has been successfully deployed to your local RSK node. + +# Final considerations + +This tutorial guided you through using Hardhat to deploy and test smart contracts on an RSK local node. You can take advantage of Hardhat's built-in functionalities and plugins to enhance your smart contract development workflow. + +RSK combines the benefits of smart contract functionality with the security and capabilities of the Bitcoin network. Exploring these possibilities can lead to innovative decentralized applications. + +We hope this tutorial was useful and encourage you to share your feedback and results. If you found this guide helpful, feel free to share it with your community! diff --git a/content/rsk-devportal/tutorials/ethereum-devs/truffle-test.md b/content/rsk-devportal/tutorials/ethereum-devs/truffle-test.md index 3bbc4183f5..937f819e02 100644 --- a/content/rsk-devportal/tutorials/ethereum-devs/truffle-test.md +++ b/content/rsk-devportal/tutorials/ethereum-devs/truffle-test.md @@ -1,412 +1,338 @@ ---- -layout: rsk -title: Testing smart contracts using Truffle -tags: tutorial, rsk, truffle, test -description: "How to create and run tests on your RSK smart contracts using Truffle." -render_features: "custom-terminals" ---- - -In this tutorial, I will show you step-by-step how to create and run tests in smart contracts using Truffle framework connected to an RSK local node. - -# Overview - -Here is a summary of the steps to be taken: - -1. Installation requirements; -2. Run a RSK local node (regtest); -3. Create the Register project; -4. Configure Truffle framework; -5. Create a smart contract; -6. Compile; -7. Testing without deploy; -8. Deploy on RSK local node; -9. Testing a deployed smart contract; - -## Translations - -This article is also available in -[Português](https://rsk.solange.dev/#/pt/truffle-tests/readme "Testando smart contracts utilizando Truffle na rede RSK"). - -# Requirements - -1. POSIX compliant shell -2. Java -3. Editor: Visual Studio Code (VSCode) ou outro editor de sua escolha -4. Truffle - -All requirements are explained in detail in the tutorial link below: - -* [Setup a project with Truffle and OpenZeppelin](/tutorials/ethereum-devs/setup-truffle-oz/) - -# RSK Local node - regtest - -When we develop a project using Truffle Framework, we need a blockchain node running locally. This is better for development, and running tests. We'll run a local node, also known as regtest. - -There are several ways to set up an RSK local node. To know how to download a JAR file and run it using the Java SDK, check out the tutorial: - -* [Setup a project with Truffle and OpenZeppelin](/tutorials/ethereum-devs/setup-truffle-oz/) - -## Run - -To run the node: - -[](#top "multiple-terminals") -- Linux, Mac OSX - ```shell - $ java -cp -Drpc.providers.web.cors=* co.rsk.Start --regtest - ``` -- Windows - ```windows-command-prompt - C:\> java -cp -Drpc.providers.web.cors=* co.rsk.Start --regtest - ``` - -Replace `` with your path to the JAR file. As an example: - -[](#top "multiple-terminals") -- Linux, Mac OSX - ```shell - $ java -cp C:/RskjCode/rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest - ``` -- Windows - ```windows-command-prompt - C:\> java -cp C:\RSK\node\rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest - ``` - -If you see no output - that is a good thing: -Its output is directed to a log file. - -**Important:** - -> Do not close this terminal/console window, -> if closed the local node will stop running. - -# Create the register project - - -1. Create a new folder named `Register`, and navigate to the folder in the terminal; -2. Initialize an empty Truffle project; -3. Initialize an npm project - -```shell -mkdir Register -cd Register -truffle init -npm init -y -``` - -If you would like more details about this step, you can see the tutorial previously mentioned: - -* [Setup a project with Truffle and OpenZeppelin](/tutorials/ethereum-devs/setup-truffle-oz/) - -Open the project in VS Code. - -```shell -code . -``` - -# Configure Truffle to connect to RSK local node - -Open `truffle-config.js` file in your Truffle project and overwrite it with the following code: - -```javascript -module.exports = { - networks: { - development: { - host: "127.0.0.1", - port: 4444, - network_id: "*" - }, - }, - compilers: { - solc: { - version: "0.5.16", - } - } -} -``` - -Check out the VS Code image: - -![truffle-config](/assets/img/tutorials/truffle-test/image-04.png) - -# Smart contract - -In your terminal, inside the project folder, run this command: - -```shell -truffle create contract Register -``` - -This command creates a 'skeleton' smart contract. See the results in the `contracts` folder: - -![truffle create contract Register](/assets/img/tutorials/truffle-test/image-05.png) - -Overwrite it with the following code: - -```javascript -pragma solidity 0.5.16; - -contract Register { - string private info; - - function setInfo(string memory _info) public { - info = _info; - } - - function getInfo() public view returns (string memory) { - return info; - } -} -``` - -Check out the VS Code image: - -![VS Code Register.sol](/assets/img/tutorials/truffle-test/image-06.png) - -## Register.sol - -This smart contract has: - -* A variable `info` to store a string -* A function `getInfo()` to return the string stored at variable info -* A function `setInfo()` to change the string stored at variable info - -# Compile the smart contract - -Run this command in the terminal: - -``` -truffle compile -``` - -```windows-command-prompt -C:\RSK\Register>truffle compile - -Compiling your contracts... -=========================== -> Compiling .\contracts\Migrations.sol -> Compiling .\contracts\Register.sol -> Artifacts written to C:\RSK\Register\build\contracts -> Compiled successfully using: - - solc: 0.5.16+commit.9c3226ce.Emscripten.clang - -C:\RSK\Register> -``` - -# Testing without deployment - -It is possible to test a smart contract which is not published in any network yet. - -In the `test` folder, create a file named `register_new.js` - -Copy and paste this source code: - -```javascript -const Register = artifacts.require('Register'); - -contract('Test new Register', (accounts) => { - it('should store an information', async () => { - const RegisterInstance = await Register.new(); - // Set information "RSK" - await RegisterInstance.setInfo("RSK", { from: accounts[0] }); - // Get information value - const storedData = await RegisterInstance.getInfo(); - assert.equal(storedData, "RSK", 'The information RSK was not stored.'); - }); -}); -``` - -Check out the VS Code image: - -![VSCode register_new](/assets/img/tutorials/truffle-test/image-08.png) - -> To do tests in a smart contract which is not published in any network, use `.new()`. It will create a new smart contract instance for run the tests. - -## Running tests - -In the terminal, run this command: - -``` -truffle test -``` - -Check out the result: - -![truffle test](/assets/img/tutorials/truffle-test/image-09.png) - -Our test passed :) - -# Deploy on RSK local node - -Firstly, we need to create a file in the Truffle structure with instructions to deploy the smart contract. - -## Create file 2_deploy_contracts.js - -The `migrations` folder has JavaScript files that help you deploy contracts to the network. -More about [running migrations](https://www.trufflesuite.com/docs/truffle/getting-started/running-migrations) - -In the `migrations` folder, create the file `2_deploy_contracts.js` - -Copy and paste this source code: - -```javascript -const Register = artifacts.require("Register"); - -module.exports = function(deployer) { - deployer.deploy(Register); -}; -``` - -Check out the VS Code image: - -![2_deploy_contracts.js](/assets/img/tutorials/truffle-test/image-10.png) - -## Migrate - -In the terminal, run this command: - -``` -truffle migrate -``` - -Since the default configuration of `truffle-config.js` is for a local node, it only takes a few seconds for the transactions of the publication of the smart contract to be included in the Blockchain. - -The migrate command will compile the smart contract again if necessary. - -```windows-command-prompt -C:\RSK\Register>truffle migrate - -Compiling your contracts... -=========================== -> Compiling .\contracts\Migrations.sol -> Compiling .\contracts\Register.sol -> Artifacts written to C:\RSK\Register\build\contracts -> Compiled successfully using: - - solc: 0.5.16+commit.9c3226ce.Emscripten.clang -``` - -First, it deploys the smart contract `Migrations.sol`, file generated by Truffle: - -```windows-command-prompt -Starting migrations... -====================== -> Network name: 'development' -> Network id: 33 -> Block gas limit: 6800000 (0x67c280) - -1_initial_migration.js -====================== - - Deploying 'Migrations' - ---------------------- - > transaction hash: 0xafb91cbad70f3c5fde615b01e4a288b63919c68a6e84c69275e0898f4f07f2bb - > Blocks: 0 Seconds: 0 - > contract address: 0x32c9e33F4D8FD5C763B6e6ee2f958A7048b20AbE - > block number: 179468 - > block timestamp: 1593741541 - > account: 0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826 - > balance: 999999999999.424664 - > gas used: 188419 (0x2e003) - > gas price: 20 gwei - > value sent: 0 ETH - > total cost: 0.00376838 ETH - - > Saving migration to chain. - > Saving artifacts - ------------------------------------- - > Total cost: 0.00376838 ETH -``` - -And then it deploys our smart contract `Register.sol`: - -```windows-command-prompt -2_deploy_contracts.js -===================== - - Deploying 'Register' - -------------------- - > transaction hash: 0xa25ba50d5831e49c4e3e2a42bc1b3a92158ca57e30a8a72e171b3a3bfa35e7e4 - > Blocks: 0 Seconds: 0 - > contract address: 0xD156852128F3625d816F2d4257c0e961B1a0a33a - > block number: 179472 - > block timestamp: 1593741545 - > account: 0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826 - > balance: 999999999999.41858098 - > gas used: 262150 (0x40006) - > gas price: 20 gwei - > value sent: 0 ETH - > total cost: 0.005243 ETH - - > Saving migration to chain. - > Saving artifacts - ------------------------------------- - > Total cost: 0.005243 ETH - -Summary -======= -> Total deployments: 2 -> Final cost: 0.00901138 ETH -``` - -# Testing a deployed smart contract - -Let's create a new test file for the published smart contract. - -In the terminal, inside the project folder, run this command: - -```shell -truffle create test Register -``` - -This command creates a `test` file, related to the smart contract `Register`, in the `test` folder. This file has a test that checks whether the published smart contract can be instantiated. - -Check out the VS Code image: - -![truffle create test Register](/assets/img/tutorials/truffle-test/image-14.png) - -Let's replace the file with the instructions to execute the same tests we did before, but now for the `deployed` smart contract: - -```javascript -const Register = artifacts.require('Register'); - -contract('Test deployed Register', (accounts) => { - it('should store an information', async () => { - const RegisterInstance = await Register.deployed(); - // Set information "RSK" - await RegisterInstance.setInfo("RSK", { from: accounts[0] }); - // Get information value - const storedData = await RegisterInstance.getInfo(); - assert.equal(storedData, "RSK", 'The information RSK was not stored.'); - }); -}); -``` - -![Test deployed Register](/assets/img/tutorials/truffle-test/image-15.png) - -## Running the test - -The `truffle test` command performs tests on all files found in the` test` directory. -Now we have 2 files with tests. -To run tests on only one file, specify the name in the `test` directory. - -We will run the tests of the `register.js` file. In the terminal, execute this command: - -``` -truffle test test/register.js -``` - -Check out the result: - -![truffle test register.js](/assets/img/tutorials/truffle-test/image-16.png) - -Our test passed again :) - -# Final considerations - -In this tutorial I showed you how to use the Truffle framework to run tests on smart contracts, connected to a RSK local node. - -Our goal is to join forces and give options to people who believe in the power of smart contracts, and also believe in the security of Bitcoin, through RSK. - -I hope this tutorial has been helpful and I’d appreciate your feedback. -Happy with this tutorial? -Share it if you like it :) +--- +menu_title: Hardhat test +layout: rsk +title: Testing smart contracts using Hardhat +tags: tutorial, rsk, hardhat, test +description: "How to create and run tests on your RSK smart contracts using Hardhat." +render_features: "custom-terminals" +--- + +In this tutorial, I will show you step-by-step how to create and run tests on smart contracts using the Hardhat framework connected to an RSK local node. + +# Overview + +Here is a summary of the steps to be taken: + +1. Installation requirements; +2. Run a RSK local node (regtest); +3. Create the Register project; +4. Configure Hardhat; +5. Create a smart contract; +6. Compile; +7. Testing without deploy; +8. Deploy on RSK local node; +9. Testing a deployed smart contract; + +# Requirements + +1. POSIX compliant shell +2. Java +3. Node.js and npm +4. Editor: Visual Studio Code (VSCode) or another editor of your choice +5. Hardhat + +All requirements are explained in detail in the tutorial link below: + +* [Setup a project with Hardhat](/tutorials/ethereum-devs/setup-hardhat/) + +# RSK Local node - regtest + +When we develop a project using Hardhat, we need a blockchain node running locally. This is better for development and for running tests. We'll run a local node, also known as regtest. + +There are several ways to set up an RSK local node. For instructions on downloading a JAR file and running it using the Java SDK, check out the tutorial: + +* [Setup a project with Hardhat](/tutorials/ethereum-devs/setup-hardhat/) + +## Run + +To run the node: + +[](#top "multiple-terminals") +- Linux, Mac OSX + ```shell + $ java -cp -Drpc.providers.web.cors=* co.rsk.Start --regtest + ``` +- Windows + ```windows-command-prompt + C:\> java -cp -Drpc.providers.web.cors=* co.rsk.Start --regtest + ``` + +Replace `` with your path to the JAR file. As an example: + +[](#top "multiple-terminals") +- Linux, Mac OSX + ```shell + $ java -cp C:/RskjCode/rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest + ``` +- Windows + ```windows-command-prompt + C:\> java -cp C:\RSK\node\rskj-core-3.1.0-IRIS-all.jar -Drpc.providers.web.cors=* co.rsk.Start --regtest + ``` + +If you see no output - that is a good thing: +Its output is directed to a log file. + +**Important:** + +> Do not close this terminal/console window, +> if closed the local node will stop running. + +# Create the register project + +1. Create a new folder named `Register`, and navigate to the folder in the terminal; +2. Initialize an empty Hardhat project; +3. Initialize an npm project + +```shell +mkdir Register +cd Register +npx hardhat init +npm init -y +``` + +If you would like more details about this step, you can see the tutorial previously mentioned: + +* [Setup a project with Hardhat and OpenZeppelin](/tutorials/ethereum-devs/setup-hardhat-oz/) + +Open the project in VS Code. + +```shell +code . +``` + +# Configure Hardhat to connect to RSK local node + +Open `hardhat.config.js` file in your Hardhat project and overwrite it with the following code: + +```javascript +require("@nomiclabs/hardhat-waffle"); + +module.exports = { + solidity: "0.8.4", + networks: { + hardhat: { + chainId: 33 // This is the RSK regtest chain ID + }, + rskLocal: { + url: "http://127.0.0.1:4444/", + chainId: 33 // This is the RSK regtest chain ID + } + } +}; +``` + +This configuration sets up Hardhat to connect to the RSK local node for deployment and testing purposes. It specifies the Solidity version to use for compiling your contracts and configures the `rskLocal` network with the URL of your running RSK local node and its chain ID. + +Check out the VS Code image: + +![truffle-config](/assets/img/tutorials/truffle-test/image-04.png) + +# Smart contract Register.sol + +In your terminal, inside the project folder, create a new file under the `contracts` directory named `Register.sol`. You can use the following command or create the file directly from your text editor: + +```shell +touch contracts/Register.sol +``` +Now, open the Register.sol file in your text editor and overwrite it with the following Solidity code: + +```javascript +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +contract Register { + string private info; + + function setInfo(string memory _info) public { + info = _info; + } + + function getInfo() public view returns (string memory) { + return info; + } +} +``` + +This smart contract includes: + +- A private state variable `info` to store a string. +- A function `setInfo(string memory _info)` that allows writing a new string to the `info` variable. +- A function `getInfo()` that reads and returns the current value of the `info` variable. + +This simple contract serves as a basic example of how to write and read to a state variable in Solidity. + +![VS Code Register.sol](/assets/img/tutorials/truffle-test/image-06.png) + +# Compile the smart contract + +To compile your smart contract using Hardhat, run the following command in the terminal: + +```shell +npx hardhat compile +``` + +You should see output similar to this, indicating that your contract has been compiled successfully: + +``` +Compiling 1 file with 0.8.4 +Compilation finished successfully +``` +This process compiles the `Register.sol` contract, and the output will be stored in the `artifacts` directory of your project. Hardhat automatically handles the compilation process, looking for Solidity files in the `contracts` folder, compiling them according to the Solidity version specified in `hardhat.config.js`, and saving the compiled artifacts. + +# Testing without deployment + +To test a smart contract that hasn't been deployed to any network using Hardhat, follow these steps: + +1. In the `test` folder of your project, create a file named `register_new.js`. +2. Copy and paste the following test code into `register_new.js`: + +```javascript +const { expect } = require("chai"); +const { ethers } = require("hardhat"); + +describe("Register contract", function () { + it("Should store and retrieve information", async function () { + const Register = await ethers.getContractFactory("Register"); + const register = await Register.deploy(); + await register.deployed(); + + // Set information to "RSK" + await register.setInfo("RSK"); + // Get stored information + const storedInfo = await register.getInfo(); + + expect(storedInfo).to.equal("RSK"); + }); +}); +``` + +This test script does the following: + +- It uses Hardhat's `ethers` library to interact with Ethereum and its testing environment. +- The `describe` block groups together the "Register contract" tests. +- Inside the `describe` block, the `it` function defines a single test, "Should store and retrieve information". +- The test deploys a new instance of the `Register` contract, then calls the `setInfo` function to store the string "RSK". +- It retrieves the stored information using `getInfo` and asserts that the stored information is equal to "RSK". + +1. To run the tests, use the following command in the terminal: + +```shell +npx hardhat test +``` + +After running this command, you should see output indicating that the test has passed, demonstrating that the smart contract's `setInfo` and `getInfo` functions are working as expected, without having deployed the contract to any blockchain network. + +# Deploy on RSK local node + +To deploy your smart contract to the RSK local node using Hardhat, follow these steps: + +## Create the deployment script + +1. In the `scripts` folder of your Hardhat project, create a file named `deploy.js`. +2. Copy and paste the following deployment script into `deploy.js`: + +```javascript +async function main() { + const [deployer] = await ethers.getSigners(); + + console.log("Deploying contracts with the account:", deployer.address); + + const Register = await ethers.getContractFactory("Register"); + const register = await Register.deploy(); + + console.log("Register contract deployed to:", register.address); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); +``` + +This script does the following: + +- Retrieves the deployer's address from the Hardhat's runtime environment. +- Uses the `ethers` library, which is automatically available in the Hardhat environment, to get the `Register` contract factory. +- Deploys the `Register` contract and logs its address to the console. + +## Deploy the contract + +1. To deploy the contract to the RSK local node, run the deploy script using Hardhat: + +```shell +npx hardhat run scripts/deploy.js --network rskLocal +``` + +This command specifies that you want to run the `deploy.js` script on the `rskLocal` network, which you should have defined in your `hardhat.config.js` file. + +After running the command, you will see output similar to the following, indicating that your contract has been deployed: + +``` +Deploying contracts with the account: [Deployer's Address] +Register contract deployed to: [Register Contract Address] +``` + +This output confirms that the `Register` contract has been successfully deployed to your local RSK node. + +# Testing a deployed smart contract + +To test a deployed smart contract using Hardhat, follow these steps: + +1. Inside your Hardhat project, ensure you have a test file for the `Register` contract. If not, create a new `test` file in the test folder. You can name it `register_deployed.js` for clarity. + +2. Copy and paste the following test code into register_deployed.js: + + +```javascript +const { expect } = require("chai"); +const { ethers } = require("hardhat"); + +describe("Register contract", function () { + let register; + let deployer; + + before(async function () { + // Deploy the contract before running tests + const Register = await ethers.getContractFactory("Register"); + register = await Register.deploy(); + await register.deployed(); + + [deployer] = await ethers.getSigners(); + }); + + it("Should store and retrieve information", async function () { + // Set information to "RSK" + await register.setInfo("RSK"); + // Get stored information + const storedInfo = await register.getInfo(); + + expect(storedInfo).to.equal("RSK"); + }); +}); +``` + +This test script does the following: + +- In the `before` hook, it deploys a new instance of the `Register` contract before the tests are run. + +- The `it` function defines a single test, "Should store and retrieve information", which interacts with the deployed contract to test its functionality. + +To run this specific test file, use the following command in the terminal: + +```shell +npx hardhat test test/register_deployed.js +``` + +This command tells Hardhat to execute only the tests contained in the `register_deployed.js` file. + +After running this command, you should see output indicating that the test has passed, which confirms that the deployed `Register` contract's `setInfo` and `getInfo` functions are working as expected. + +# Final considerations + +This tutorial guided you through using Hardhat to deploy and test smart contracts on an RSK local node. You can take advantage of Hardhat's built-in functionalities and plugins to enhance your smart contract development workflow. + +RSK combines the benefits of smart contract functionality with the security and capabilities of the Bitcoin network. Exploring these possibilities can lead to innovative decentralized applications. + +We hope this tutorial was useful and encourage you to share your feedback and results. If you found this guide helpful, feel free to share it with your community!