All Projects → miguelmota → solidity-create2-example

miguelmota / solidity-create2-example

Licence: MIT license
Example of how to use the CREATE2 opcode released in the Constantinople update for Ethereum

Programming Languages

javascript
184084 projects - #8 most used programming language
Makefile
30231 projects

Projects that are alternatives of or similar to solidity-create2-example

Echidna
Ethereum smart contract fuzzer
Stars: ✭ 571 (+488.66%)
Mutual labels:  smart-contracts, evm
Remix Ide
Documentation for Remix IDE
Stars: ✭ 1,768 (+1722.68%)
Mutual labels:  smart-contracts, evm
blockhead
Crypto portfolio tracker, DeFi dashboard, NFT viewer and data explorer for the Ethereum/EVM-based blockchain ecosystem and the web 3.0-powered metaverse https://gitcoin.co/grants/2966/blockhead
Stars: ✭ 41 (-57.73%)
Mutual labels:  smart-contracts, evm
metamorphic
A factory contract for creating metamorphic (i.e. redeployable) contracts.
Stars: ✭ 167 (+72.16%)
Mutual labels:  smart-contracts, create2
awesome-ethereum-events
Inspired by the awesome list of awesome lists of awesome lists of...
Stars: ✭ 18 (-81.44%)
Mutual labels:  smart-contracts, evm
Remix Project
Remix is a browser-based compiler and IDE that enables users to build Ethereum contracts with Solidity language and to debug transactions.
Stars: ✭ 225 (+131.96%)
Mutual labels:  smart-contracts, evm
Remix
This has been moved to https://github.com/ethereum/remix-project
Stars: ✭ 1,063 (+995.88%)
Mutual labels:  smart-contracts, evm
prb-math
Solidity library for advanced fixed-point math
Stars: ✭ 404 (+316.49%)
Mutual labels:  smart-contracts, evm
EVM-Simulator
EVM-Simulator bachelor's thesis.
Stars: ✭ 36 (-62.89%)
Mutual labels:  smart-contracts, evm
gas-reporting
Reference documentation on every gas price API and all the different formats
Stars: ✭ 85 (-12.37%)
Mutual labels:  smart-contracts, evm
bytecode-verifier
Compile Solidity source code and verify its bytecode matches the blockchain
Stars: ✭ 78 (-19.59%)
Mutual labels:  smart-contracts, evm
vandal
Static program analysis framework for Ethereum smart contract bytecode.
Stars: ✭ 121 (+24.74%)
Mutual labels:  smart-contracts, evm
blockstarter
This is a white label solution to create a contribution crypto-wallet that can be used in your ICO campaign.
Stars: ✭ 21 (-78.35%)
Mutual labels:  smart-contracts
move
Home of the Move programming language
Stars: ✭ 125 (+28.87%)
Mutual labels:  smart-contracts
intx
intx – extended precision integer library
Stars: ✭ 83 (-14.43%)
Mutual labels:  evm
FFXIVOpcodeWizard
How about we not work hard?
Stars: ✭ 53 (-45.36%)
Mutual labels:  opcodes
emerald-web3-gateway
The Web3 Gateway for the Oasis Emerald ParaTime.
Stars: ✭ 19 (-80.41%)
Mutual labels:  evm
scilla-vanilla
No description or website provided.
Stars: ✭ 20 (-79.38%)
Mutual labels:  smart-contracts
NEO-Tutorial
Learning NEO Step by Step
Stars: ✭ 26 (-73.2%)
Mutual labels:  smart-contracts
ZYX-20
A Zyx Network client based on the go-ethereum fork
Stars: ✭ 0 (-100%)
Mutual labels:  evm

Solidity CREATE2 example

Example of how to use the CREATE2 opcode released in the Constantinople update for Ethereum.

Tutorial

These tutorial will show you how to predetermine a smart contract address off-chain and then deploy using create2 from a smart contract.

Factory.sol - a contract that deploys other contracts using the create2 opcode:

pragma solidity >0.4.99 <0.6.0;

