There is an existing unanswered question from another author with the same problem, I am creating a more detailed one with the hopes both can be closed.
I have a solidity contract based on the ideas from this post. Basically it is factory contract that allows the deployment of forwarder contracts. To minimize gas costs, after creating a forwarder you can create a clone of it.
I wish to calculate the address that will be generated using create2, which works well with the createForwarder function:
ForwarderFactory.sol
function createForwarder(address forwardAddress, uint256 salt)
public
onlyOwner
returns (Forwarder forwarder)
{
bytes memory bytecode =
abi.encodePacked(
type(Forwarder).creationCode,
uint256(uint160(address(forwardAddress)))
);
assembly {
forwarder := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
}
emit Deployed(address(forwarder), salt);
}
CalculateAddress.js
let bytecode = `${forwarderBytecode}${encodeParam(
"address",
forwardAddress
).slice(2)}`;
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();
}
That works well. However when generating a new clone address, the previous buildCreate2Address function does not work anymore because the 2nd and 3rd parameter in the create2 function are different.
ForwarderFactory.sol
function generateCloneAddress(address target, uint256 salt)
private
returns (address cloneAddress)
{
bytes20 targetBytes = bytes20(target);
assembly {
let clone := mload(0x40)
mstore(
clone,
0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
)
mstore(add(clone, 0x14), targetBytes)
mstore(
add(clone, 0x28),
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
)
cloneAddress := create2(0, clone, 0x37, salt)
}
}
I am not quite sure if its the bytecode that is changing, or if its the buildCreate2Address that needs to be updated.
363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3with the bytes from indices 10 to 29 (inclusive) being the 20-bytes address of your cloned contract. You can the details here: https://blog.openzeppelin.com/deep-dive-into-the-minimal-proxy-contract/ – Franco Jun 13 '21 at 16:32