Skip to content

Commit e743d74

Browse files
authored
1 parent 11f373d commit e743d74

1 file changed

Lines changed: 255 additions & 0 deletions

File tree

tests/Lexer_Coverage.t.sol

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
/// SPDX-License-Identifier: BSD-2-Clause
2+
3+
pragma solidity ^0.6.0 <0.8.0;
4+
pragma ABIEncoderV2;
5+
pragma experimental SMTChecker;
6+
7+
/**********************************************************************
8+
* example.sol *
9+
**********************************************************************/
10+
11+
// Code in this contract is not meant to work (or be a good example).
12+
// It is meant to demonstrate good syntax highlighting by the lexer,
13+
// even if otherwise hazardous.
14+
15+
// Comments relevant to the lexer are single-line.
16+
/* Comments relevant to the code are multi-line. */
17+
18+
library Assembly {
19+
function junk(address _addr) private returns (address _ret) {
20+
assembly {
21+
let tmp := 0
22+
23+
// nested code block
24+
let mulmod_ := 0 { // evade collision with `mulmod`
25+
let tmp:=sub(mulmod_,1) // `tmp` is not a label
26+
mulmod_ := tmp
27+
}
28+
/* guess what mulmod_ is now... */
29+
_loop: // JIC, dots are invalid in labels
30+
let i := 0x10
31+
loop:
32+
// Escape sequences in comments are not parsed.
33+
/* Not sure what's going on here, but it sure is funky!
34+
\o/ \o/ \o/ \o/ \o/ \o/ \o/ \o/ \o/ \o/ \o/ \o/ \o/ */
35+
mulmod(_addr, mulmod_, 160)
36+
37+
0x1 i sub // instructional style
38+
i =: tmp /* tmp not used */
39+
40+
jumpi(loop, not(iszero(i)))
41+
42+
mstore(0x0, _addr)
43+
return(0x0, 160)
44+
}
45+
}
46+
}
47+
48+
contract Strings {
49+
// `double` is not a keyword (yet)
50+
string double = "This\ is a string\nwith \"escapes\",\
51+
and it's multi-line. // no comment"; // comment ok // even nested :)
52+
string single = 'This\ is a string\nwith "escapes",\
53+
and it\'s multi-line. // no comment'; // same thing, single-quote
54+
string hexstr = hex'537472696e67732e73656e6428746869732e62616c616e6365293b';
55+
56+
fallback() external payable virtual {}
57+
58+
receive() external payable {
59+
revert();
60+
}
61+
}
62+
63+
contract Types is Strings {
64+
using Assembly for Assembly;
65+
66+
bytes stringsruntime = type(Strings).runtimeCode;
67+
68+
// typesM (compiler chokes on invalid)
69+
int8 i8; // valid
70+
//int10 i10; // invalid
71+
uint256 ui256; // valid
72+
//uint9001 ui9001; // invalid
73+
bytes1 b1; //valid
74+
//bytes42 b42; // invalid - M out of range for `bytes`
75+
76+
// typesMxN (compiler chokes on invalid)
77+
fixed8x0 f8x0; // valid
78+
fixed8x1 f8x1; // valid
79+
fixed8x8 f8x8; // valid
80+
//fixed0x8 f0x8; // invalid since MxN scheme changed
81+
ufixed256x80 uf256x80; // valid
82+
//ufixed42x217 uf42x217; // invalid - M must be multiple of 8, N <= 80
83+
84+
// special cases (internally not types)
85+
string str; // dynamic array (not a value-type)
86+
bytes bs; // same as above
87+
//var v = 5; // `var` is a keyword, not a type, and compiler chokes
88+
uint unu$ed; // `var` is highlighted, though, and `$` is a valid char
89+
90+
address a = "0x1"; // lexer parses as string
91+
struct AddressMap {
92+
address origin;
93+
address result;
94+
address sender;
95+
bool touched;
96+
}
97+
mapping (address => AddressMap) touchedMe;
98+
99+
function failOnNegative(int8 _arg)
100+
private
101+
pure
102+
returns (uint256)
103+
{
104+
/* implicit type conversion from `int8` to `uint256` */
105+
return _arg;
106+
}
107+
108+
// some arithmetic operators + built-in names
109+
function opportunisticSend(address k) private {
110+
/* `touchedMe[k].result` et al are addresses, so
111+
`send()` available */
112+
touchedMe[k].origin.send(uint256(k)**2 % 100 finney);
113+
touchedMe[k].result.send(1 wei);
114+
touchedMe[k].sender.send(mulmod(1 szabo, k, 42));
115+
}
116+
117+
fallback() external payable override {
118+
/* inferred type: address */
119+
var k = msg.sender;
120+
/* inferred type: `ufixed0x256` */
121+
var v = 1/42;
122+
/* can't be `var` - location specifier requires explicit type */
123+
int negative = -1;
124+
125+
// valid syntax, unexpected result - not our problem
126+
ui256 = failOnNegative(negative);
127+
128+
// logic operators
129+
if ((!touchedMe[msg.sender].touched &&
130+
!touchedMe[tx.origin].touched) ||
131+
((~(msg.sender * v + a)) % 256 == 42)
132+
) {
133+
address garbled = Assembly.junk(a + msg.sender);
134+
135+
/* create a new AddressMap struct in storage */
136+
AddressMap storage tmp;
137+
138+
// TODO: highlight all known internal keywords?
139+
tmp.origin = tx.origin;
140+
tmp.result = garbled;
141+
tmp.sender = msg.sender;
142+
tmp.touched = true;
143+
144+
/* does this link-by-reference as expected?.. */
145+
touchedMe[msg.sender] = tmp;
146+
touchedMe[tx.origin] = tmp;
147+
}
148+
else {
149+
/* weak guard against re-entry */
150+
touchedMe[k].touched = false;
151+
152+
opportunisticSend(k);
153+
154+
delete touchedMe[k];
155+
/* these probably do nothing... */
156+
delete touchedMe[msg.sender];
157+
delete touchedMe[tx.origin];
158+
}
159+
}
160+
}
161+
162+
/**
163+
\brief Examples of bad practices.
164+
165+
TODO: This special NatSpec notation is not parsed yet.
166+
167+
@author Noel Maersk
168+
*/
169+
/// Triple-slash NatSpec should work.
170+
/// @title Some examples of bad practices.
171+
/// @author Noel Maersk
172+
/// @notice Very old, might've been "fixed" by obsoletion.
173+
/// @dev This is a dummy comment.
174+
/// @custom:unmaintained This code is not maintained.
175+
176+
contract BadPractices {
177+
address constant creator; /* `internal` by default */
178+
address private owner; /* forbid inheritance */
179+
bool mutex;
180+
181+
modifier critical {
182+
assert(!mutex);
183+
mutex = true;
184+
_;
185+
mutex = false;
186+
}
187+
188+
constructor() external {
189+
creator = tx.origin;
190+
owner = msg.sender;
191+
}
192+
193+
/* Dangerous - function public, and doesn't check who's calling. */
194+
function withdraw(uint _amount)
195+
public
196+
critical
197+
returns (bool)
198+
{ /* `mutex` set via modifier */
199+
/* Throwing on failed call may be dangerous. Consider
200+
returning false instead?.. */
201+
require(msg.sender.call.value(_amount)());
202+
return true;
203+
} /* `mutex` reset via modifier */
204+
205+
/* fallback */
206+
fallback() external payable {
207+
/* `i` will be `uint8`, so this is an endless loop
208+
that will consume all gas and eventually throw.
209+
*/
210+
for (var i = 0; i < 257; i++) {
211+
owner++;
212+
}
213+
}
214+
215+
/* receive()?.. nah, why bother */
216+
}
217+
218+
/* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /*
219+
// A regular multi-line comment closure, including an escaped variant as
220+
// demonstrated shortly, should close the comment; note that the lexer
221+
// should not be nesting multi-line comments.
222+
//
223+
// If the comment is still shown as "open", then a
224+
//
225+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
226+
// !!! MALICIOUS CODE SEGMENT !!!
227+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
228+
//
229+
// can be erroneously thought of as inactive, and left unread.
230+
// In fact, the compiler will produce executable code it, possibly
231+
// overriding the program above.
232+
//
233+
// It is imperative that syntax highlighters do parse it if either of
234+
// `* /` or `\* /` (with space removed) are present.
235+
//
236+
// Now, let's party! :) \*/
237+
238+
contract MoreBadPractices is BadPractices {
239+
uint balance;
240+
241+
fallback() external payable override {
242+
balance += msg.value;
243+
if (!msg.sender.send(this.balance / 10)) throw;
244+
balance -= this.balance;
245+
}
246+
}
247+
248+
/*
249+
// Open comment to EOF. Compiler chokes on this, but it's useful for
250+
// highlighting to show that there's an unmatched multi-line comment
251+
// open.
252+
253+
contract CommentToEndOfFile is MoreBadPractices {
254+
fallback() external payable override {}
255+
}

0 commit comments

Comments
 (0)