Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Create2 library #1744

Merged
3 changes: 1 addition & 2 deletions .solcover.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module.exports = {
testCommand: 'node --max-old-space-size=4096 ../node_modules/.bin/truffle test --network coverage',
compileCommand: 'node --max-old-space-size=4096 ../node_modules/.bin/truffle compile --network coverage',
skipFiles: [
'lifecycle/Migrations.sol',
'mocks'
'mocks',
]
}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### New features:
* `Address.toPayable`: added a helper to convert between address types without having to resort to low-level casting. ([#1773](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1773))
* Facilities to make metatransaction-enabled contracts through the Gas Station Network. ([#1844](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1844))
* `Create2`: simple library to make usage of the `CREATE2` opcode easier. ([#1744](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1744))

### Improvements:
* `Address.isContract`: switched from `extcodesize` to `extcodehash` for less gas usage. ([#1802](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1802))
Expand Down
23 changes: 23 additions & 0 deletions contracts/mocks/Create2Impl.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pragma solidity ^0.5.0;

import "../utils/Create2.sol";
import "../token/ERC20/ERC20.sol";

contract Create2Impl {
nventuro marked this conversation as resolved.
Show resolved Hide resolved
function deploy(bytes32 salt, bytes memory code) public {
Create2.deploy(salt, code);
}

function deployERC20(bytes32 salt) public {
// solhint-disable-next-line indent
Create2.deploy(salt, type(ERC20).creationCode);
}

function computeAddress(bytes32 salt, bytes memory code) public view returns (address) {
return Create2.computeAddress(salt, code);
}

function computeAddress(bytes32 salt, bytes memory code, address deployer) public pure returns (address) {
return Create2.computeAddress(salt, code, deployer);
}
}
49 changes: 49 additions & 0 deletions contracts/utils/Create2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
pragma solidity ^0.5.0;

/**
* @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
* `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'.
*
* See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
* information.
*/
library Create2 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of this name. Do we have other options?

Copy link
Contributor

@nventuro nventuro Sep 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usage will be Create2.deploy(). I also dislike the name, but I'm not sure how we can more succinctly convey the underlying idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I think we wont came up with a better name.

/**
* @dev Deploys a contract using `CREATE2`. The address where the contract
* will be deployed can be known in advance via {computeAddress}. Note that
* a contract cannot be deployed twice using the same salt.
*/
function deploy(bytes32 salt, bytes memory bytecode) internal returns (address) {
address addr;
// solhint-disable-next-line no-inline-assembly
assembly {
addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
if iszero(addr) {
revert(0, 0)
}
}
return addr;
}

/**
* @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the `bytecode`
* or `salt` will result in a new destination address.
*/
function computeAddress(bytes32 salt, bytes memory bytecode) internal view returns (address) {
return computeAddress(salt, bytecode, address(this));
}

/**
* @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
* `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
*/
function computeAddress(bytes32 salt, bytes memory bytecodeHash, address deployer) internal pure returns (address) {
bytes32 bytecodeHashHash = keccak256(bytecodeHash);
bytes32 _data = keccak256(
abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHashHash)
);
return address(bytes20(_data << 96));
}
}
2 changes: 2 additions & 0 deletions contracts/utils/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ Miscellaneous contracts containing utility functions, often related to working w

{{Arrays}}

{{Create2}}

{{ReentrancyGuard}}
Loading