contract Factory {
  event Deployed(address addr, uint256 salt);

  function deploy(bytes memory code, uint256 salt) public {
    address addr;
    assembly {
      addr := create2(0, add(code, 0x20), mload(code), salt)
      if iszero(extcodesize(addr)) {
        revert(0, 0)
      }
    }

    emit Deployed(addr, salt);
  }
}

Account.sol - the contract to counterfactual instantiate:

pragma solidity >0.4.99 <0.6.0;

contract Account {
  address public owner;

  constructor(address payable _owner) public {
    owner = _owner;
  }

  function setOwner(address _owner) public {
    require(msg.sender == owner);
    owner = _owner;
  }

  function destroy(address payable recipient) public {
    require(msg.sender == owner);
    selfdestruct(recipient);
  }

  function() payable external {}
}

Create helper functions:

// deterministically computes the smart contract address given
// the account the will deploy the contract (factory contract)
// the salt as uint256 and the contract bytecode
function buildCreate2Address(creatorAddress, saltHex, byteCode) {
  return `0x${web3.utils.sha3(`0x${[
    'ff',
    creatorAddress,
    saltHex,
    web3.utils.sha3(byteCode)
  ].map(x => x.replace(/0x/, ''))
  .join('')}`).slice(-40)}`.toLowerCase()
}

// converts an int to uint256
function numberToUint256(value) {
  const hex = value.toString(16)
  return `0x${'0'.repeat(64-hex.length)}${hex}`
}

// encodes parameter to pass as contract argument
function encodeParam(dataType, data) {
  return web3.eth.abi.encodeParameter(dataType, data)
}

// returns true if contract is deployed on-chain
async function isContract(address) {
  const code = await web3.eth.getCode(address)
  return code.slice(2).length > 0
}

Deploy factory address:

const Factory = new web3.eth.Contract(factoryAbi)
const {_address: factoryAddress} = await Factory.deploy({
    data: factoryBytecode
}).send({
  from: '0x303de46de694cc75a2f66da93ac86c6a6eee607e'
})

console.log(factoryAddress) // "0xb03F3ED17b679671C9B638f2FCd48ADcE5e26d0e"

Now you can compute off-chain deterministically the address of the account contract:

// constructor arguments are appended to contract bytecode
const bytecode = `${accountBytecode}${encodeParam('address', '0x262d41499c802decd532fd65d991e477a068e132').slice(2)}`
const salt = 1

const computedAddr = buildCreate2Address(
  factoryAddress,
  numberToUint256(salt),
  bytecode
)

console.log(computedAddr) // "0x45d673256f870c135b2858e593653fb22d39795f"
console.log(await isContract(computedAddr)) // false (not deployed on-chain)

You can send eth to the precomputed contract address 0x45d673256f870c135b2858e593653fb22d39795f even though it's not deployed. Once there's eth in the contract you can deploy the contract and have the funds sent to a different address if you wish. CREATE2 is useful because you don't need to deploy a new contract on-chain for new users; you or anyone can deploy the contract only once there's already funds in it (which the contract can have refund logic for gas).

Let's deploy the account contract using the factory:

const factory = new web3.eth.Contract(factoryAbi, factoryAddress)
const salt = 1
const bytecode = `${accountBytecode}${encodeParam('address', '0x262d41499c802decd532fd65d991e477a068e132').slice(2)}`
const result = await factory.methods.deploy(bytecode, salt).send({
  from: account,
  gas: 4500000,
  gasPrice: 10000000000,
  nonce
})


const addr = result.events.Deployed.returnValues.addr.toLowerCase()
console.log(computedAddr == addr) // true (deployed contract address is the same as precomputed address)
console.log(result.transactionHash) // "0x4b0f212af772aab80094b5fe6b5f3f3c544c099d43ce3ca7343c63bbb0776de4"
console.log(addr) // "0x45d673256f870c135b2858e593653fb22d39795f"
console.log(await isContract(computedAddr)) // true (deployed on-chain)

Example code found here.

Development

Download Parity binary from releases page (at the time of this writing Parity is only full client that supports the new opcode):

make download-parity-mac

Start parity:

make start-parity

Compile contracts:

make compile

Deploy contracts:

make deploy

Test contracts:

make test

Note: if using a different mnemonic seed, update the accounts in chain.json

Resources

Credits

License

MIT

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].