Skip to content

Commit 037be81

Browse files
author
vividcoder
committed
test: add FreezeTest.sol and bytecode comments
Reverse-engineered the Solidity source from CONTRACT_CODE and FACTORY_CODE bytecode in FreezeTest.java. Added selector and opcode comments above each bytecode constant. Also removed accidental blank lines in pr-check.yml.
1 parent 808fa99 commit 037be81

3 files changed

Lines changed: 100 additions & 2 deletions

File tree

.github/workflows/pr-check.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ jobs:
4141
}
4242
4343
// 2. Conventional format check
44-
4544
const conventionalRegex = /^(feat|fix|refactor|docs|style|test|chore|ci|perf|build|revert)(\([^)]+\))?:\s\S.*/;
46-
4745
if (title && !conventionalRegex.test(title)) {
4846
errors.push(
4947
'PR title must follow conventional format: `type(scope): description`\n' +

framework/src/test/java/org/tron/common/runtime/vm/FreezeTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@
5151
@Slf4j
5252
public class FreezeTest {
5353

54+
// Compiled from FreezeTest.sol (tron-solc ^0.5.16).
55+
// FreezeContract — inner contract with TRON freeze/unfreeze opcodes:
56+
// destroy(address) [0x00f55d9d] selfdestruct
57+
// freeze(address,uint256,uint256) [0x30e1e4e5] opcode 0xd5 FREEZE
58+
// unfreeze(address,uint256) [0x7b46b80b] opcode 0xd6 UNFREEZE
59+
// getExpireTime(address,uint256) [0xe7aa4e0b] opcode 0xd7 FREEZEEXPIRETIME
5460
private static final String CONTRACT_CODE = "608060405261037e806100136000396000f3fe6080604052"
5561
+ "34801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506004361061"
5662
+ "00655760003560e01c8062f55d9d1461006a57806330e1e4e5146100ae5780637b46b80b1461011a578063e7"
@@ -73,6 +79,13 @@ public class FreezeTest {
7379
+ "506001905092915050565b60008273ffffffffffffffffffffffffffffffffffffffff1682d7905092915050"
7480
+ "56fea26474726f6e58200fd975eab4a8c8afe73bf3841efe4da7832d5a0d09f07115bb695c7260ea64216473"
7581
+ "6f6c63430005100031";
82+
// Compiled from FreezeTest.sol (tron-solc ^0.5.16).
83+
// Factory — deploys FreezeContract and predicts CREATE2 addresses:
84+
// deployCreate2Contract(uint256) [0x41aa9014] CREATE deploy
85+
// getCreate2Addr(uint256) [0xbb63e785] CREATE2 address prediction
86+
// Note: getCreate2Addr uses bytes1(0x41) as the TRON mainnet prefix
87+
// in keccak256(abi.encodePacked(0x41, address(this), salt, codeHash)).
88+
// This value is hardcoded at compile time by tron-solc.
7689
private static final String FACTORY_CODE = "6080604052610640806100136000396000f3fe60806040523"
7790
+ "4801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5060043610610"
7891
+ "0505760003560e01c806341aa901414610055578063bb63e785146100c3575b600080fd5b610081600480360"
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
// Reconstructed from FACTORY_CODE bytecode in FreezeTest.java
3+
// Compiler: tron-solc ^0.5.16
4+
//
5+
// FACTORY_CODE contains two nested contracts:
6+
// Factory (outer) — deploys FreezeContract via CREATE / CREATE2
7+
// FreezeContract (inner) — freeze/unfreeze operations with TRON-specific opcodes
8+
9+
pragma solidity ^0.5.16;
10+
11+
// ============================================================
12+
// Inner contract — deployed by Factory via CREATE / CREATE2
13+
// ============================================================
14+
contract FreezeContract {
15+
16+
// selector: 0x00f55d9d
17+
function destroy(address payable target) external {
18+
selfdestruct(target);
19+
}
20+
21+
// selector: 0x30e1e4e5
22+
// Freeze TRX for target, then return time remaining until expiry
23+
function freeze(address payable target, uint256 amount, uint256 res)
24+
external returns (uint256)
25+
{
26+
target.freeze(amount, res); // TRON opcode 0xd5 (FREEZE)
27+
// STATICCALL to this.getExpireTime(target, res), then subtract
28+
return block.timestamp
29+
- address(this).getExpireTime(target, res);
30+
}
31+
32+
// selector: 0x7b46b80b
33+
function unfreeze(address payable target, uint256 res)
34+
external returns (uint256)
35+
{
36+
target.unfreeze(res); // TRON opcode 0xd6 (UNFREEZE)
37+
return 1;
38+
}
39+
40+
// selector: 0xe7aa4e0b
41+
function getExpireTime(address payable target, uint256 res)
42+
external view returns (uint256)
43+
{
44+
return target.freezeExpireTime(res); // TRON opcode 0xd7 (FREEZEEXPIRETIME)
45+
}
46+
}
47+
48+
// ============================================================
49+
// Factory contract — outer layer
50+
// ============================================================
51+
contract Factory {
52+
53+
// selector: 0x41aa9014
54+
// Deploy FreezeContract using CREATE (salt is unused, CREATE ignores it)
55+
function deployCreate2Contract(uint256 salt) public returns (address) {
56+
bytes memory bytecode = type(FreezeContract).creationCode;
57+
address addr;
58+
assembly {
59+
addr := create(0, add(bytecode, 0x20), mload(bytecode))
60+
}
61+
require(extcodesize(addr) > 0);
62+
return addr;
63+
}
64+
65+
// selector: 0xbb63e785
66+
// Predict CREATE2 address without deploying
67+
//
68+
// TRON CREATE2 formula (differs from standard EVM):
69+
// address = keccak256(prefix ++ sender[20] ++ salt[32] ++ keccak256(code)[32])[12:]
70+
//
71+
// - Standard EVM uses 0xff as prefix (magic byte)
72+
// - TRON replaces it with the address prefix byte (0x41 for mainnet, 0xa0 for testnet)
73+
// - This value is hardcoded at compile time by tron-solc
74+
//
75+
function getCreate2Addr(uint256 salt) public view returns (address) {
76+
bytes memory bytecode = type(FreezeContract).creationCode;
77+
bytes32 hash = keccak256(
78+
abi.encodePacked(
79+
bytes1(0x41), // TRON mainnet address prefix
80+
address(this), // 20-byte factory address
81+
salt, // 32-byte salt
82+
keccak256(bytecode) // 32-byte code hash
83+
)
84+
);
85+
return address(uint160(uint256(hash)));
86+
}
87+
}

0 commit comments

Comments
 (0)