Git Product home page Git Product logo

solidity-create2-example's Introduction

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

solidity-create2-example's People

Contributors

miguelmota avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

solidity-create2-example's Issues

Delete me

Feel free to delete this sorry and thank you for your contributions.

Constructor in chain.json

Hey. I have a question to you.
According to parity wiki ,
"The constructor bytecode is executed when the genesis is created and the code returned by the “constructor” is stored in the genesis state."
Why you use it here ?

Factory.json

Hello,

thank you for providing this example.
How do we get the files Factory.json and Account.json?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.