research/impurity/check_for_impurity.se

71 lines
3.2 KiB
Plaintext
Raw Normal View History

2017-03-24 05:43:24 +00:00
macro calldatachar($x):
div(calldataload($x), 2**248)
2017-04-14 09:56:06 +00:00
# sum([2**x for x in [0x31, 0x32, 0x33, 0x3a, 0x3b, 0x3c, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x54, 0x55, 0xf0, 0xff]])
mask = 57897811465722876096115075801844696845150819816717216876035649536196444422144
2017-03-24 05:43:24 +00:00
data approved_addrs[]
def submit(addr: address):
# Copy external contract code
extcode = string(~extcodesize(addr))
~extcodecopy(addr, extcode, 0, ~extcodesize(addr))
ops = array(~extcodesize(addr))
pushargs = array(~extcodesize(addr))
# Loop through the code
with i = 0:
with op = 0:
while i < len(extcode):
with c = ~mod(~mload(extcode + i - 31), 256):
# Banned opcode
if ~and(2**c, mask):
~invalid()
# PUSH
if 0x60 <= c and c <= 0x7f:
pushargs[op] = ~div(~mload(extcode + i + 1), 256 ** (0x7f - c))
i += c - 0x5e
# Call, callcode, delegatecall
elif c == 0xf1 or c == 0xf2 or c == 0xf4:
2017-04-14 09:56:06 +00:00
# Pattern-match four ways of setting the gas parameter:
2017-03-24 05:43:24 +00:00
#
# 1. PUSH<value>
2017-04-14 09:56:06 +00:00
# 2. sub(GAS, PUSH<value>)
# 3. GAS
# 4. SWAP1 <address> (<gas> ... )
# 5. DUP
2017-03-24 05:43:24 +00:00
if op >= 2 and ops[op - 1] >= 0x60 and ops[op - 1] <= 0x7f:
address_entry = op - 2
elif op >= 4 and ops[op - 1] == 0x03 and ops[op - 2] == 0x5a and ops[op - 3] >= 0x60 and ops[op - 3] <= 0x7f:
address_entry = op - 4
2017-04-14 09:56:06 +00:00
elif op >= 2 and ops[op - 1] == 0x5a:
address_entry = op - 2
elif op >= 2 and ops[op - 1] == 0x90:
address_entry = op - 2
elif op >= 2 and ops[op - 1] >= 0x80 and ops[op - 1] < 0x90:
address_entry = op - 2
2017-03-24 05:43:24 +00:00
else:
~invalid()
# Operation before the gas parameter must satisfy one of three conditions:
#
# 1. It is a PUSH of an already approved address
# 2. It is the address itself, through the ADDRESS opcode (ie. self-calling is permitted)
# 3. It is a PUSH1, ie. less than 256 (ie. a present or future precompile)
if self.approved_addrs[pushargs[address_entry]]:
success = 1
elif ops[address_entry] == 0x30:
success = 1
elif ops[address_entry] == 0x60:
success = 1
if not success:
~invalid()
i += 1
else:
i += 1
ops[op] = c
op += 1
self.approved_addrs[addr] = 1
return(1: bool)
2017-03-24 05:53:49 +00:00
def const check(addr: address):
2017-03-24 05:43:24 +00:00
return(self.approved_addrs[addr]:bool)