我正在尝试在 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)
}
}
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)
}
}