research/forwarder.py

40 lines
1.2 KiB
Python

from ethereum import utils
def mk_forwarder(address):
code = b'\x36\x60\x00\x60\x00\x37' # CALLDATACOPY 0 0 (CALLDATASIZE)
code += b'\x61\x10\x00\x60\x00\x36\x60\x00' # 4096 0 CALLDATASIZE 0
code += b'\x73' + utils.normalize_address(address) + b'\x5a' # address gas
code += b'\xf4' # delegatecall
code += b'\x61\x10\x00\x60\x00\xf3' # 4096 0 RETURN
return code
def mk_wrapper(code):
lencodepush = b'\x60' + utils.encode_int(len(code)) # length of code
returner = lencodepush + b'\x60\x0c\x60\x00' # start from 12 in code, 0 in memory
returner += b'\x39' # CODECOPY
returner += lencodepush + b'\x60\x00' + b'\xf3' # return code
assert len(returner) == 12
return returner + code
kode = """
moose: num
def increment_moose(i: num) -> num:
self.moose += i
return self.moose
"""
def test():
from ethereum.tools import tester2
c = tester2.Chain()
x = c.contract(kode, language='viper')
fwdcode = mk_forwarder(x.address)
initcode = mk_wrapper(fwdcode)
y = c.contract(initcode, language='evm')
assert c.head_state.get_code(y) == fwdcode
z = tester2.ABIContract(c, x.translator, y)
assert z.increment_moose(3) == 3
assert z.increment_moose(5) == 8
if __name__ == '__main__':
test()