Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion actuator/src/main/java/org/tron/core/vm/program/Program.java
Original file line number Diff line number Diff line change
Expand Up @@ -1621,7 +1621,8 @@ public void createContract2(DataWord value, DataWord memStart, DataWord memSize,
}

byte[] senderAddress;
if (VMConfig.allowTvmCompatibleEvm() && getCallDeep() == MAX_DEPTH) {
if ((VMConfig.allowTvmCompatibleEvm() || VMConfig.allowTvmOsaka())
&& getCallDeep() == MAX_DEPTH) {
stackPushZero();
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,72 @@ Op.CALL, new DataWord(10000),
VMConfig.initAllowTvmSelfdestructRestriction(0);
}

@Test
public void testCreate2MaxDepthWithOsakaOnly() throws ContractValidateException {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great to add a test case where both allowTvmCompatibleEvm and allowTvmOsaka are false, just to explicitly confirm that CREATE2 behaves as expected when neither flag is enabled. Helps make the intent clear for future readers!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, thanks! Added testCreate2MaxDepthWithNeitherFlag in the latest push: with both allowTvmCompatibleEvm and allowTvmOsaka disabled, the MAX_DEPTH short-circuit is not taken, so at max depth CREATE2 still proceeds as before — it records an internal transaction and pushes the new contract address instead of 0. This documents the baseline behavior alongside the Osaka-only case for future readers. PTAL.

boolean allowTvmCompatibleEvm = VMConfig.allowTvmCompatibleEvm();
boolean allowTvmOsaka = VMConfig.allowTvmOsaka();
VMConfig.initAllowTvmCompatibleEvm(0);
VMConfig.initAllowTvmOsaka(1);
try {
invoke = new ProgramInvokeMockImpl() {
@Override
public int getCallDeep() {
return 64;
}
};
Protocol.Transaction trx = Protocol.Transaction.getDefaultInstance();
InternalTransaction interTrx =
new InternalTransaction(trx, InternalTransaction.TrxType.TRX_UNKNOWN_TYPE);
program = new Program(new byte[0], new byte[0], invoke, interTrx);
program.setRootTransactionId(new byte[32]);

program.createContract2(DataWord.ZERO(), DataWord.ZERO(), DataWord.ZERO(), DataWord.ZERO());

Assert.assertEquals(DataWord.ZERO(), program.getStack().pop());
Assert.assertTrue(program.getResult().getInternalTransactions().isEmpty());
} finally {
VMConfig.initAllowTvmCompatibleEvm(allowTvmCompatibleEvm ? 1 : 0);
VMConfig.initAllowTvmOsaka(allowTvmOsaka ? 1 : 0);
}
}

@Test
public void testCreate2MaxDepthWithNeitherFlag() throws ContractValidateException {
boolean allowTvmCompatibleEvm = VMConfig.allowTvmCompatibleEvm();
boolean allowTvmOsaka = VMConfig.allowTvmOsaka();
VMConfig.initAllowTvmCompatibleEvm(0);
VMConfig.initAllowTvmOsaka(0);
try {
byte[] contractAddr = Hex.decode("41471fd3ad3e9eeadeec4608b92d16ce6b500704cc");
invoke = new ProgramInvokeMockImpl(StoreFactory.getInstance(), new byte[0], contractAddr) {
@Override
public int getCallDeep() {
return 64;
}

@Override
public boolean byTestingSuite() {
return true;
}
};
program = new Program(null, null, invoke,
new InternalTransaction(Protocol.Transaction.getDefaultInstance(),
InternalTransaction.TrxType.TRX_UNKNOWN_TYPE));
program.setRootTransactionId(new byte[32]);

program.createContract2(DataWord.ZERO(), DataWord.ZERO(), DataWord.ZERO(), DataWord.ZERO());

// With neither flag enabled the MAX_DEPTH short-circuit must not fire: CREATE2
// proceeds, records an internal transaction and pushes the new contract
// address (not 0), unlike the Osaka/CompatibleEvm guarded path above.
Assert.assertFalse(program.getResult().getInternalTransactions().isEmpty());
Assert.assertFalse(program.getStack().pop().isZero());
} finally {
VMConfig.initAllowTvmCompatibleEvm(allowTvmCompatibleEvm ? 1 : 0);
VMConfig.initAllowTvmOsaka(allowTvmOsaka ? 1 : 0);
}
}

// TIP-854 outer-frame containment: a CALL to validateMultiSign or
// batchValidateSign with malformed calldata must (a) push 0 onto the outer
// stack, (b) leave the outer frame free of any propagated exception, and
Expand Down
Loading