This tutorial teaches you the basics of Optimism development.
Optimism is EVM equivalent, meaning we run a slightly modified version of the same geth
you run on mainnet.
Therefore, we the differences between Optimism development and Ethereum development are minor.
But a few differences do exist.
To access any Ethereum type network you need an endpoint. We recommend you get one from Alchemy, our preferred provider. See here for step by step directions on using Alchemy.
Alternatively, we have other great providers that support our networks.
For development purposes we recommend you use either a local development node or Optimism Goerli. That way you don't need to spend real money. If you need ETH on Optimism Goerli for testing purposes, you can use this faucet.
The tests examples below all use Optimism Goerli.
We have Hardhat's Greeter contract on Optimism Goerli, at address 0x106941459A8768f5A92b770e280555FAF817576f. You can verify your development stack configuration by interacting with it.
As you can see in the different development stacks below, the way you deploy contracts and interact with them on Optimism is almost identical to the way you do it with L1 Ethereum. The most visible difference is that you have to specify a different endpoint (of course). The list of other differences is here.
In Hardhat you use a configuration similar to this one.
Follow these steps to add Optimism Goerli support to an existing Hardhat project.
-
Define your network configuration in
.env
:# Put the mnemonic for an account on Optimism here MNEMONIC=test test test test test test test test test test test junk # API KEY for Alchemy ALCHEMY_API_KEY= # URL to access Optimism Goerli (if not using Alchemy) OPTIMISM_GOERLI_URL=
-
Add
dotenv
to your project:yarn add dotenv
-
Edit
hardhat.config.js
:-
Use
.env
for your blockchain configuration:require('dotenv').config()
-
Get the correct URL from the configuration:
const optimismGoerliUrl = process.env.ALCHEMY_API_KEY ? `https://opt-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}` : process.env.OPTIMISM_GOERLI_URL
-
Add a network definition in
module.exports.networks
:
"optimism-goerli": { url: optimismGoerliUrl, accounts: { mnemonic: process.env.MNEMONIC } }
-
-
Run the console:
cd hardhat yarn yarn hardhat console --network optimism-goerli
-
Connect to the Greeter contract:
Greeter = await ethers.getContractFactory("Greeter") greeter = await Greeter.attach("0x106941459A8768f5A92b770e280555FAF817576f")
-
Read information from the contract:
await greeter.greet()
-
Submit a transaction, wait for it to be processed, and see that it affected the state.
tx = await greeter.setGreeting(`Hardhat: Hello ${new Date()}`) rcpt = await tx.wait() await greeter.greet()
To deploy a contract from the Hardhat console:
Greeter = await ethers.getContractFactory("Greeter")
greeter = await Greeter.deploy("Greeter from hardhat")
console.log(`Contract address: ${greeter.address}`)
await greeter.greet()
In Truffle you use a configuration similar to this one.
Follow these steps to add Optimism Goerli support to an existing Truffle project.
-
Define your network configuration in
.env
:# Put the mnemonic for an account on Optimism here MNEMONIC=test test test test test test test test test test test junk # API KEY for Alchemy ALCHEMY_API_KEY= # URL to access Optimism Goerli (if not using Alchemy) OPTIMISM_GOERLI_URL=
-
Add
dotenv
and@truffle/hdwallet-provider
to your project:yarn add dotenv @truffle/hdwallet-provider
-
Edit
truffle-config.js
:-
Uncomment this line:
const HDWalletProvider = require('@truffle/hdwallet-provider')
-
Use
.env
for your network configuration:require('dotenv').config()
-
Get the correct URL:
const optimismGoerliUrl = process.env.ALCHEMY_API_KEY ? `https://opt-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}` : process.env.OPTIMISM_GOERLI_URL
-
Add a network definition in
module.exports.networks
:"optimism-goerli": { provider: () => new HDWalletProvider( process.env.MNEMONIC, optimismGoerliUrl), network_id: 420 }
-
-
Compile the contract and run the console:
truffle compile truffle console --network optimism-goerli
-
Connect to the Greeter contact:
greeter = await Greeter.at("0x106941459A8768f5A92b770e280555FAF817576f")
-
Read information from the contact:
await greeter.greet()
-
Submit a transaction, wait for it to be processed, and see that it affected the state.
tx = await greeter.setGreeting(`Truffle: Hello ${new Date()}`) await greeter.greet()
You deploy a new contract from the console:
greeter = await Greeter.new("Greeter from Truffle")
console.log(`Contract address: ${greeter.address}`)
await greeter.greet()
In Remix you access Optimism through your own wallet.
-
Add Optimism Goerli to your wallet. If you use Metamask, follow the directions here (starting at step 4), with these parameters:
Parameter Value Network Name Optimism Goerli New RPC URL Either a third party provider or https://goerli.optimism.io Chain ID 420 Currency Symbol GOR Block Explorer URL https://blockscout.com/optimism/goerli -
Log on with your wallet to Optimism Goerli.
-
Browse to Remix.
-
Select the Environment Injected Web3 Provider.
-
Accept the connection in the wallet.
-
Make sure your environment is Injected Web3 and the network ID is 420.
-
Download Greeter.sol and upload (
) it to Remix under contracts.
-
Right-click contracts > Greeter.sol and select Compile.
-
Open contracts > artifacts and see that there's a
Greeter.json
file. This file is the compiled version, the API for the contract, etc. -
If you do not have Goerli ETH, get some using Paradigm's faucet and transfer it to Optimism by sending it to address 0x636Af16bf2f682dD3109e60102b8E1A089FedAa8.
-
Scroll down. In the At Address field, type the contract address (
0x106941459A8768f5A92b770e280555FAF817576f
). Then, click At Address. Expand the contract to see you can interact with it. -
Click greet and expand the transaction result in the console (bottom right).
-
Type a greeting and then click setGreeting. Approve the transaction in your wallet. Note that if the greeting includes a comma you need to enclose it in quotes.
-
See the results on the console and then click greet again to see the greeting changed.
You deploy a new contract:
Foundry does not give us a JavaScript console, everything can be done from the shell command line.
-
Set the RPC URL and the contract address.
export ETH_RPC_URL= << Your Goerli URL goes here >> export GREETER=0x106941459A8768f5A92b770e280555FAF817576f
-
Call
greet()
. Notice that the response is provided in hex.cast call $GREETER "greet()"
-
Call
greet()
again, and this time translate to ASCIIcast call $GREETER "greet()" | cast --to-ascii
-
Put your mnemonic in a file
mnem.delme
and send a transaction.cast send --mnemonic-path mnem.delme $GREETER "setGreeting(string)" '"hello"' --legacy
-
Test that the greeting has changed:
cast call $GREETER "greet()" | cast --to-ascii
Use this command:
forge create --mnemonic-path ./mnem.delme Greeter \
--constructor-args "Greeter from Foundry" --legacy
This library is provided as an npm package, which is different from what forge expects. Here is how you can import it without importing the entire Optimism monorepo:
-
Install the JavaScript tools if you don't already have them: Node.js and yarn.
-
Install the
@eth-optimism/contracts
library underlib
.cd lib yarn add @eth-optimism/contracts
-
If you are using
git
, addnode_modules
to.gitignore
. -
The remapping that
forge
deduces is not the same as what you would have with hardhat. To ensure source code compatibility, create a file (in the application's root directory) calledremappings.txt
with this content:@eth-optimism/=lib/node_modules/@eth-optimism/
You can now run forge build
with contracts that use the Optimism contract library.
To see this in action:
- Install the JavaScript libraries
cd foundry/lib
yarn
-
Test the application
cd .. forge test
Starting from Waffle v4.x.x you can use Waffle chai matchers to test your smart contracts directly on an Optimism node.
The tutorial makes these assumptions:
- You have Node.js running on your computer, as well as yarn.
- You have
make
installed on your computer (you can verify this by runningwhich make
in the terminal). - You have a Goerli Optimism address with enough funds on it. You can use these faucets to get some free test funds.
- You have general understanding of smart contracts development.
-
Insert your mnemonic in the line 15 of
...waffle/test/mock-contract.test.ts
to use your address in the test. -
In the terminal, run the following commands:
cd waffle yarn yarn build yarn test
You should see 2 tests passing.
-
Play around with the code! Check out other available matchers in the Waffle documentation.
Note that in the tutorial we've been compiling smart contracts using Waffle. If you prefer to compile your smart contracts using other tools (like Hardhat) you can install the appropriate packages and modify build
script in the package.json
file.
It is best to start development with the EVM provided by the development stack. Not only is it faster, but such EVMs often have extra features, such as the ability to log messages from Solidity or a graphical user interface.
After you are done with that development, debug your decentralized application using either a development node or the Kovan test network. This lets you debug parts that that are Optimism specific such as calls to bridges to transfer assets between layers.
Only when you have a version that works well on a test network should you deploy to the production network, where every transaction has a cost.