• Stars
    star
    434
  • Rank 100,274 (Top 2 %)
  • Language
    Solidity
  • License
    MIT License
  • Created about 3 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Hardhat plugin to deploy your smart contracts across multiple EVM chains with the same deterministic address.

xdeployer ๐Ÿ’ฅ

Test xdeploy License: MIT npm package

Hardhat plugin to deploy your smart contracts across multiple Ethereum Virtual Machine (EVM) chains with the same deterministic address.

It is pronounced cross-deployer.

What

This plugin will help you make easier and safer usage of the CREATE2 EVM opcode. CREATE2 can be used to compute in advance the address where a smart contract will be deployed, which allows for interesting new mechanisms known as counterfactual interactions.

Installation

With npm versions >=7:

# based on ethers v6
npm install --save-dev xdeployer

With npm version 6:

# based on ethers v6
npm install --save-dev xdeployer @nomicfoundation/hardhat-ethers ethers @openzeppelin/contracts
Using ethers v5

With npm versions >=7:

# based on ethers v5
npm install --save-dev 'xdeployer@^1.2.7'

With npm version 6:

# based on ethers v5
npm install --save-dev 'xdeployer@^1.2.7' @nomiclabs/hardhat-ethers 'ethers@^5.7.2' @openzeppelin/contracts

Or if you are using Yarn:

# based on ethers v6
yarn add --dev xdeployer @nomicfoundation/hardhat-ethers ethers @openzeppelin/contracts
Using ethers v5
# based on ethers v5
yarn add --dev 'xdeployer@^1.2.7' @nomiclabs/hardhat-ethers 'ethers@^5.7.2' @openzeppelin/contracts

In case you are using pnpm, invoke:

# based on ethers v6
pnpm add --save-dev xdeployer
Using ethers v5
# based on ethers v5
pnpm add --save-dev 'xdeployer@^1.2.7'

Note: This plugin uses the optional chaining operator (?.). Optional chaining is not supported in Node.js v13 and below.

Import the plugin in your hardhat.config.js:

require("xdeployer");

Or if you are using TypeScript, in your hardhat.config.ts:

import "xdeployer";

Required Plugins

Tasks

This plugin provides the xdeploy task, which allows you to deploy your smart contracts across multiple EVM chains with the same deterministic address:

npx hardhat xdeploy

Environment Extensions

This plugin does not extend the environment.

Configuration

You need to add the following configurations to your hardhat.config.js file:

module.exports = {
  networks: {
    mainnet: { ... }
  },
  xdeploy: {
    contract: "YOUR_CONTRACT_NAME_TO_BE_DEPLOYED",
    constructorArgsPath: "PATH_TO_CONSTRUCTOR_ARGS", // optional; default value is `undefined`
    salt: "YOUR_SALT_MESSAGE",
    signer: "SIGNER_PRIVATE_KEY",
    networks: ["LIST_OF_NETWORKS"],
    rpcUrls: ["LIST_OF_RPCURLS"],
    gasLimit: 1_500_000, // optional; default value is `1.5e6`
  },
};

Or if you are using TypeScript, in your hardhat.config.ts:

const config: HardhatUserConfig = {
  networks: {
    mainnet: { ... }
  },
  xdeploy: {
    contract: "YOUR_CONTRACT_NAME_TO_BE_DEPLOYED",
    constructorArgsPath: "PATH_TO_CONSTRUCTOR_ARGS", // optional; default value is `undefined`
    salt: "YOUR_SALT_MESSAGE",
    signer: "SIGNER_PRIVATE_KEY",
    networks: ["LIST_OF_NETWORKS"],
    rpcUrls: ["LIST_OF_RPCURLS"],
    gasLimit: 1_500_000, // optional; default value is `1.5e6`
  },
};

The parameters constructorArgsPath and gasLimit are optional. The salt parameter is a random value (32 byte string) used to create the contract address. If you have previously deployed the same contract with the identical salt, the contract creation transaction will fail due to EIP-684. For more details, see also here.

Example:

