5

I'd like to know either how to implement the skinny CREATE2 in Python or a package that provides it.

This is the function I'm trying to port from TypeScript to Python. It calls generateAddress2 with that particular salt (size 32):

export function getUserIdentity(walletAddr) {
    const bytecode = getBytecode(walletAddr)
    const addr = getAddress(
        `0x${generateAddress2(ADDR_FACTORY, Buffer.alloc(32), bytecode).toString(
            "hex"
        )}`
    )
    return { bytecode, addr }
}

And this is the ethereumjs generateAddress2 implementation:

/**
 * Generates an address for a contract created using CREATE2.
 * @param from The address which is creating this new address
 * @param salt A salt
 * @param initCode The init code of the contract being created
 */
export const generateAddress2 = function(from: Buffer, salt: Buffer, initCode: Buffer): Buffer {
  assertIsBuffer(from)
  assertIsBuffer(salt)
  assertIsBuffer(initCode)

  assert(from.length === 20)
  assert(salt.length === 32)

  const address = keccak256(
    Buffer.concat([Buffer.from('ff', 'hex'), from, salt, keccak256(initCode)]),
  )

  return address.slice(-20)
}

Many thanks!

1 Answer 1

8

Sorted, just in case it helps anyone:

@pytest.mark.parametrize('address, salt, init_code, expected_address', [
    (
        '0x0000000000000000000000000000000000000000',
        '0x0000000000000000000000000000000000000000000000000000000000000000',
        '0x00',
        '0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38',
    ),
    (
        '0xdeadbeef00000000000000000000000000000000',
        '0x0000000000000000000000000000000000000000000000000000000000000000',
        '0x00',
        '0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3',
    ),
    (
        '0xdeadbeef00000000000000000000000000000000',
        '0x000000000000000000000000feed000000000000000000000000000000000000',
        '0x00',
        '0xD04116cDd17beBE565EB2422F2497E06cC1C9833',
    ),
    (
        '0x0000000000000000000000000000000000000000',
        '0x0000000000000000000000000000000000000000000000000000000000000000',
        '0xdeadbeef',
        '0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e',
    ),
    (
        '0x00000000000000000000000000000000deadbeef',
        '0x00000000000000000000000000000000000000000000000000000000cafebabe',
        '0xdeadbeef',
        '0x60f3f640a8508fC6a86d45DF051962668E1e8AC7',
    ),
    (
        '0x00000000000000000000000000000000deadbeef',
        '0x00000000000000000000000000000000000000000000000000000000cafebabe',
        '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
        '0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C',
    ),
    (
        '0x0000000000000000000000000000000000000000',
        '0x0000000000000000000000000000000000000000000000000000000000000000',
        '0x',
        '0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0',
    ),
])
def test_create2(address, salt, init_code, expected_address):
    """Test the CREATE2 opcode Python implementation.

    EIP-104
    https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md
    """
    from eth_utils import to_checksum_address
    from web3 import Web3

    pre = '0xff'
    b_pre = bytes.fromhex(pre[2:])
    b_address = bytes.fromhex(address[2:])
    b_salt = bytes.fromhex(salt[2:])
    b_init_code = bytes.fromhex(init_code[2:])

    keccak_b_init_code = Web3.keccak(b_init_code)
    b_result = Web3.keccak(b_pre + b_address + b_salt + keccak_b_init_code)
    result_address = to_checksum_address(b_result[12:].hex())

    assert result_address == expected_address

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.