Ethereum development is a vast field, often dominated by JavaScript and Python tools. However, for Ruby developers, a powerful and maintained library exists to bring the same capabilities to your favorite language: the eth.rb gem. This guide provides a comprehensive walkthrough on using eth.rb to deploy and interact with a smart contract on the Ethereum Goerli testnet.
Whether you prefer a step-by-step console approach or quick script execution, this tutorial covers both methods. By the end, you'll understand how to manage accounts, deploy contracts, send transactions, and read state—all using Ruby.
Prerequisites
Before diving into the code, ensure you have the following set up and ready:
- An Ethereum Goerli Node: You can obtain one by signing up with a node provider like Chainstack and deploying a node on the Goerli testnet. Note that Goerli is being phased out; consider using Sepolia or Holesky for new projects.
- Ruby Installed: Make sure you have a recent version of Ruby installed on your system. Check the official Ruby documentation for installation instructions.
- A Funded Ethereum Account: You'll need an account with a private key and some testnet ETH. Use a Goerli faucet to obtain testnet ether if needed.
- Solidity Compiler: Install the Solidity compiler (
solc) to compile smart contract code locally.
Preparing Your Smart Contract
For this tutorial, we'll use a basic SimpleStorage contract. This contract stores a single unsigned integer and provides functions to update and retrieve its value.
Create a file named simplestorage.sol with the following content:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;
contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint retVal) {
return storedData;
}
}This contract is straightforward and perfect for learning the deployment process.
Console-Based Deployment Walkthrough
Follow these steps to deploy and interact with your contract using the Ruby interactive console.
Step 1: Clone the eth.rb Repository
Start by cloning the official eth.rb GitHub repository to your local machine:
git clone https://github.com/q9f/eth.rbStep 2: Launch the Ruby Console
Navigate into the cloned directory and start the interactive console:
cd eth.rb
ruby bin/consoleStep 3: Configure the Ethereum Client
Inside the console, create a client instance by providing your node's HTTPS endpoint:
client = Eth::Client.create 'YOUR_CHAINSTACK_NODE_URL'Replace YOUR_CHAINSTACK_NODE_URL with your actual node endpoint.
Step 4: Load Your Account
Import your Ethereum account using its private key:
deployer_account = Eth::Key.new priv: 'YOUR_PRIVATE_KEY'Important: Never hardcode private keys in production scripts. Use environment variables for security.
Step 5: Set Gas Parameters
Configure the gas limit and fees for your transactions. These values are in Wei:
client.gas_limit = 200000
client.max_fee_per_gas = 41000000000
client.max_priority_fee_per_gas = 40000000000Step 6: Load and Deploy the Contract
Import the contract from your Solidity file:
contract = Eth::Contract.from_file(file: 'contracts/simplestorage.sol')Deploy the contract to the network:
deployment_receipt = client.deploy_and_wait(contract, sender_key: deployer_account, gas_limit: 200000)The deploy_and_wait method returns a transaction receipt once the deployment is confirmed.
Step 7: Interact with the Deployed Contract
First, define the contract's ABI and address:
simplestorage_abi = '[{"inputs":[],"name":"get","outputs":[{"internalType":"uint256","name":"retVal","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"}]'
simplestorage_address = "YOUR_DEPLOYED_CONTRACT_ADDRESS"Create a contract instance:
simplestorage_contract = Eth::Contract.from_abi(name: "SimpleStorage", address: simplestorage_address, abi: simplestorage_abi)Call the set function to store a value:
client.transact_and_wait(simplestorage_contract, "set", 1234, sender_key: deployer_account)Read the stored value using the get function:
stored_value = client.call(simplestorage_contract, "get")
puts stored_valueThis should return 1234.
Script-Based Deployment Walkthrough
For a more automated approach, you can use Ruby scripts to perform the same actions.
Step 1: Install the eth.rb Gem
Install the gem globally:
gem install ethStep 2: Create a Deployment Script
Create a file named deploy.rb:
require 'eth'
client = Eth::Client.create 'YOUR_CHAINSTACK_NODE_URL'
deployer_account = Eth::Key.new priv: 'YOUR_PRIVATE_KEY'
client.max_fee_per_gas = 41000000000
client.max_priority_fee_per_gas = 40000000000
contract = Eth::Contract.from_file(file: 'simplestorage.sol')
response = client.deploy_and_wait(contract, sender_key: deployer_account, gas_limit: 200000)
puts "Contract deployed at: #{response.contract_address}"Run the script:
ruby deploy.rbStep 3: Create a Transaction Script
Create transact.rb to call the set function:
require 'eth'
client = Eth::Client.create 'YOUR_CHAINSTACK_NODE_URL'
deployer_account = Eth::Key.new priv: 'YOUR_PRIVATE_KEY'
abi = '[{"inputs":[],"name":"get","outputs":[{"internalType":"uint256","name":"retVal","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"}]'
contract_address = "YOUR_CONTRACT_ADDRESS"
contract = Eth::Contract.from_abi(name: "SimpleStorage", address: contract_address, abi: abi)
client.transact_and_wait(contract, "set", 12345, sender_key: deployer_account)
puts "Value set to 12345"Run it with:
ruby transact.rbStep 4: Create a Call Script
Finally, create call.rb to read the stored value:
require 'eth'
client = Eth::Client.create 'YOUR_CHAINSTACK_NODE_URL'
abi = '[{"inputs":[],"name":"get","outputs":[{"internalType":"uint256","name":"retVal","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"}]'
contract_address = "YOUR_CONTRACT_ADDRESS"
contract = Eth::Contract.from_abi(name: "SimpleStorage", address: contract_address, abi: abi)
value = client.call(contract, "get")
puts "Stored value is: #{value}"Execute it:
ruby call.rb👉 Explore more deployment strategies
Frequently Asked Questions
What is the eth.rb gem?
The eth.rb gem is a maintained Ruby library for interacting with the Ethereum blockchain. It allows developers to create keys, sign transactions, deploy contracts, and call functions directly from Ruby code.
Why use Ruby for Ethereum development?
Ruby offers a clean, readable syntax and a robust ecosystem. For teams already proficient in Ruby, using eth.rb can streamline blockchain development without needing to switch languages.
How do I secure my private keys when using scripts?
Always use environment variables or secure secret management systems to handle private keys. Avoid hardcoding them in your source files to prevent accidental exposure.
What is the difference between transact_and_wait and call?transact_and_wait sends a transaction that modifies the blockchain state (e.g., calling set) and waits for confirmation. call is used for read-only operations that do not require gas or change state.
Can I use eth.rb with mainnet?
Yes, but exercise extreme caution. Use testnets for development and testing. When deploying to mainnet, ensure all code is audited and use small amounts of funds initially.
What are common issues when deploying contracts?
Insufficient gas, incorrect node endpoints, or Solidity compilation errors are common pitfalls. Double-check your gas settings and node connectivity.
Conclusion
You've successfully deployed and interacted with an Ethereum smart contract using the eth.rb Ruby gem. This demonstrates that Ethereum development isn't limited to JavaScript or Python—Ruby developers can fully participate in the ecosystem.
The console method offers a great way to learn and experiment, while scripts provide efficiency for repeated tasks. As you explore further, consider integrating these techniques into larger Ruby applications, such as web services or automation tools.
Remember to always prioritize security, especially when handling private keys and deploying to live networks. Happy coding!