xdeploy: {
  contract: "ERC20Mock",
  constructorArgsPath: "./deploy-args.ts",
  salt: "WAGMI",
  signer: process.env.PRIVATE_KEY,
  networks: ["hardhat", "goerli", "sepolia"],
  rpcUrls: ["hardhat", process.env.ETH_GOERLI_TESTNET_URL, process.env.ETH_SEPOLIA_TESTNET_URL],
  gasLimit: 1.2 * 10 ** 6,
},

The current available networks are:

  • Local:
    • localhost
    • hardhat
  • EVM-Based Test Networks:
    • goerli
    • sepolia
    • bscTestnet
    • optimismTestnet
    • arbitrumTestnet
    • arbitrumSepolia
    • mumbai
    • polygonZkEVMTestnet
    • hecoTestnet
    • fantomTestnet
    • fuji
    • sokol
    • chiado
    • moonbaseAlpha
    • alfajores
    • auroraTestnet
    • harmonyTestnet
    • spark
    • cronosTestnet
    • evmosTestnet
    • bobaTestnet
    • cantoTestnet
    • baseTestnet
    • mantleTestnet
    • scrollTestnet
    • lineaTestnet
    • zoraTestnet
    • luksoTestnet
    • mantaTestnet
  • EVM-Based Production Networks:
    • ethMain
    • bscMain
    • optimismMain
    • arbitrumMain
    • arbitrumNova
    • polygon
    • polygonZkEVMMain
    • hecoMain
    • fantomMain
    • avalanche
    • gnosis
    • moonriver
    • moonbeam
    • celo
    • auroraMain
    • harmonyMain
    • fuse
    • cronosMain
    • evmosMain
    • bobaMain
    • cantoMain
    • mantleMain
    • lineaMain
    • zoraMain
    • luksoMain
    • mantaMain

Note that you must ensure that your deployment account has sufficient funds on all target networks. In addition, please be aware that gnosis refers to the previously known xDai chain, and arbitrumTestnet targets the (soon to be deprecated) Goerli test network, whilst arbitrumSepolia targets the Sepolia test network. Eventually, please refer to this issue why this plugin does not support the Base mainnet.

Local Deployment

If you also want to test deploy your smart contracts on "hardhat" or "localhost", you must first add the following Solidity file called Create2DeployerLocal.sol to your contracts/ folder:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { Create2Deployer } from "xdeployer/src/contracts/Create2Deployer.sol";

contract Create2DeployerLocal is Create2Deployer {}

For this kind of deployment, you must set the Solidity version in the hardhat.config.js or hardhat.config.ts file to 0.8.19 or higher.

The RPC URL for hardhat is simply hardhat, while for localhost you must first run npx hardhat node, which defaults to http://127.0.0.1:8545. It is important to note that the local deployment does not generate the same deterministic address as on all live test/production networks, since the address of the smart contract that calls the opcode CREATE2 differs locally from the live test/production networks. I recommend using local deployments for general testing, for example to understand the correct gasLimit target size.

Further Considerations

The constructor arguments file must have an exportable field called data in case you are using TypeScript:

const data = [
  "arg1",
  "arg2",
  ...
];
export { data };

BigInt literals (e.g. 100_000_000_000_000_000_000n) can be used for the constructor arguments if you set target: ES2020 in your tsconfig.json file. See also here for an example.

If you are using common JavaScript:

module.exports = [
  "arg1",
  "arg2",
  ...
];

The gasLimit field is set to 1'500'000 by default because the CREATE2 operations are a complex sequence of opcode executions. Usually the providers do not manage to estimate the gasLimit for these calls, so a predefined value is set.

The contract creation transaction is displayed on Etherscan (or any other block explorer) as a so-called internal transaction. An internal transaction is an action that is occurring within, or between, one or multiple smart contracts. In other words, it is initiated inside the code itself, rather than externally, from a wallet address controlled by a human. For more details on why it works this way, see here.

