我正在尝试在 TRON 区块链上实施 openzeppelin 的最小代理克隆合同

I'm trying to implement openzeppelin's minimal proxy clone contract on TRON blockchain

openzeppelin 最小代理合约here has this function predictDeterministicAddress() that hashes values like the sender's address, a salt... to generate a contract address that the create2 function will also generate, when it's passed the same values as dictated in this EIP

这个 EIP 声明任意值 0xff 当用盐哈希时,发送者的地址和合约字节码将始终生成相同的地址。

我正在尝试在 TRON 区块链上实现 predictDeterministicAddress() 函数,但是 TRON docs 指定了一个不同的任意值,0x41 用于实现相同的功能.

我试图只替换这些值,但我看不到 openzeppelin 团队在他们的函数中在哪里使用了值 0xff

下面是openzeppelin哈希函数:

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
            mstore(add(ptr, 0x38), shl(0x60, deployer))
            mstore(add(ptr, 0x4c), salt)
            mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
            predicted := keccak256(add(ptr, 0x37), 0x55)
        }
    }

另外由于我对汇编的了解有限,我不能完全理解他们的哈希函数是如何工作的。

任何人都可以向我解释一下,或者帮助我理解如何在 TRON 区块链上实现该功能以达到预期的效果吗?

基本上我希望能够将相同的值传递给 create2 以及 TRON 区块链上的这个函数,并生成相同的合约地址。

根据solidity的官方文档(https://docs.soliditylang.org/en/latest/control-structures.html?highlight=create2#salted-contract-creations-create2),计算create2地址的算法应该如下:

keccak256(bytes1(0xff) ++ address(factory_contract) 
    ++ bytes32(salt) ++ keccak256(bytes(creation_code) ++ bytes(arg...)))

但是在TRON上,算法应该是这样的:

keccak256(bytes1(0x41) ++ address(factory_contract) 
    ++ bytes32(salt) ++ keccak256(bytes(creation_code) ++ bytes(arg...)))

不同的是第一个字节给了外层的keccak256函数。以太坊EVM为0xff,波场TVM为0x41

在计算预测地址(predicted := keccak256(add(ptr, 0x37), 0x55))之前,从(ptr)开始,内存数据:

0x00 ~ 0x13 3d602d80600a3d3981f3363d3d373d3d3d363d73 
0x14 ~ 0x27 (implementation address)
0x28 ~ 0x37 5af43d82803e903d91602b57fd5bf3 ff (This byte is the key, should be replaced by 0x41 on TRON)
0x38 ~ 0x4b (deployer address)
0x4c ~ 0x6b (salt bytes32)
0x6c ~ 0x8b (keccak256(0x00 ~ 0x37)) (This part hash is keccak256(bytes(creation_code) ++ bytes(arg...)))

这意味着代理合约的创建代码将是 0x3d602d80600a3d3981f3363d3d373d3d3d363d73(impl)5af43d82803e903d91602b57fd5bf3。 我们可以在(https://ethervm.io/decompile)上反编译这段代码,结果如下:

(implementation address is replaced by 0xea674fdde714fd979de3edf0f56aa9716b898ec8)

label_0000:
    // Inputs[3]
    // {
    //     @0000  returndata.length
    //     @0006  returndata.length
    //     @0009  memory[returndata.length:returndata.length + 0x2d]
    // }
    0000    3D  RETURNDATASIZE
    0001    60  PUSH1 0x2d
    0003    80  DUP1
    0004    60  PUSH1 0x0a
    0006    3D  RETURNDATASIZE
    0007    39  CODECOPY
    0008    81  DUP2
    0009    F3  *RETURN
    // Stack delta = +1
    // Outputs[3]
    // {
    //     @0000  stack[0] = returndata.length
    //     @0007  memory[returndata.length:returndata.length + 0x2d] = code[0x0a:0x37]
    //     @0009  return memory[returndata.length:returndata.length + 0x2d];
    // }
    // Block terminates

    000A    36    CALLDATASIZE
    000B    3D    RETURNDATASIZE
    000C    3D    RETURNDATASIZE
    000D    37    CALLDATACOPY
    000E    3D    RETURNDATASIZE
    000F    3D    RETURNDATASIZE
    0010    3D    RETURNDATASIZE
    0011    36    CALLDATASIZE
    0012    3D    RETURNDATASIZE
    0013    73    PUSH20 0xea674fdde714fd979de3edf0f56aa9716b898ec8
    0028    5A    GAS
    0029    F4    DELEGATECALL
    002A    3D    RETURNDATASIZE
    002B    82    DUP3
    002C    80    DUP1
    002D    3E    RETURNDATACOPY
    002E    90    SWAP1
    002F    3D    RETURNDATASIZE
    0030    91    SWAP2
    0031    60    PUSH1 0x2b
    0033    57    *JUMPI
    0034    FD    *REVERT
    0035    5B    JUMPDEST
    0036    F3    *RETURN

openzeppelin哈希函数在TRON上调整如下:

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf34100000000000000000000000000000000)
            mstore(add(ptr, 0x38), shl(0x60, deployer))
            mstore(add(ptr, 0x4c), salt)
            mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
            predicted := keccak256(add(ptr, 0x37), 0x55)
        }
    }