Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
cmp20test
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
explorer-for-cmp20
cmp20test
Commits
09ccef1b
Commit
09ccef1b
authored
Feb 11, 2026
by
Developer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add new contract
parent
ea5dffbe
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
197 additions
and
0 deletions
+197
-0
Call.sol
contracts/Call.sol
+114
-0
testCallLogs.js
scripts/testCallLogs.js
+83
-0
No files found.
contracts/Call.sol
0 → 100644
View file @
09ccef1b
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract Callee {
uint256 public value;
uint256 public counter;
event Wrote(uint256 newValue, uint256 newCounter);
function setValue(uint256 v) external {
value = v;
counter += 1;
emit Wrote(value, counter);
}
// 先改状态,再 REVERT
function setThenRevert(uint256 v) external {
value = v;
counter += 1;
emit Wrote(value, counter);
revert("callee reverted after write");
}
// 先改状态,再 assert 触发 panic(更像“异常失败”)
function setThenAssert(uint256 v) external {
value = v;
counter += 1;
emit Wrote(value, counter);
assert(false);
}
}
contract RevertingConstructor {
uint256 public x;
constructor(uint256 v) {
x = v;
revert("constructor revert");
}
}
contract Caller {
Callee public callee;
event CallResult(bool success, bytes data);
// 新增:Caller 本地日志(persistent) — 用来演示即使内部调用回滚,Caller 的日志会保留
event CallerLog(string info);
constructor() {
callee = new Callee();
}
// 基线:成功调用会真正改 callee 状态
function okCall(uint256 v) external {
emit CallerLog("okCall: before callee.setValue");
callee.setValue(v);
emit CallerLog("okCall: after callee.setValue");
}
/**
* 关键测试1:低级 call 调用 setThenRevert
* 预期:
* - 返回 success=false
* - callee.value / callee.counter 不会改变(保持调用前的值)
* - callee 发出的 Wrote 事件不会出现在最终的 receipt 中(已被回滚)
*/
function testRevertRollback(uint256 v) external returns (bool) {
emit CallerLog("testRevertRollback: before low-level call");
(bool ok, bytes memory data) = address(callee).call(
abi.encodeWithSignature("setThenRevert(uint256)", v)
);
emit CallResult(ok, data);
emit CallerLog("testRevertRollback: after low-level call");
return ok;
}
/**
* 关键测试2:低级 call 调用 setThenAssert (panic)
* 预期同上:success=false + callee 状态不变
*/
function testPanicRollback(uint256 v) external returns (bool) {
emit CallerLog("testPanicRollback: before low-level call");
(bool ok, bytes memory data) = address(callee).call(
abi.encodeWithSignature("setThenAssert(uint256)", v)
);
emit CallResult(ok, data);
emit CallerLog("testPanicRollback: after low-level call");
return ok;
}
/**
* 关键测试3:CREATE 失败会回滚本次 CREATE 的所有副作用
* 这里我们用 try/catch 捕获创建失败,让外层不 revert。
*/
function testCreateRollback(uint256 v) external returns (bool) {
emit CallerLog("testCreateRollback: before CREATE");
bool success;
try new RevertingConstructor(v) returns (RevertingConstructor /*rc*/) {
// 这个分支理论上不会走到
success = true;
} catch (bytes memory reason) {
emit CallResult(false, reason);
success = false;
}
emit CallerLog("testCreateRollback: after CREATE");
return success;
}
// 方便读取被测状态
function readCallee() external view returns (uint256 v, uint256 c) {
v = callee.value();
c = callee.counter();
}
}
scripts/testCallLogs.js
0 → 100644
View file @
09ccef1b
const
hre
=
require
(
"
hardhat
"
);
async
function
decodeLogs
(
receipt
,
ifaces
)
{
const
decoded
=
[];
for
(
const
log
of
receipt
.
logs
)
{
let
parsed
=
null
;
for
(
const
iface
of
ifaces
)
{
try
{
parsed
=
iface
.
parseLog
(
log
);
break
;
}
catch
(
e
)
{
// not this iface
}
}
if
(
parsed
)
{
decoded
.
push
({
name
:
parsed
.
name
,
args
:
parsed
.
args
,
address
:
log
.
address
,
});
}
else
{
decoded
.
push
({
raw
:
log
});
}
}
return
decoded
;
}
async
function
main
()
{
const
[
deployer
]
=
await
hre
.
ethers
.
getSigners
();
console
.
log
(
"
Signer:
"
,
deployer
.
address
);
const
Caller
=
await
hre
.
ethers
.
getContractFactory
(
"
Caller
"
);
const
caller
=
await
Caller
.
deploy
();
await
caller
.
waitForDeployment
();
const
callerAddr
=
await
caller
.
getAddress
();
console
.
log
(
"
Caller deployed to:
"
,
callerAddr
);
const
calleeAddr
=
await
caller
.
callee
();
const
Callee
=
await
hre
.
ethers
.
getContractFactory
(
"
Callee
"
);
const
callee
=
Callee
.
attach
(
calleeAddr
);
console
.
log
(
"
Callee (created by Caller) address:
"
,
callee
.
address
);
const
ifaces
=
[
caller
.
interface
,
callee
.
interface
];
console
.
log
(
"
\n
== 1) okCall (should change callee and emit Wrote) ==
"
);
let
tx
=
await
caller
.
okCall
(
100
);
let
rcpt
=
await
tx
.
wait
();
console
.
log
(
"
okCall txHash
"
,
rcpt
.
transactionHash
);
console
.
log
(
"
Decoded logs:
"
,
await
decodeLogs
(
rcpt
,
ifaces
));
console
.
log
(
"
Callee storage after okCall:
"
,
await
caller
.
readCallee
());
console
.
log
(
"
\n
== 2) testRevertRollback (callee reverts after write) ==
"
);
tx
=
await
caller
.
testRevertRollback
(
200
);
rcpt
=
await
tx
.
wait
();
console
.
log
(
"
testRevertRollback txHash
"
,
rcpt
.
transactionHash
);
const
logs2
=
await
decodeLogs
(
rcpt
,
ifaces
);
console
.
log
(
"
Decoded logs:
"
,
logs2
);
console
.
log
(
"
Callee storage after testRevertRollback:
"
,
await
caller
.
readCallee
());
console
.
log
(
"
\n
== 3) testPanicRollback (callee assert -> panic) ==
"
);
tx
=
await
caller
.
testPanicRollback
(
300
);
rcpt
=
await
tx
.
wait
();
console
.
log
(
"
testPanicRollback txHash
"
,
rcpt
.
transactionHash
);
const
logs3
=
await
decodeLogs
(
rcpt
,
ifaces
);
console
.
log
(
"
Decoded logs:
"
,
logs3
);
console
.
log
(
"
Callee storage after testPanicRollback:
"
,
await
caller
.
readCallee
());
console
.
log
(
"
\n
== 4) testCreateRollback (constructor reverts) ==
"
);
tx
=
await
caller
.
testCreateRollback
(
999
);
rcpt
=
await
tx
.
wait
();
console
.
log
(
"
testCreateRollback txHash
"
,
rcpt
.
transactionHash
);
const
logs4
=
await
decodeLogs
(
rcpt
,
ifaces
);
console
.
log
(
"
Decoded logs:
"
,
logs4
);
console
.
log
(
"
Callee storage after testCreateRollback:
"
,
await
caller
.
readCallee
());
console
.
log
(
'
\n
Done
'
);
}
main
().
catch
((
e
)
=>
{
console
.
error
(
e
);
process
.
exitCode
=
1
;
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment