Skip to content

Commit

Permalink
docs: add hardhat example + ci (ethereum-optimism#641)
Browse files Browse the repository at this point in the history
* feat(hardhat-ovm): allow overriding the polling interval for the provider and its signers

The default is 50ms, which should make running the OVM tests smooth. If you want
to run tests against a remote node and do not want to overwhelm it, set the
parameter in the hardhat config's network

* chore: add changeset

* docs: add hardhat example

imported from https://github.com/ethereum-optimism/optimism-tutorial/

* ci: add deploy/deploy:ovm

* fix(contracts): wait for contracts to finish

workaround hardhat not generating build artifacts for both evm and ovm

* fix: use istanbul hard fork

* test(contracts): remove hardcoded post-state in nuisance gas test

this post state is not giving us much info, and it's hard to
update it or debug it when it does not pass for any reason

Co-authored-by: Georgios Konstantopoulos <[email protected]>
  • Loading branch information
platocrat and gakonst authored Apr 28, 2021
1 parent 6daa408 commit 122df8c
Show file tree
Hide file tree
Showing 16 changed files with 597 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-clouds-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@eth-optimism/hardhat-ovm": minor
---

allow overriding the ethers polling interval
15 changes: 15 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
steps:
# Monorepo tests
- uses: actions/checkout@v2

- name: Get yarn cache directory path
Expand Down Expand Up @@ -46,5 +47,19 @@ jobs:
env:
FORCE_COLOR: 1
ENABLE_GAS_REPORT: 1

- name: Print gas report
run: cat integration-tests/gas-report.txt

# Examples Tests
- name: Test & deploy hardhat-example on hardhat (regression)
working-directory: ./examples/hardhat
run: |
yarn deploy
yarn test
- name: Test & deploy hardhat-example on Optimism
working-directory: ./examples/hardhat
run: |
yarn deploy:ovm
yarn test:ovm
6 changes: 6 additions & 0 deletions examples/hardhat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# The Official™ Optimism Tutorial

[![Discord](https://img.shields.io/discord/667044843901681675.svg?color=768AD4&label=discord&logo=https%3A%2F%2Fdiscordapp.com%2Fassets%2F8c9701b98ad4372b58f13fd9f65f966e.svg)](https://discord.com/channels/667044843901681675)
[![Twitter Follow](https://img.shields.io/twitter/follow/optimismPBC.svg?label=optimismPBC&style=social)](https://twitter.com/optimismPBC)

### For the full README, please see the [guided repository of the `optimism-tutorial`](https://github.com/ethereum-optimism/optimism-tutorial) repository
196 changes: 196 additions & 0 deletions examples/hardhat/contracts/ERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// SPDX-License-Identifier: MIT
pragma solidity >0.6.0 <0.8.0;

/**
* @title ERC20
* @dev A super simple ERC20 implementation!
*/
contract ERC20 {

/**********
* Events *
**********/

event Transfer(
address indexed _from,
address indexed _to,
uint256 _value
);

event Approval(
address indexed _owner,
address indexed _spender,
uint256 _value
);


/*************
* Variables *
*************/

mapping (address => uint256) public balances;
mapping (address => mapping (address => uint256)) public allowances;

// Some optional extra goodies.
uint256 public totalSupply;
string public name;


/***************
* Constructor *
***************/

/**
* @param _initialSupply Initial maximum token supply.
* @param _name A name for our ERC20 (technically optional, but it's fun ok jeez).
*/
constructor(
uint256 _initialSupply,
string memory _name
)
public
{
balances[msg.sender] = _initialSupply;
totalSupply = _initialSupply;
name = _name;
}


/********************
* Public Functions *
********************/

/**
* Checks the balance of an address.
* @param _owner Address to check a balance for.
* @return Balance of the address.
*/
function balanceOf(
address _owner
)
external
view
returns (
uint256
)
{
return balances[_owner];
}

/**
* Transfers a balance from your account to someone else's account!
* @param _to Address to transfer a balance to.
* @param _amount Amount to transfer to the other account.
* @return true if the transfer was successful.
*/
function transfer(
address _to,
uint256 _amount
)
external
returns (
bool
)
{
require(
balances[msg.sender] >= _amount,
"You don't have enough balance to make this transfer!"
);

balances[msg.sender] -= _amount;
balances[_to] += _amount;

emit Transfer(
msg.sender,
_to,
_amount
);

return true;
}

/**
* Transfers a balance from someone else's account to another account. You need an allowance
* from the sending account for this to work!
* @param _from Account to transfer a balance from.
* @param _to Account to transfer a balance to.
* @param _amount Amount to transfer to the other account.
* @return true if the transfer was successful.
*/
function transferFrom(
address _from,
address _to,
uint256 _amount
)
external
returns (
bool
)
{
require(
balances[_from] >= _amount,
"Can't transfer from the desired account because it doesn't have enough balance."
);

require(
allowances[_from][msg.sender] >= _amount,
"Can't transfer from the desired account because you don't have enough of an allowance."
);

balances[_to] += _amount;
balances[_from] -= _amount;

emit Transfer(
_from,
_to,
_amount
);

return true;
}

/**
* Approves an account to spend some amount from your account.
* @param _spender Account to approve a balance for.
* @param _amount Amount to allow the account to spend from your account.
* @return true if the allowance was successful.
*/
function approve(
address _spender,
uint256 _amount
)
external
returns (
bool
)
{
allowances[msg.sender][_spender] = _amount;

emit Approval(
msg.sender,
_spender,
_amount
);

return true;
}

/**
* Checks how much a given account is allowed to spend from another given account.
* @param _owner Address of the account to check an allowance from.
* @param _spender Address of the account trying to spend from the owner.
* @return Allowance for the spender from the owner.
*/
function allowance(
address _owner,
address _spender
)
external
view
returns (
uint256
)
{
return allowances[_owner][_spender];
}
}
20 changes: 20 additions & 0 deletions examples/hardhat/deploy/ERC20.deploy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Just a standard hardhat-deploy deployment definition file!
const func = async (hre) => {
const { deployments, getNamedAccounts } = hre
const { deploy } = deployments
const { deployer } = await getNamedAccounts()

const initialSupply = 1000000
const name = 'My Optimistic Token'

await deploy('ERC20', {
from: deployer,
args: [initialSupply, name],
gasPrice: hre.ethers.BigNumber.from('0'),
gasLimit: 8999999,
log: true
})
}

func.tags = ['ERC20']
module.exports = func
29 changes: 29 additions & 0 deletions examples/hardhat/hardhat.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require('@nomiclabs/hardhat-ethers')
require('@nomiclabs/hardhat-waffle')
require('hardhat-deploy')
require("@eth-optimism/hardhat-ovm")

module.exports = {
networks: {
// Add this network to your config!
optimism: {
url: 'http://127.0.0.1:8545',
// instantiate with a mnemonic so that you have >1 accounts available
accounts: {
mnemonic: 'test test test test test test test test test test test junk'
},
// This sets the gas price to 0 for all transactions on L2. We do this
// because account balances are not automatically initiated with an ETH
// balance (yet, sorry!).
gasPrice: 0,
ovm: true // This sets the network as using the ovm and ensure contract will be compiled against that.
},
},
solidity: '0.7.6',
ovm: {
solcVersion: '0.7.6'
},
namedAccounts: {
deployer: 0
},
}
28 changes: 28 additions & 0 deletions examples/hardhat/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "@eth-optimism/hardhat-example",
"private": true,
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"deploy": "hardhat deploy",
"deploy:ovm": "hardhat deploy --network optimism",
"compile": "hardhat compile",
"compile:ovm": "hardhat compile --network optimism",
"test": "hardhat test",
"test:ovm": "hardhat test --network optimism",
"clean": "rimraf ./cache-ovm ./cache ./artifacts-ovm ./artifacts ./deployments"
},
"devDependencies": {
"@eth-optimism/hardhat-ovm": "^0.0.3",
"@nomiclabs/hardhat-ethers": "^2.0.1",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"chai": "4.3.4",
"chai-as-promised": "^7.1.1",
"ethereum-waffle": "^3.3.0",
"ethers": "^5.1.4",
"hardhat": "^2.2.0",
"hardhat-deploy": "^0.7.5",
"mocha": "^8.2.1"
}
}
Loading

0 comments on commit 122df8c

Please sign in to comment.