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.