【问题标题】:I'm trying to implement openzeppelin's minimal proxy clone contract on TRON blockchain我正在尝试在 TRON 区块链上实现 openzeppelin 的最小代理克隆合约
【发布时间】:2022-11-12 00:11:15
【问题描述】:

openzeppelin 最小代理合约 here 有这个函数 predictDeterministicAddress() 散列值,比如发件人的地址,盐......生成一个合约地址,create2 函数也将生成,当它传递相同的值时在这个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 区块链上的这个函数,并生成相同的合约地址。

【问题讨论】:

    标签: chainlink hardhat openzeppelin tron


    【解决方案1】:

    根据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,TRON 中的 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)
            }
        }
    

    【讨论】:

    • 你好,这行得通。非常感谢,真的。我尝试联系您,但找不到联系方式或其他信息。如果您不介意,请给我发个 dm。另外,如果您能建议我了解这些东西的方法,我将非常感激。再次感谢。
    • 我建议你去 github 或 TRON 的 discord 并提出问题。 ^_^
    • 我不认为有必要,你已经解决了我的问题。谢谢。我的意思是,我如何学习处理字节和编写程序集。
    猜你喜欢
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 2011-02-27
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    相关资源
    最近更新 更多