Warning
Solidity version 0.8.20 introduced support for the new opcode PUSH0, which was added as part of the Shanghai hard fork. Prior to running a deployment with a >=0.8.20-compiled bytecode (using the EVM version shanghai), please verify that all targeted EVM networks support the PUSH0 opcode. Otherwise, a deployment attempt on an EVM chain without PUSH0 support may result in deployment or runtime failure(s).

Usage

npx hardhat xdeploy

Usage With Truffle

Truffle suite users can leverage the Hardhat plugin hardhat-truffle5 (or if you use Truffle v4 hardhat-truffle4) to integrate with TruffleContract from Truffle v5. This plugin allows tests and scripts written for Truffle to work with Hardhat.

How It Works

EVM opcodes can only be called via a smart contract. I have deployed a helper smart contract Create2Deployer with the same address across all the available networks to make easier and safer usage of the CREATE2 EVM opcode. During your deployment, the plugin will call this contract.

A Note on SELFDESTRUCT

Using the CREATE2 EVM opcode always allows to redeploy a new smart contract to a previously selfdestructed contract address. However, if a contract creation is attempted, due to either a creation transaction or the CREATE/CREATE2 EVM opcode, and the destination address already has either nonzero nonce, or non-empty code, then the creation throws immediately, with exactly the same behavior as would arise if the first byte in the init code were an invalid opcode. This applies retroactively starting from genesis.

A Note on the Contract Creation Transaction

It is important to note that the msg.sender of the contract creation transaction is the helper smart contract Create2Deployer with address 0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2. If you are relying on common smart contract libraries such as OpenZeppelin for your smart contract, which set certain constructor arguments to msg.sender (e.g. owner), you will need to change these arguments to tx.origin so that they are set to your deployer's EOA address. For another workaround, see here.

Caveat: Please familiarise yourself with the security considerations concerning tx.origin. You can find more information about it, e.g. here.

Donation

I am a strong advocate of the open-source and free software paradigm. However, if you feel my work deserves a donation, you can send it to this address: 0x07bF3CDA34aA78d92949bbDce31520714AB5b228. I can pledge that I will use this money to help fix more existing challenges in the Ethereum ecosystem ๐Ÿค.

More Repositories

1

reentrancy-attacks

A chronological and (hopefully) complete list of reentrancy attacks to date.
1,287
star
2

snekmate

State-of-the-art, highly opinionated, hyper-optimised, and secure ๐ŸVyper smart contract building blocks.
Solidity
493
star
3

createx

Factory smart contract to make easier and safer usage of the `CREATE` and `CREATE2` EVM opcodes as well as of `CREATE3`-based (i.e. without an initcode factor) contract creations.
Solidity
293
star
4

create2deployer

Helper smart contract to make easier and safer usage of the `CREATE2` EVM opcode.
TypeScript
274
star
5

hardhat-project-template-ts

A fully-fledged Hardhat project template based on TypeScript.
TypeScript
209
star
6

malleable-signatures

This repository implements a simplified PoC that demonstrates how signature malleability attacks using compact signatures can be executed.
Solidity
105
star
7

ecdsa-nonce-reuse-attack

This repository implements a Python function that recovers the private key from two different signatures that use the same random nonce during signature generation.
Python
84
star
8

tornado-cash-exploit

This repository implements a simplified PoC that showcases how a contract can morph. A similar approach was used as part of the governance attack on Tornado Cash in May 2023.
Solidity
48
star
9

metatx

A smart contract to enable ERC-20 token meta-transactions on Ethereum.
JavaScript
45
star
10

escrow-contract

A simple multilateral escrow smart contract for ETH and ERC-20 tokens governed by Cobie.
TypeScript
37
star
11

raw-tx

Three scripts to ordinary generate, EIP-4844-type generate, and execute a signed raw transaction with `ethers`.
TypeScript
30
star
12

torn-detector

Detect if a contract has been deployed in the latest (or predefined) block from an address that was previously funded through Tornado.Cash.
TypeScript
22
star
13

solidity-games

A repository for Solidity-based smart contract games.
Solidity
21
star
14

meth

