Added utility function to compute CREATE2 addresses (#697).
This commit is contained in:
parent
7250cdcd31
commit
f8087ae39c
@ -3,7 +3,7 @@
|
||||
// We use this for base 36 maths
|
||||
import BN from 'bn.js';
|
||||
|
||||
import { arrayify, stripZeros, hexlify } from './bytes';
|
||||
import { arrayify, concat, stripZeros, hexlify } from './bytes';
|
||||
import { BigNumber } from './bignumber';
|
||||
import { keccak256 } from './keccak256';
|
||||
import { encode } from './rlp';
|
||||
@ -140,3 +140,47 @@ export function getContractAddress(transaction: { from: string, nonce: Arrayish
|
||||
])).substring(26));
|
||||
}
|
||||
|
||||
export type Create2Options = {
|
||||
from: string,
|
||||
salt: Arrayish,
|
||||
initCode?: Arrayish,
|
||||
initCodeHash?: Arrayish,
|
||||
};
|
||||
|
||||
// See: https://eips.ethereum.org/EIPS/eip-1014
|
||||
export function getCreate2Address(options: Create2Options): string {
|
||||
let initCodeHash = options.initCodeHash;
|
||||
if (options.initCode) {
|
||||
if (initCodeHash) {
|
||||
if (keccak256(options.initCode) !== initCodeHash) {
|
||||
errors.throwError("initCode/initCodeHash mismatch", errors.INVALID_ARGUMENT, {
|
||||
arg: "options", value: options
|
||||
});
|
||||
}
|
||||
} else {
|
||||
initCodeHash = keccak256(options.initCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (!initCodeHash) {
|
||||
errors.throwError("missing initCode or initCodeHash", errors.INVALID_ARGUMENT, {
|
||||
arg: "options", value: options
|
||||
});
|
||||
}
|
||||
|
||||
const from = getAddress(options.from);
|
||||
|
||||
const salt = arrayify(options.salt);
|
||||
if (salt.length !== 32) {
|
||||
errors.throwError("invalid salt", errors.INVALID_ARGUMENT, {
|
||||
arg: "options", value: options
|
||||
});
|
||||
}
|
||||
|
||||
return getAddress("0x" + keccak256(concat([
|
||||
"0xff",
|
||||
from,
|
||||
salt,
|
||||
initCodeHash
|
||||
])).substring(26));
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType } from './abi-coder';
|
||||
import { getAddress, getContractAddress, getIcapAddress } from './address';
|
||||
import { getAddress, getContractAddress, getCreate2Address, getIcapAddress } from './address';
|
||||
import * as base64 from './base64';
|
||||
import { BigNumber, bigNumberify } from './bignumber';
|
||||
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, isHexString, joinSignature, padZeros, splitSignature, stripZeros } from './bytes';
|
||||
@ -103,6 +103,7 @@ export {
|
||||
getAddress,
|
||||
getIcapAddress,
|
||||
getContractAddress,
|
||||
getCreate2Address,
|
||||
|
||||
formatEther,
|
||||
parseEther,
|
||||
|
@ -36,3 +36,64 @@ describe('Checksum and ICAP address generation', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Create2 Address Generation", function() {
|
||||
var tests = [
|
||||
{
|
||||
name: "Example 0",
|
||||
from: "0x0000000000000000000000000000000000000000",
|
||||
salt: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
initCode: "0x00",
|
||||
expected: "0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38"
|
||||
},
|
||||
{
|
||||
name: "Example 1",
|
||||
from: "0xdeadbeef00000000000000000000000000000000",
|
||||
salt: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
initCode: "0x00",
|
||||
expected: "0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3"
|
||||
},
|
||||
{
|
||||
name: "Example 2",
|
||||
from: "0xdeadbeef00000000000000000000000000000000",
|
||||
salt: "0x000000000000000000000000feed000000000000000000000000000000000000",
|
||||
initCode: "0x00",
|
||||
expected: "0xD04116cDd17beBE565EB2422F2497E06cC1C9833"
|
||||
},
|
||||
{
|
||||
name: "Example 3",
|
||||
from: "0x0000000000000000000000000000000000000000",
|
||||
salt: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
initCode: "0xdeadbeef",
|
||||
expected: "0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e"
|
||||
},
|
||||
{
|
||||
name: "Example 4",
|
||||
from: "0x00000000000000000000000000000000deadbeef",
|
||||
salt: "0x00000000000000000000000000000000000000000000000000000000cafebabe",
|
||||
initCode: "0xdeadbeef",
|
||||
expected: "0x60f3f640a8508fC6a86d45DF051962668E1e8AC7"
|
||||
},
|
||||
{
|
||||
name: "Example 5",
|
||||
from: "0x00000000000000000000000000000000deadbeef",
|
||||
salt: "0x00000000000000000000000000000000000000000000000000000000cafebabe",
|
||||
initCode: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
|
||||
expected: "0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C"
|
||||
},
|
||||
{
|
||||
name: "Example 6",
|
||||
from: "0x0000000000000000000000000000000000000000",
|
||||
salt: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
initCode: "0x",
|
||||
expected: "0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0"
|
||||
},
|
||||
];
|
||||
|
||||
tests.forEach(function(test) {
|
||||
it("correctly computes the Create2 address - " + test.name, function() {
|
||||
const address = ethers.utils.getCreate2Address(test);
|
||||
assert.equal(address, test.expected, "correctly computes Create2 address");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user