forked from foundry-rs/foundry
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RecordLogs.t.sol
231 lines (176 loc) · 7.77 KB
/
RecordLogs.t.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.18;
import "ds-test/test.sol";
import "cheats/Vm.sol";
contract Emitter {
event LogAnonymous(bytes data) anonymous;
event LogTopic0(bytes data);
event LogTopic1(uint256 indexed topic1, bytes data);
event LogTopic12(uint256 indexed topic1, uint256 indexed topic2, bytes data);
event LogTopic123(uint256 indexed topic1, uint256 indexed topic2, uint256 indexed topic3, bytes data);
function emitAnonymousEvent(bytes memory data) public {
emit LogAnonymous(data);
}
function emitEvent(bytes memory data) public {
emit LogTopic0(data);
}
function emitEvent(uint256 topic1, bytes memory data) public {
emit LogTopic1(topic1, data);
}
function emitEvent(uint256 topic1, uint256 topic2, bytes memory data) public {
emit LogTopic12(topic1, topic2, data);
}
function emitEvent(uint256 topic1, uint256 topic2, uint256 topic3, bytes memory data) public {
emit LogTopic123(topic1, topic2, topic3, data);
}
}
contract Emitterv2 {
Emitter emitter = new Emitter();
function emitEvent(uint256 topic1, uint256 topic2, uint256 topic3, bytes memory data) public {
emitter.emitEvent(topic1, topic2, topic3, data);
}
function getEmitterAddr() public view returns (address) {
return address(emitter);
}
}
contract RecordLogsTest is DSTest {
Vm constant vm = Vm(HEVM_ADDRESS);
Emitter emitter;
bytes32 internal seedTestData = keccak256(abi.encodePacked("Some data"));
// Used on testRecordOnEmitDifferentDepths()
event LogTopic(uint256 indexed topic1, bytes data);
function setUp() public {
emitter = new Emitter();
}
function generateTestData(uint8 n) internal returns (bytes memory) {
bytes memory output = new bytes(n);
for (uint8 i = 0; i < n; i++) {
output[i] = seedTestData[i % 32];
if (i % 32 == 31) {
seedTestData = keccak256(abi.encodePacked(seedTestData));
}
}
return output;
}
function testRecordOffGetsNothing() public {
emitter.emitEvent(1, 2, 3, generateTestData(48));
Vm.Log[] memory entries = vm.getRecordedLogs();
assertEq(entries.length, 0);
}
function testRecordOnNoLogs() public {
vm.recordLogs();
Vm.Log[] memory entries = vm.getRecordedLogs();
assertEq(entries.length, 0);
}
function testRecordOnSingleLog() public {
bytes memory testData = "Event Data in String";
vm.recordLogs();
emitter.emitEvent(1, 2, 3, testData);
Vm.Log[] memory entries = vm.getRecordedLogs();
assertEq(entries.length, 1);
assertEq(entries[0].topics.length, 4);
assertEq(entries[0].topics[0], keccak256("LogTopic123(uint256,uint256,uint256,bytes)"));
assertEq(entries[0].topics[1], bytes32(uint256(1)));
assertEq(entries[0].topics[2], bytes32(uint256(2)));
assertEq(entries[0].topics[3], bytes32(uint256(3)));
assertEq(abi.decode(entries[0].data, (string)), string(testData));
assertEq(entries[0].emitter, address(emitter));
}
// TODO
// This crashes on decoding!
// The application panicked (crashed).
// Message: index out of bounds: the len is 0 but the index is 0
// Location: <local-dir>/evm/src/trace/decoder.rs:299
function NOtestRecordOnAnonymousEvent() public {
bytes memory testData = generateTestData(48);
vm.recordLogs();
emitter.emitAnonymousEvent(testData);
Vm.Log[] memory entries = vm.getRecordedLogs();
assertEq(entries.length, 1);
}
function testRecordOnSingleLogTopic0() public {
bytes memory testData = generateTestData(48);
vm.recordLogs();
emitter.emitEvent(testData);
Vm.Log[] memory entries = vm.getRecordedLogs();
assertEq(entries.length, 1);
assertEq(entries[0].topics.length, 1);
assertEq(entries[0].topics[0], keccak256("LogTopic0(bytes)"));
// While not a proper string, this conversion allows the comparison.
assertEq(abi.decode(entries[0].data, (string)), string(testData));
assertEq(entries[0].emitter, address(emitter));
}
function testEmitRecordEmit() public {
bytes memory testData0 = generateTestData(32);
emitter.emitEvent(1, 2, testData0);
vm.recordLogs();
bytes memory testData1 = generateTestData(16);
emitter.emitEvent(3, testData1);
Vm.Log[] memory entries = vm.getRecordedLogs();
assertEq(entries.length, 1);
assertEq(entries[0].topics.length, 2);
assertEq(entries[0].topics[0], keccak256("LogTopic1(uint256,bytes)"));
assertEq(entries[0].topics[1], bytes32(uint256(3)));
assertEq(abi.decode(entries[0].data, (string)), string(testData1));
assertEq(entries[0].emitter, address(emitter));
}
function testRecordOnEmitDifferentDepths() public {
vm.recordLogs();
bytes memory testData0 = generateTestData(16);
emit LogTopic(1, testData0);
bytes memory testData1 = generateTestData(20);
emitter.emitEvent(2, 3, testData1);
bytes memory testData2 = generateTestData(24);
Emitterv2 emitter2 = new Emitterv2();
emitter2.emitEvent(4, 5, 6, testData2);
Vm.Log[] memory entries = vm.getRecordedLogs();
assertEq(entries.length, 3);
assertEq(entries[0].topics.length, 2);
assertEq(entries[0].topics[0], keccak256("LogTopic(uint256,bytes)"));
assertEq(entries[0].topics[1], bytes32(uint256(1)));
assertEq(abi.decode(entries[0].data, (string)), string(testData0));
assertEq(entries[0].emitter, address(this));
assertEq(entries[1].topics.length, 3);
assertEq(entries[1].topics[0], keccak256("LogTopic12(uint256,uint256,bytes)"));
assertEq(entries[1].topics[1], bytes32(uint256(2)));
assertEq(entries[1].topics[2], bytes32(uint256(3)));
assertEq(abi.decode(entries[1].data, (string)), string(testData1));
assertEq(entries[1].emitter, address(emitter));
assertEq(entries[2].topics.length, 4);
assertEq(entries[2].topics[0], keccak256("LogTopic123(uint256,uint256,uint256,bytes)"));
assertEq(entries[2].topics[1], bytes32(uint256(4)));
assertEq(entries[2].topics[2], bytes32(uint256(5)));
assertEq(entries[2].topics[3], bytes32(uint256(6)));
assertEq(abi.decode(entries[2].data, (string)), string(testData2));
assertEq(entries[2].emitter, emitter2.getEmitterAddr());
}
function testRecordsConsumednAsRead() public {
Vm.Log[] memory entries;
emitter.emitEvent(1, generateTestData(16));
// hit record now
vm.recordLogs();
entries = vm.getRecordedLogs();
assertEq(entries.length, 0);
// emit after calling .getRecordedLogs()
emitter.emitEvent(2, 3, generateTestData(24));
entries = vm.getRecordedLogs();
assertEq(entries.length, 1);
assertEq(entries[0].topics.length, 3);
assertEq(entries[0].emitter, address(emitter));
// let's emit two more!
emitter.emitEvent(4, 5, 6, generateTestData(20));
emitter.emitEvent(generateTestData(32));
entries = vm.getRecordedLogs();
assertEq(entries.length, 2);
assertEq(entries[0].topics.length, 4);
assertEq(entries[1].topics.length, 1);
assertEq(entries[0].emitter, address(emitter));
assertEq(entries[1].emitter, address(emitter));
// the last one
emitter.emitEvent(7, 8, 9, generateTestData(24));
entries = vm.getRecordedLogs();
assertEq(entries.length, 1);
assertEq(entries[0].topics.length, 4);
assertEq(entries[0].emitter, address(emitter));
}
}