The moment you Rust, you should look for your Mojo ๐Ÿ”ฅ.
21
star
15

batch-distributor

Helper smart contract for batch sending both native and ERC-20 tokens.
TypeScript
20
star
16

p256-verifier-vyper

P256 (a.k.a. secp256r1 elliptic curve) signature verification ๐ŸVyper contract.
Vyper
19
star
17

create-util

Helper smart contract to make easier and safer usage of the `CREATE` EVM opcode.
TypeScript
19
star
18

mnemonic-to-private-key

A JavaScript script that converts the mnemonic phrase into a wallet private key using the ethers.js library.
JavaScript
15
star
19

ethereum-key-generation-python

Generating Ethereum addresses in Python.
Python
13
star
20

pcaversaccio

My public profile.
12
star
21

fork-testing-evm-compatibility

This repository implements a simple fork test on Optimism that proves that the EVM behaviour of the forked chain is not identically replicated locally.
Solidity
12
star
22

erc20-permit-upgradeable

Permit-enabled, upgradeable ERC20 smart contract template.
TypeScript
11
star
23

erc20-oz-sdk

How to deploy an ERC20 smart contract using OpenZeppelin SDK and write a TokenExchange smart contract.
Solidity
7
star
24

zksync-vyper-sandbox

A sandbox environment for ZKsync Era Vyper compiler testing.
TypeScript
7
star
25

mass-key-generation

A repository for mass public-private key generation (Bitcoin & Ethereum).
Java
7
star
26

tornado-cash-ether-withdrawal-decipherer

Deciphering the ether transactions in the Tornado.Cash withdrawals.
JavaScript
7
star
27

bitsquatting

Helper script for generating permutations of an ENS domain that differ by 1-bit from the original domain.
Python
7
star
28

gpg-sign-and-encrypt

This guide explains how to sign and encrypt an email using the `gpg` (GNU Privacy Guard) tool from the command line.
7
star
29

ethereum-key-generation

A repository that shows how to generate a private / public key pair using web3.js or HD wallets.
JavaScript
5
star
30

tokenbridge-helium-ethereum

A tokenbridge between the Helium blockchain (native network) and the Ethereum blockchain (foreign network).
4
star
31

chainlink-price-feed

Retrieve the ETH/USD price feed from Chainlink's oracle using Infura.
JavaScript
4
star
32

connection-vscode-to-google-colab-gpus

A step-by-step guide to connecting the local Visual Studio Code to Google Colab's GPU runtime.
4
star
33

pool-viewer

Similar to an ETH2 block explorer, but focused only on recent data.
2
star
34

pcaversaccio.github.io

My personal website.
HTML
2
star
35

payfoot-token-contract

This is PayFoot's ERC-20 smart contract, whose tokens are used as stablecoins in their ecosystem.
JavaScript
2
star
36

configurations

Monorepo for my personal configurations.
Shell
2
star
37

startfeld-token-contract

This is Startfeld's ERC-20 smart contract, whose tokens are used as vouchers in their ecosystem.
JavaScript
2
star
38

randao-distribution

Empirical distribution of the randomness beacon (=RANDAO) provided by the Beacon chain.
Python
2
star
39

porini-community-token-contract

This is Porini's ERC-20 smart contract, whose tokens can activate communities to support conservation activities and learn about blockchain technology.
JavaScript
2
star
40

impact-dollar-token-contract

This is Impact Dollar's ERC-20 smart contract, whose tokens can deliver a demonstrable contribution to conservation and protected areas through digital collectibles.
JavaScript
2
star
41

block-explorer-swissdlt

A block explorer for the Swiss DLT blockchain.
TypeScript
1
star
42

interface-solc-test

Solidity
1
star
43

saentis-gulden-token-contract

This is Sรคntis Gulden's ERC-20 smart contract, whose tokens are used as vouchers in their ecosystem.
JavaScript
1
star
44

ath-erc20-token

Smart contract of the Alethena (ATH) token.
1
star
45

telegram-group-counter

A simple Python script to check how many Telegram groups a user is in.
Python
1
star