def test_if_enough_time_passed_since_last_play_then_grant_earnings_to_last_player( self): # Player 1 presses the button result = self.contract.process(MIN_AMOUNT_REQUIRED, value=140, sender=t.k0) self.assertEquals(result, 1) self.state.mine(1) winningBalanceBefore = State().get_balance(u.int_to_addr(t.k1)) losingBalanceBefore = State().get_balance(u.int_to_addr(t.k0)) # Player 2 presses the button result = self.contract.process(MIN_AMOUNT_REQUIRED, value=140, sender=t.k1) self.assertEquals(result, 1) self.state.mine(3) # Player 2 presses the button again result = self.contract.process(MIN_AMOUNT_REQUIRED, value=140, sender=t.k1) self.assertEquals(result, 2) winningBalanceAfter = State().get_balance(u.int_to_addr(t.k1)) losingBalanceAfter = State().get_balance(u.int_to_addr(t.k0)) self.assertEquals(losingBalanceAfter, losingBalanceBefore) self.assertTrue(winningBalanceAfter > losingBalanceBefore)
def test_reverter(): c = tester.Chain() x = c.contract(reverter_code, value=10**15, language='serpent') x.entry() assert c.head_state.get_storage_data(x.address, 8080) == 4040 assert c.head_state.get_balance(utils.int_to_addr(5050)) == 9 assert c.head_state.get_storage_data(x.address, 8081) == 0 assert c.head_state.get_balance(utils.int_to_addr(5051)) == 0
def validator_inject(state, vcode, deposit_size, randao_commitment, address, nonce=0, ct=None): if not ct: ct = get_casper_ct() state.set_balance(utils.int_to_addr(1), deposit_size) t = Transaction(nonce, 0, 10**8, casper_config['CASPER_ADDR'], deposit_size, ct.encode('deposit', [vcode, randao_commitment, address])) t._sender = utils.int_to_addr(1) success, output = apply_transaction(state, t) assert success
def test_simple_send(self): self.c.issue(tester.a0, 100000000000) assert self.c.balance(tester.a0) == 100000000000 assert self.c.send(tester.a1, 1000) == 1 assert self.c.balance(tester.a0) == 100000000000 - 1000 assert self.c.balance(tester.a1) == 1000 last_tx = self.c.last_tx() assert utils.int_to_addr(last_tx[0]) == tester.a0 assert utils.int_to_addr(last_tx[1]) == tester.a1 assert last_tx[2:] == [1000, 1]
def test_chain(alloc={}, genesis_gas_limit=9999999, min_gas_limit=5000, startgas=3141592): # alloc alloc[tester.a0] = {'balance': 100000 * utils.denoms.ether} for i in range(9): alloc[utils.int_to_addr(i)] = {'balance': 1} # genesis header = { "number": 0, "gas_limit": genesis_gas_limit, "gas_used": 0, "timestamp": 1467446877, "difficulty": 1, "uncles_hash": '0x' + utils.encode_hex(utils.sha3(rlp.encode([]))) } genesis = mk_basic_state(alloc, header, tester.get_env(None)) # tester tester.languages['viper'] = compiler.Compiler() tester.STARTGAS = startgas chain = tester.Chain(alloc=alloc, genesis=genesis) chain.chain.env.config['MIN_GAS_LIMIT'] = min_gas_limit chain.mine(1) return chain
def test_crowdfund(): c = tester.Chain() x = c.contract(crowdfund_code, language='serpent') # Create a campaign with id 100 x.create_campaign(100, 45, 100000, 2) # Create a campaign with id 200 x.create_campaign(200, 48, 100000, 2) # Make some contributions x.contribute(100, value=1, sender=tester.k1) assert 1 == x.progress_report(100) x.contribute(200, value=30000, sender=tester.k2) x.contribute(100, value=59049, sender=tester.k3) assert 59050 == x.progress_report(100) x.contribute(200, value=70001, sender=tester.k4) # Expect the 100001 units to be delivered to the destination # account for campaign 2 assert 100001 == c.head_state.get_balance(utils.int_to_addr(48)) mida1 = c.head_state.get_balance(tester.a1) mida3 = c.head_state.get_balance(tester.a3) # Mine 5 blocks to expire the campaign c.mine(5) # Ping the campaign after expiry x.contribute(100, value=1) # Expect refunds assert mida1 + 1 == c.head_state.get_balance(tester.a1) assert mida3 + 59049 == c.head_state.get_balance(tester.a3)
def test_typed_storage(): def randomword(length): return ''.join(random.choice(string.lowercase) for i in range(length)) types = nc.TypedStorage._valid_types random.seed(1) # a hardcoded seed to make the test deterministic for t in types: ts = nc.TypedStorage(t) td = dict() randomprefix = randomword(random.randint(1, 10)) randomkey = randomword(random.randint(1, 50)) ts.setup(randomprefix, td.get, td.__setitem__) if t == 'address': address = utils.int_to_addr(random.randint(0, 0xFFFFFFFF)) ts.set(randomkey, address, t) assert ts.get(randomkey, t) == address elif t == 'string' or t == 'bytes' or t == 'binary': word = randomword(10) ts.set(randomkey, word, t) assert ts.get(randomkey, t) == word elif 'uint' in t: size = int(t[4:]) v = random.randint(0, 2**size - 1) ts.set(randomkey, v, t) assert ts.get(randomkey, t) == v elif 'int' in t: size = int(t[3:]) v = random.randint(0, 2**(size - 2) - 1) ts.set(randomkey, v, t) assert ts.get(randomkey, t) == v else: pass
def test_crowdfund(): s = tester.state() c = s.abi_contract(crowdfund_code) # Create a campaign with id 100 c.create_campaign(100, 45, 100000, 2) # Create a campaign with id 200 c.create_campaign(200, 48, 100000, 2) # Make some contributions c.contribute(100, value=1, sender=tester.k1) assert 1 == c.progress_report(100) c.contribute(200, value=30000, sender=tester.k2) c.contribute(100, value=59049, sender=tester.k3) assert 59050 == c.progress_report(100) c.contribute(200, value=70001, sender=tester.k4) # Expect the 100001 units to be delivered to the destination # account for campaign 2 assert 100001 == s.block.get_balance(utils.int_to_addr(48)) mida1 = s.block.get_balance(tester.a1) mida3 = s.block.get_balance(tester.a3) # Mine 5 blocks to expire the campaign s.mine(5) # Ping the campaign after expiry c.contribute(100, value=1) # Expect refunds assert mida1 + 1 == s.block.get_balance(tester.a1) assert mida3 + 59049 == s.block.get_balance(tester.a3)
def listener(log): print "LISTENER", log if log['_event_type'] == 'Created': addr = utils.int_to_addr(log['addr']) spread_contracts.append(addr.encode('hex')) if log['_event_type'] == 'NextCalled': depths.append(log['depth'])
class NativeContractBase(object): address = utils.int_to_addr(1024) def __init__(self, ext, msg): self._ext = ext self._msg = msg self.gas = msg.gas @classmethod def _on_msg(cls, ext, msg): nac = cls(ext, msg) try: return nac._safe_call() except Exception: log.error('contract errored', contract=cls.__name__) print(traceback.format_exc()) return 0, msg.gas, [] def _get_storage_data(self, key): return self._ext.get_storage_data(self._msg.to, key) def _set_storage_data(self, key, value): return self._ext.set_storage_data(self._msg.to, key, value) def _safe_call(self): return 1, self.gas, []
def custom_chain(tester, alloc={}, genesis_gas_limit=4712388, min_gas_limit=5000, startgas=3141592): # alloc for i in range(9): alloc[utils.int_to_addr(i)] = {'balance': 1} # genesis from ethereum.genesis_helpers import mk_basic_state header = { "number": 0, "gas_limit": genesis_gas_limit, "gas_used": 0, "timestamp": 1467446877, "difficulty": 1, "uncles_hash": '0x' + utils.encode_hex(utils.sha3(rlp.encode([]))) } genesis = mk_basic_state(alloc, header, tester.get_env(None)) # tester tester.languages['viper'] = compiler.Compiler() tester.STARTGAS = startgas c = tester.Chain(alloc=alloc, genesis=genesis) c.chain.env.config['MIN_GAS_LIMIT'] = min_gas_limit c.mine(1) return c
class TestTSC(nc.NativeContract): address = utils.int_to_addr(2051) size = nc.Scalar('uint32') numbers = nc.List('uint32') words = nc.Dict('bytes') def setup_numbers(ctx, size='uint32', returns=None): ctx.size = size assert isinstance(ctx.numbers, nc.List) for i in range(size): ctx.numbers.append(i) def sum_numbers(ctx, returns='uint32'): assert ctx.size == len(ctx.numbers) return sum(ctx.numbers[i] for i in range(len(ctx.numbers))) def setup_words(ctx, num='uint32', returns=None): for i in range(num): key = 'key%d' % i word = 'word%d' % i ctx.words[key] = word assert ctx.words[key] == word def get_word(ctx, key='bytes', returns='bytes'): r = ctx.words[key] return r def muladdsize(ctx, val='uint32', returns='uint32'): ctx.size += val ctx.size *= val return ctx.size
class CreateNativeContractInstance(NativeContractBase): """ special contract to create an instance of native contract instance refers to instance in the BC. msg.data[:4] defines the native contract msg.data[4:] is sent as data to the new contract call with last 4 bytes of the address of the contract for which an instance should be created. i.e. msg.data = ContractClass.address[-4:] called by _apply_message value was added to this contract (needs to be moved) """ address = utils.int_to_addr(1024) def _safe_call(self): log.debug('create native contract instance called') assert len(self._msg.sender) == 20 assert len(self._msg.data.extract_all()) >= 4 # get native contract nc_address = registry.native_contract_address_prefix + self._msg.data.extract_all( )[:4] if nc_address not in registry: return 0, self._msg.gas, b'' native_contract = registry[nc_address].im_self # get new contract address if self._ext.tx_origin != self._msg.sender: self._ext._block.increment_nonce(self._msg.sender) nonce = utils.encode_int( self._ext._block.get_nonce(self._msg.sender) - 1) self._msg.to = registry.mk_instance_address(native_contract, self._msg.sender, nonce) assert not self._ext.get_balance(self._msg.to) # must be none existant # value was initially added to this contract's address, we need to transfer success = self._ext._block.transfer_value(self.address, self._msg.to, self._msg.value) assert success assert not self._ext.get_balance(self.address) # call new instance with additional data self._msg.is_create = True self._msg.data = vm.CallData(self._msg.data.data[4:], 0, 0) res, gas, dat = registry[self._msg.to](self._ext, self._msg) assert gas >= 0 log.debug('created native contract instance', template=nc_address.encode('hex'), instance=self._msg.to.encode('hex')) return res, gas, memoryview(self._msg.to).tolist()
def tester_state(deploy_key, private_keys, tester_blockgas_limit): tester_state = tester.state() # special addresses 1 to 5 alloc = { int_to_addr(i): {'wei': 1} for i in range(1, 5) } for privkey in [deploy_key] + private_keys: address = privatekey_to_address(privkey) alloc[address] = { 'balance': DEFAULT_BALANCE, } for account in tester.accounts: alloc[account] = { 'balance': DEFAULT_BALANCE, } db = ethereum.db.EphemDB() env = ethereum.config.Env( db, ethereum.config.default_config, ) genesis_overwrite = { 'nonce': zpad(data_decoder('0x00006d6f7264656e'), 8), 'difficulty': quantity_decoder('0x20000'), 'mixhash': zpad(b'\x00', 32), 'coinbase': address_decoder('0x0000000000000000000000000000000000000000'), 'timestamp': 0, 'extra_data': b'', 'gas_limit': tester_blockgas_limit, 'start_alloc': alloc, } genesis_block = ethereum.blocks.genesis( env, **genesis_overwrite ) # enable DELEGATECALL opcode genesis_block.number = genesis_block.config['HOMESTEAD_FORK_BLKNUM'] + 1 tester_state.db = db tester_state.env = env tester_state.block = genesis_block tester_state.blocks = [genesis_block] return tester_state
def OP_CALLCODE(): subgas, to, value, meminstart, meminsz, memoutstart, memoutsz = \ stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop() if not mem_extend(mem, msgtop.compustate, '', meminstart, meminsz) or \ not mem_extend(mem, msgtop.compustate, '', memoutstart, memoutsz): return drop(OUT_OF_GAS) if msgtop.compustate.gas < subgas: return drop(out_of_gas_exception('subcall gas', gas, msgtop.compustate, '')) msgtop.compustate.gas -= subgas data = [0] * ((meminsz >> 5) + 1) copy32(mem, data, meminstart, 0, meminsz) call_msg = Message(msgtop.to, msgtop.to, value, subgas, data, meminsz) special[0] = 'call' special[1] = call_msg special[2] = block.get_code(utils.int_to_addr(to)) special[3] = memoutstart special[4] = memoutsz
class TestTSC(nc.NativeContract): address = utils.int_to_addr(2051) owner = nc.Scalar('address') def own(ctx, returns=None): if ctx.owner == '\0' * 20: ctx.owner = ctx.tx_origin assert ctx.owner == ctx.tx_origin def assert_owner(ctx): if ctx.tx_origin != ctx.owner: raise RuntimeError('not owner') @nc.constant def protected(ctx, returns='uint32'): ctx.assert_owner() return 1
class TestTSC(nc.TypedStorageContract): address = utils.int_to_addr(2050) a = nc.Scalar('uint32') b = nc.List('uint16') c = nc.Dict('uint32') def _safe_call(ctx): # skalar assert ctx.a == 0 ctx.a = 1 assert ctx.a == 1 ctx.a = 2 assert ctx.a == 2 # list assert isinstance(ctx.b, nc.List) ctx.b[0] = 10 assert ctx.b[0] == 10 ctx.b[1000] = 12 assert ctx.b[1000] == 12 assert len(ctx.b) == 1001 ctx.b[1000] = 66 assert ctx.b[1000] == 66 assert len(ctx.b) == 1001 ctx.b.append(99) assert len(ctx.b) == 1002 ctx.b.append(99) assert len(ctx.b) == 1003 # mapping assert isinstance(ctx.c, nc.Dict) key = b'test' assert ctx.c[key] == 0 ctx.c[key] = 33 assert ctx.c[key] == 33 ctx.c[key] = 66 assert ctx.c[key] == 66 return 1, 1, []
def custom_chain(tester, alloc={}, genesis_gas_limit=4712388, min_gas_limit=5000, startgas=3141592): # alloc for i in range(9): alloc[utils.int_to_addr(i)] = {'balance': 1} # genesis from ethereum.genesis_helpers import mk_basic_state header = { "number": 0, "gas_limit": genesis_gas_limit, "gas_used": 0, "timestamp": 1467446877, "difficulty": 1, "uncles_hash": '0x'+utils.encode_hex(utils.sha3(rlp.encode([]))) } genesis = mk_basic_state(alloc, header, tester.get_env(None)) # tester tester.languages['viper'] = compiler.Compiler() tester.STARTGAS = startgas c = tester.Chain(alloc=alloc, genesis=genesis) c.chain.env.config['MIN_GAS_LIMIT'] = min_gas_limit c.mine(1) return c
def OP_CALL(): subgas, to, value, meminstart, meminsz, memoutstart, memoutsz = \ stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop() if max(meminstart + meminsz, memoutstart + memoutsz) > len(mem) << 5: if not mem_extend(mem, msgtop.compustate, '', meminstart, meminsz) or \ not mem_extend(mem, msgtop.compustate, '', memoutstart, memoutsz) or \ msgtop.compustate.gas < subgas: return drop(OUT_OF_GAS) msgtop.compustate.gas -= subgas if block.get_balance(msgtop.to) >= value: data = [0] * ((meminsz >> 5) + 1) copy32(mem, data, meminstart, 0, meminsz) to = utils.int_to_addr(to) call_msg = Message(msgtop.to, to, value, subgas, data, meminsz) special[0] = 'call' special[1] = call_msg special[2] = block.get_code(to) special[3] = memoutstart special[4] = memoutsz else: stk.append(0)
def __init__(self, num_accounts=len(keys)): self.temp_data_dir = tempfile.mkdtemp() self.db = db.EphemDB() self.env = Env(self.db) self.last_tx = None initial_balances = {} for i in range(num_accounts): account = accounts[i] initial_balances[account] = {'wei': 10 ** 24} for i in range(1, 5): address = int_to_addr(i) initial_balances[address] = {'wei': 1} self.block = blocks.genesis( self.env, start_alloc=initial_balances, ) self.blocks = [self.block] self.block.timestamp = 1410973349 self.block.coinbase = DEFAULT_ACCOUNT self.block.gas_limit = 10 ** 9
def __init__(self, num_accounts=len(keys)): self.temp_data_dir = tempfile.mkdtemp() self.db = db.EphemDB() self.env = Env(self.db) self.last_tx = None initial_balances = {} for i in range(num_accounts): account = accounts[i] initial_balances[account] = {'wei': 10**24} for i in range(1, 5): address = int_to_addr(i) initial_balances[address] = {'wei': 1} self.block = blocks.genesis( self.env, start_alloc=initial_balances, ) self.blocks = [self.block] self.block.timestamp = 1410973349 self.block.coinbase = DEFAULT_ACCOUNT self.block.gas_limit = 10**9
accounts = [] keys = [] for account_number in range(10): keys.append(sha3(to_string(account_number))) accounts.append(privtoaddr(keys[-1])) k0, k1, k2, k3, k4, k5, k6, k7, k8, k9 = keys[:10] a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = accounts[:10] base_alloc = {} minimal_alloc = {} for a in accounts: base_alloc[a] = {'balance': 10**24} for i in range(1, 9): base_alloc[int_to_addr(i)] = {'balance': 1} minimal_alloc[int_to_addr(i)] = {'balance': 1} minimal_alloc[accounts[0]] = {'balance': 10**18} # Initialize languages languages = {} try: import serpent languages['serpent'] = serpent except ImportError: pass from ethereum.tools._solidity import get_solidity _solidity = get_solidity() if _solidity:
from mk_sendmany import mk_multisend_code, get_multisend_gas from ethereum.tools import tester2 from ethereum import utils # from ethereum.slogging import get_logger, configure_logging # logger = get_logger() # configure_logging(':trace') c = tester2.Chain() args = {utils.int_to_addr(10000 + i**3): i**3 for i in range(1, 101)} c.tx(to=b'', value=sum(args.values()), data=mk_multisend_code(args), startgas=get_multisend_gas(args), gasprice=20 * 10**9) for addr, value in args.items(): assert c.head_state.get_balance(addr) == value print("Test successful")
def test_init(self): assert self.s.block.get_code(self.c.address) != '' assert utils.int_to_addr(self.s.block.get_storage_data(self.c.address, 0)) == tester.a0
METROPOLIS_STATEROOT_STORE=0x10, METROPOLIS_BLOCKHASH_STORE=0x20, METROPOLIS_WRAPAROUND=65536, METROPOLIS_GETTER_CODE=decode_hex('6000355460205260206020f3'), METROPOLIS_DIFF_ADJUSTMENT_CUTOFF=9, # Constantinople fork CONSTANTINOPLE_FORK_BLKNUM=2**100, # DAO fork DAO_FORK_BLKNUM=1920000, DAO_FORK_BLKHASH=decode_hex( '4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb'), DAO_FORK_BLKEXTRA=decode_hex('64616f2d686172642d666f726b'), DAO_WITHDRAWER=utils.normalize_address( '0xbf4ed7b27f1d666546e30d74d50d173d20bca754'), # Anti-DoS fork ANTI_DOS_FORK_BLKNUM=2463000, SPURIOUS_DRAGON_FORK_BLKNUM=2675000, CONTRACT_CODE_SIZE_LIMIT=0x6000, # Default consensus strategy: ethash, poa, casper, pbft CONSENSUS_STRATEGY='ethash', # Serenity fork SERENITY_FORK_BLKNUM=2**99, PREV_HEADER_DEPTH=256, SYSTEM_ENTRY_POINT=utils.int_to_addr(2**160 - 2), SERENITY_HEADER_VERIFIER=utils.int_to_addr(255), SERENITY_HEADER_POST_FINALIZER=utils.int_to_addr(254), SERENITY_GETTER_CODE=decode_hex( '60ff331436604014161560155760203560003555005b6000355460205260206020f3'), # Custom specials CUSTOM_SPECIALS={}, )
class EventNAC(nc.NativeABIContract): address = utils.int_to_addr(2005) events = [Shout] def afunc(ctx, a='uint16', b='uint16', returns=None): ctx.Shout(a, b, 3)
from ethereum.tools import tester as t from ethereum import utils, common, transactions, abi from casper_initiating_transactions import mk_initializers, casper_config, \ viper_rlp_decoder_address, sig_hasher_address, purity_checker_address, casper_abi, purity_checker_abi from viper import compiler import serpent from ethereum.slogging import LogRecorder, configure_logging, set_level config_string = ':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace,eth.vm.exit:trace,eth.pb.msg:trace,eth.pb.tx:debug' #configure_logging(config_string=config_string) import rlp alloc = {} for i in range(9): alloc[utils.int_to_addr(i)] = {'balance': 1} alloc[t.a0] = {'balance': 10**22} alloc[t.a1] = {'balance': 10**22} s = t.Chain(alloc=alloc) t.languages['viper'] = compiler.Compiler() t.gas_limit = 9999999 t.STARTGAS = 2000000 s.mine(1) EPOCH_LENGTH = casper_config["epoch_length"] code_template = """ ~calldatacopy(0, 0, 128) ~call(3000, 1, 0, 0, 128, 0, 32) return(~mload(0) == %s) """ def mk_validation_code(address):
def get_finalizer_code(): global _finalizer_code if not _finalizer_code: import serpent _finalizer_code = get_contract_code( serpent.compile(open(finalizer_path).read())) return _finalizer_code # The Casper-specific config declaration casper_config = copy.deepcopy(default_config) casper_config['HOMESTEAD_FORK_BLKNUM'] = 0 casper_config['METROPOLIS_FORK_BLKNUM'] = 0 casper_config['SERENITY_FORK_BLKNUM'] = 0 # config['CASPER_ADDR'] == config['SERENITY_HEADER_VERIFIER'] casper_config['CASPER_ADDR'] = utils.int_to_addr(255) casper_config['RLP_DECODER_ADDR'] = utils.int_to_addr(253) casper_config['HASH_WITHOUT_BLOOM_ADDR'] = utils.int_to_addr(252) casper_config['MAX_UNCLE_DEPTH'] = 0 casper_config['PREV_HEADER_DEPTH'] = 1 casper_config['CONSENSUS_STRATEGY'] = 'casper' _casper_ct = None def get_casper_ct(): import serpent global _casper_ct if not _casper_ct: _casper_ct = abi.ContractTranslator( serpent.mk_full_signature(open(casper_path).read()))
def vm_execute(ext, msg, code): # precompute trace flag # if we trace vm, we're in slow mode anyway trace_vm = log_vm_op.is_active('trace') compustate = Compustate(gas=msg.gas) stk = compustate.stack mem = compustate.memory if code in code_cache: processed_code = code_cache[code] else: processed_code = preprocess_code(code) code_cache[code] = processed_code # print(processed_code.keys(), code) codelen = len(code) s = time.time() steps = 0 _prevop = None # for trace only while compustate.pc in processed_code: ops, minstack, maxstack, totgas, nextpos = processed_code[ compustate.pc] if len(compustate.stack) < minstack: return vm_exception('INSUFFICIENT STACK') if len(compustate.stack) > maxstack: return vm_exception('STACK SIZE LIMIT EXCEEDED') if totgas > compustate.gas: return vm_exception('OUT OF GAS %d %d' % (totgas, compustate.gas)) jumped = False compustate.gas -= totgas compustate.pc = nextpos # Invalid operation; can only come at the end of a chunk if ops[-1][0] == 'INVALID': return vm_exception('INVALID OP', opcode=ops[-1][1]) for op, opcode, pushval in ops: if trace_vm: """ This diverges from normal logging, as we use the logging namespace only to decide which features get logged in 'eth.vm.op' i.e. tracing can not be activated by activating a sub like 'eth.vm.op.stack' """ trace_data = {} trace_data['stack'] = list( map(to_string, list(compustate.stack))) if _prevop in ('MLOAD', 'MSTORE', 'MSTORE8', 'SHA3', 'CALL', 'CALLCODE', 'CREATE', 'CALLDATACOPY', 'CODECOPY', 'EXTCODECOPY'): if len(compustate.memory) < 1024: trace_data['memory'] = \ ''.join([encode_hex(ascii_chr(x)) for x in compustate.memory]) else: trace_data['sha3memory'] = \ encode_hex(utils.sha3(b''.join([ascii_chr(x) for x in compustate.memory]))) if _prevop in ('SSTORE', ) or steps == 0: trace_data['storage'] = ext.log_storage(msg.to) trace_data['gas'] = to_string(compustate.gas + totgas) trace_data['inst'] = opcode trace_data['pc'] = to_string(compustate.pc - 1) if steps == 0: trace_data['depth'] = msg.depth trace_data['address'] = msg.to trace_data['steps'] = steps trace_data['depth'] = msg.depth if op[:4] == 'PUSH': trace_data['pushvalue'] = pushval log_vm_op.trace('vm', op=op, **trace_data) steps += 1 _prevop = op # Valid operations # Pushes first because they are very frequent if 0x60 <= opcode <= 0x7f: # compustate.pc += opcode - 0x5f # Move 1 byte forward for # 0x60, up to 32 bytes for 0x7f stk.append(pushval) elif opcode < 0x10: if op == 'STOP': return peaceful_exit('STOP', compustate.gas, []) elif op == 'ADD': stk.append((stk.pop() + stk.pop()) & TT256M1) elif op == 'SUB': stk.append((stk.pop() - stk.pop()) & TT256M1) elif op == 'MUL': stk.append((stk.pop() * stk.pop()) & TT256M1) elif op == 'DIV': s0, s1 = stk.pop(), stk.pop() stk.append(0 if s1 == 0 else s0 // s1) elif op == 'MOD': s0, s1 = stk.pop(), stk.pop() stk.append(0 if s1 == 0 else s0 % s1) elif op == 'SDIV': s0, s1 = utils.to_signed(stk.pop()), utils.to_signed( stk.pop()) stk.append(0 if s1 == 0 else (abs(s0) // abs(s1) * (-1 if s0 * s1 < 0 else 1)) & TT256M1) elif op == 'SMOD': s0, s1 = utils.to_signed(stk.pop()), utils.to_signed( stk.pop()) stk.append(0 if s1 == 0 else (abs(s0) % abs(s1) * (-1 if s0 < 0 else 1)) & TT256M1) elif op == 'ADDMOD': s0, s1, s2 = stk.pop(), stk.pop(), stk.pop() stk.append((s0 + s1) % s2 if s2 else 0) elif op == 'MULMOD': s0, s1, s2 = stk.pop(), stk.pop(), stk.pop() stk.append((s0 * s1) % s2 if s2 else 0) elif op == 'EXP': base, exponent = stk.pop(), stk.pop() # fee for exponent is dependent on its bytes # calc n bytes to represent exponent nbytes = len(utils.encode_int(exponent)) expfee = nbytes * opcodes.GEXPONENTBYTE if ext.post_clearing_hardfork(): expfee += opcodes.EXP_SUPPLEMENTAL_GAS * nbytes if compustate.gas < expfee: compustate.gas = 0 return vm_exception('OOG EXPONENT') compustate.gas -= expfee stk.append(pow(base, exponent, TT256)) elif op == 'SIGNEXTEND': s0, s1 = stk.pop(), stk.pop() if s0 <= 31: testbit = s0 * 8 + 7 if s1 & (1 << testbit): stk.append(s1 | (TT256 - (1 << testbit))) else: stk.append(s1 & ((1 << testbit) - 1)) else: stk.append(s1) elif opcode < 0x20: if op == 'LT': stk.append(1 if stk.pop() < stk.pop() else 0) elif op == 'GT': stk.append(1 if stk.pop() > stk.pop() else 0) elif op == 'SLT': s0, s1 = utils.to_signed(stk.pop()), utils.to_signed( stk.pop()) stk.append(1 if s0 < s1 else 0) elif op == 'SGT': s0, s1 = utils.to_signed(stk.pop()), utils.to_signed( stk.pop()) stk.append(1 if s0 > s1 else 0) elif op == 'EQ': stk.append(1 if stk.pop() == stk.pop() else 0) elif op == 'ISZERO': stk.append(0 if stk.pop() else 1) elif op == 'AND': stk.append(stk.pop() & stk.pop()) elif op == 'OR': stk.append(stk.pop() | stk.pop()) elif op == 'XOR': stk.append(stk.pop() ^ stk.pop()) elif op == 'NOT': stk.append(TT256M1 - stk.pop()) elif op == 'BYTE': s0, s1 = stk.pop(), stk.pop() if s0 >= 32: stk.append(0) else: stk.append((s1 // 256**(31 - s0)) % 256) elif opcode < 0x40: if op == 'SHA3': s0, s1 = stk.pop(), stk.pop() compustate.gas -= opcodes.GSHA3WORD * \ (utils.ceil32(s1) // 32) if compustate.gas < 0: return vm_exception('OOG PAYING FOR SHA3') if not mem_extend(mem, compustate, op, s0, s1): return vm_exception('OOG EXTENDING MEMORY') data = bytearray_to_bytestr(mem[s0:s0 + s1]) stk.append(utils.big_endian_to_int(utils.sha3(data))) elif op == 'ADDRESS': stk.append(utils.coerce_to_int(msg.to)) elif op == 'BALANCE': if ext.post_anti_dos_hardfork(): if not eat_gas(compustate, opcodes.BALANCE_SUPPLEMENTAL_GAS): return vm_exception("OUT OF GAS") addr = utils.coerce_addr_to_hex(stk.pop() % 2**160) stk.append(ext.get_balance(addr)) elif op == 'ORIGIN': stk.append(utils.coerce_to_int(ext.tx_origin)) elif op == 'CALLER': stk.append(utils.coerce_to_int(msg.sender)) elif op == 'CALLVALUE': stk.append(msg.value) elif op == 'CALLDATALOAD': stk.append(msg.data.extract32(stk.pop())) elif op == 'CALLDATASIZE': stk.append(msg.data.size) elif op == 'CALLDATACOPY': mstart, dstart, size = stk.pop(), stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, mstart, size): return vm_exception('OOG EXTENDING MEMORY') if not data_copy(compustate, size): return vm_exception('OOG COPY DATA') msg.data.extract_copy(mem, mstart, dstart, size) elif op == 'CODESIZE': stk.append(len(code)) elif op == 'CODECOPY': mstart, dstart, size = stk.pop(), stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, mstart, size): return vm_exception('OOG EXTENDING MEMORY') if not data_copy(compustate, size): return vm_exception('OOG COPY DATA') for i in range(size): if dstart + i < len(code): mem[mstart + i] = utils.safe_ord(code[dstart + i]) else: mem[mstart + i] = 0 elif op == 'RETURNDATACOPY': mstart, dstart, size = stk.pop(), stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, mstart, size): return vm_exception('OOG EXTENDING MEMORY') if not data_copy(compustate, size): return vm_exception('OOG COPY DATA') if dstart + size > len(compustate.last_returned): return vm_exception('RETURNDATACOPY out of range') mem[mstart:mstart + size] = compustate.last_returned elif op == 'RETURNDATASIZE': stk.append(len(compustate.last_returned)) elif op == 'GASPRICE': stk.append(ext.tx_gasprice) elif op == 'EXTCODESIZE': if ext.post_anti_dos_hardfork(): if not eat_gas(compustate, opcodes.EXTCODELOAD_SUPPLEMENTAL_GAS): return vm_exception("OUT OF GAS") addr = utils.coerce_addr_to_hex(stk.pop() % 2**160) stk.append(len(ext.get_code(addr) or b'')) elif op == 'EXTCODECOPY': if ext.post_anti_dos_hardfork(): if not eat_gas(compustate, opcodes.EXTCODELOAD_SUPPLEMENTAL_GAS): return vm_exception("OUT OF GAS") addr = utils.coerce_addr_to_hex(stk.pop() % 2**160) start, s2, size = stk.pop(), stk.pop(), stk.pop() extcode = ext.get_code(addr) or b'' assert utils.is_string(extcode) if not mem_extend(mem, compustate, op, start, size): return vm_exception('OOG EXTENDING MEMORY') if not data_copy(compustate, size): return vm_exception('OOG COPY DATA') for i in range(size): if s2 + i < len(extcode): mem[start + i] = utils.safe_ord(extcode[s2 + i]) else: mem[start + i] = 0 elif opcode < 0x50: if op == 'BLOCKHASH': if ext.post_metropolis_hardfork() and False: bh_addr = ext.blockhash_store stk.append(ext.get_storage_data(bh_addr, stk.pop())) else: stk.append( utils.big_endian_to_int(ext.block_hash(stk.pop()))) elif op == 'COINBASE': stk.append(utils.big_endian_to_int(ext.block_coinbase)) elif op == 'TIMESTAMP': stk.append(ext.block_timestamp) elif op == 'NUMBER': stk.append(ext.block_number) elif op == 'DIFFICULTY': stk.append(ext.block_difficulty) elif op == 'GASLIMIT': stk.append(ext.block_gas_limit) elif opcode < 0x60: if op == 'POP': stk.pop() elif op == 'MLOAD': s0 = stk.pop() if not mem_extend(mem, compustate, op, s0, 32): return vm_exception('OOG EXTENDING MEMORY') stk.append(utils.bytes_to_int(mem[s0:s0 + 32])) elif op == 'MSTORE': s0, s1 = stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, s0, 32): return vm_exception('OOG EXTENDING MEMORY') mem[s0:s0 + 32] = utils.encode_int32(s1) elif op == 'MSTORE8': s0, s1 = stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, s0, 1): return vm_exception('OOG EXTENDING MEMORY') mem[s0] = s1 % 256 elif op == 'SLOAD': if ext.post_anti_dos_hardfork(): if not eat_gas(compustate, opcodes.SLOAD_SUPPLEMENTAL_GAS): return vm_exception("OUT OF GAS") stk.append(ext.get_storage_data(msg.to, stk.pop())) elif op == 'SSTORE': s0, s1 = stk.pop(), stk.pop() if msg.static: return vm_exception( 'Cannot SSTORE inside a static context') if ext.get_storage_data(msg.to, s0): gascost = opcodes.GSTORAGEMOD if s1 else opcodes.GSTORAGEKILL refund = 0 if s1 else opcodes.GSTORAGEREFUND else: gascost = opcodes.GSTORAGEADD if s1 else opcodes.GSTORAGEMOD refund = 0 if compustate.gas < gascost: return vm_exception('OUT OF GAS') compustate.gas -= gascost # adds neg gascost as a refund if below zero ext.add_refund(refund) ext.set_storage_data(msg.to, s0, s1) elif op == 'JUMP': compustate.pc = stk.pop() opnew = code[ compustate.pc] if compustate.pc < codelen else 0 jumped = True if opnew != JUMPDEST: return vm_exception('BAD JUMPDEST') elif op == 'JUMPI': s0, s1 = stk.pop(), stk.pop() if s1: compustate.pc = s0 opnew = code[ compustate.pc] if compustate.pc < codelen else 0 jumped = True if opnew != JUMPDEST: return vm_exception('BAD JUMPDEST') elif op == 'PC': stk.append(compustate.pc - 1) elif op == 'MSIZE': stk.append(len(mem)) elif op == 'GAS': stk.append(compustate.gas) # AFTER subtracting cost 1 elif op[:3] == 'DUP': # 0x7f - opcode is a negative number, -1 for 0x80 ... -16 for # 0x8f stk.append(stk[0x7f - opcode]) elif op[:4] == 'SWAP': # 0x8e - opcode is a negative number, -2 for 0x90 ... -17 for # 0x9f temp = stk[0x8e - opcode] stk[0x8e - opcode] = stk[-1] stk[-1] = temp elif op[:3] == 'LOG': """ 0xa0 ... 0xa4, 32/64/96/128/160 + len(data) gas a. Opcodes LOG0...LOG4 are added, takes 2-6 stack arguments MEMSTART MEMSZ (TOPIC1) (TOPIC2) (TOPIC3) (TOPIC4) b. Logs are kept track of during tx execution exactly the same way as suicides (except as an ordered list, not a set). Each log is in the form [address, [topic1, ... ], data] where: * address is what the ADDRESS opcode would output * data is mem[MEMSTART: MEMSTART + MEMSZ] * topics are as provided by the opcode c. The ordered list of logs in the transaction are expressed as [log0, log1, ..., logN]. """ depth = int(op[3:]) mstart, msz = stk.pop(), stk.pop() topics = [stk.pop() for x in range(depth)] compustate.gas -= msz * opcodes.GLOGBYTE if msg.static: return vm_exception('Cannot LOG inside a static context') if not mem_extend(mem, compustate, op, mstart, msz): return vm_exception('OOG EXTENDING MEMORY') data = bytearray_to_bytestr(mem[mstart:mstart + msz]) ext.log(msg.to, topics, data) log_log.trace('LOG', to=msg.to, topics=topics, data=list(map(utils.safe_ord, data))) # print('LOG', msg.to, topics, list(map(ord, data))) elif op == 'CREATE': value, mstart, msz = stk.pop(), stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, mstart, msz): return vm_exception('OOG EXTENDING MEMORY') if msg.static: return vm_exception( 'Cannot CREATE inside a static context') if ext.get_balance(msg.to) >= value and msg.depth < MAX_DEPTH: cd = CallData(mem, mstart, msz) ingas = compustate.gas if ext.post_anti_dos_hardfork(): ingas = all_but_1n(ingas, opcodes.CALL_CHILD_LIMIT_DENOM) create_msg = Message(msg.to, b'', value, ingas, cd, msg.depth + 1) o, gas, addr = ext.create(create_msg) if o: stk.append(utils.coerce_to_int(addr)) else: stk.append(0) compustate.gas = compustate.gas - ingas + gas else: stk.append(0) elif op in ('CALL', 'CALLCODE', 'DELEGATECALL', 'STATICCALL'): # Pull arguments from the stack if op in ('CALL', 'CALLCODE'): gas, to, value, meminstart, meminsz, memoutstart, memoutsz = \ stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop() else: gas, to, meminstart, meminsz, memoutstart, memoutsz = \ stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop() value = 0 # Static context prohibition if msg.static and value > 0: return vm_exception( 'Cannot make a non-zero-value call inside a static context' ) # Expand memory if not mem_extend(mem, compustate, op, meminstart, meminsz) or \ not mem_extend(mem, compustate, op, memoutstart, memoutsz): return vm_exception('OOG EXTENDING MEMORY') to = utils.int_to_addr(to) # Extra gas costs based on hard fork-dependent factors extra_gas = (not ext.account_exists(to)) * (op == 'CALL') * (value > 0 or not ext.post_clearing_hardfork()) * opcodes.GCALLNEWACCOUNT + \ (value > 0) * opcodes.GCALLVALUETRANSFER + \ ext.post_anti_dos_hardfork() * opcodes.CALL_SUPPLEMENTAL_GAS # Compute child gas limit if ext.post_anti_dos_hardfork(): if compustate.gas < extra_gas: return vm_exception('OUT OF GAS', needed=extra_gas) gas = min( gas, all_but_1n(compustate.gas - extra_gas, opcodes.CALL_CHILD_LIMIT_DENOM)) else: if compustate.gas < gas + extra_gas: return vm_exception('OUT OF GAS', needed=gas + extra_gas) submsg_gas = gas + opcodes.GSTIPEND * (value > 0) # Verify that there is sufficient balance and depth if ext.get_balance(msg.to) < value or msg.depth >= MAX_DEPTH: compustate.gas -= (gas + extra_gas - submsg_gas) stk.append(0) else: # Subtract gas from parent compustate.gas -= (gas + extra_gas) assert compustate.gas >= 0 cd = CallData(mem, meminstart, meminsz) # Generate the message if op == 'CALL': call_msg = Message(msg.to, to, value, submsg_gas, cd, msg.depth + 1, code_address=to, static=msg.static) elif ext.post_homestead_hardfork( ) and op == 'DELEGATECALL': call_msg = Message(msg.sender, msg.to, msg.value, submsg_gas, cd, msg.depth + 1, code_address=to, transfers_value=False, static=msg.static) elif op == 'DELEGATECALL': return vm_exception('OPCODE INACTIVE') elif op == 'CALLCODE': call_msg = Message(msg.to, msg.to, value, submsg_gas, cd, msg.depth + 1, code_address=to, static=msg.static) elif op == 'STATICCALL': call_msg = Message(msg.to, to, value, submsg_gas, cd, msg.depth + 1, code_address=to, static=True) else: raise Exception("Lolwut") # Get result result, gas, data = ext.msg(call_msg) if result == 0: stk.append(0) else: stk.append(1) # Set output memory for i in range(min(len(data), memoutsz)): mem[memoutstart + i] = data[i] compustate.gas += gas compustate.last_returned = bytearray(data) elif op == 'RETURN': s0, s1 = stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, s0, s1): return vm_exception('OOG EXTENDING MEMORY') return peaceful_exit('RETURN', compustate.gas, mem[s0:s0 + s1]) elif op == 'REVERT': if not ext.post_metropolis_hardfork(): return vm_exception('Opcode not yet enabled') s0, s1 = stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, s0, s1): return vm_exception('OOG EXTENDING MEMORY') return revert(compustate.gas, mem[s0:s0 + s1]) elif op == 'SUICIDE': if msg.static: return vm_exception( 'Cannot SUICIDE inside a static context') to = utils.encode_int(stk.pop()) to = ((b'\x00' * (32 - len(to))) + to)[12:] xfer = ext.get_balance(msg.to) if ext.post_anti_dos_hardfork(): extra_gas = opcodes.SUICIDE_SUPPLEMENTAL_GAS + \ (not ext.account_exists( to)) * (xfer > 0 or not ext.post_clearing_hardfork()) * opcodes.GCALLNEWACCOUNT if not eat_gas(compustate, extra_gas): return vm_exception("OUT OF GAS") ext.set_balance(to, ext.get_balance(to) + xfer) ext.set_balance(msg.to, 0) ext.add_suicide(msg.to) log_msg.debug('SUICIDING', addr=utils.checksum_encode(msg.to), to=utils.checksum_encode(to), xferring=xfer) return 1, compustate.gas, [] # assert utils.is_numeric(compustate.gas) # this is slow! # for a in stk: # assert is_numeric(a), (op, stk) # assert a >= 0 and a < 2**256, (a, op, stk) # if not jumped: # assert compustate.pc == nextpos # compustate.pc = nextpos if compustate.pc >= codelen: return peaceful_exit('CODE OUT OF RANGE', compustate.gas, []) return vm_exception('INVALID JUMP')
class EchoContract(nc.NativeContractBase): address = utils.int_to_addr(2000) def _safe_call(self): res, gas, data = 1, self._msg.gas, self._msg.data.data return res, gas, data
class TestTSC(nc.TypedStorageContract): address = utils.int_to_addr(2050) a = nc.Scalar('uint32') b = nc.List('uint16') c = nc.Dict('uint32') d = nc.IterableDict('uint256') e = nc.IterableDict('string') def _safe_call(ctx): # skalar assert ctx.a == 0 ctx.a = 1 assert ctx.a == 1 ctx.a = 2 assert ctx.a == 2 # list assert isinstance(ctx.b, nc.List) ctx.b[0] = 10 assert ctx.b[0] == 10 ctx.b[1000] = 12 assert ctx.b[1000] == 12 assert len(ctx.b) == 1001 ctx.b[1000] = 66 assert ctx.b[1000] == 66 assert len(ctx.b) == 1001 ctx.b.append(99) assert len(ctx.b) == 1002 ctx.b.append(99) assert len(ctx.b) == 1003 # mapping assert isinstance(ctx.c, nc.Dict) key = b'test' assert ctx.c[key] == 0 ctx.c[key] = 33 assert ctx.c[key] == 33 ctx.c[key] = 66 assert ctx.c[key] == 66 k = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17q' v = 2146209080 ctx.c[k] = v assert ctx.c[k] == v # iterable dict ctx.d[k] = v assert len(ctx.d) == 1 assert ctx.d[k] == v ctx.d[k] = 0 N = 10 for i in range(1, N + 1): v = i**2 k = bytes(i) ctx.d[k] = v assert ctx.d[k] == v assert len(list(ctx.d.keys())) == i assert set(ctx.d.keys()) == set( [bytes(j) for j in range(1, i + 1)]) assert set(ctx.d.values()) == set( [j**2 for j in range(1, i + 1)]) # iterable dict with strings N = 10 for i in range(1, N + 1): v = str(i**2) k = bytes(i) ctx.e[k] = v # log.DEV('kv', k=k, v=v) assert ctx.e[k] == v, ctx.e[k] assert len(list(ctx.e.keys())) == i assert set(ctx.e.keys()) == set( [bytes(j) for j in range(1, i + 1)]) assert set(ctx.e.values()) == set( [str(j**2) for j in range(1, i + 1)]) print list(ctx.e.keys()) print list(ctx.e.values()) print len(list(ctx.e.keys())) return 1, 1, []
class SampleNAC(nc.NativeABIContract): address = utils.int_to_addr(2001) def initialize(ctx, a='int8', c='bool', d='uint8[]'): "Constructor (can a constructor return anything?)" def afunc(ctx, a='uint16', b='uint16', returns='uint16'): return a * b def bfunc(ctx, a='uint16', returns='uint16'): return ctx.afunc(a, 2) # direct native call def cfunc(ctx, a='uint16', returns=['uint16', 'uint16']): return a, a # returns tuple def ccfunc(ctx, a='uint16', returns=['uint16']): return [a] def dfunc(ctx, a='uint16[2]', returns='uint16'): # FAILS return a[0] * a[1] def efunc(ctx, a='uint16[]', returns='uint16'): return a[0] * a[1] def ffunc(ctx, returns='uint16[2]'): return [1, 2] def ffunc2(ctx, returns=['uint16[2]']): return [[1, 2]] def gfunc(ctx, returns='address[]'): return ['\x00' * 20] * 3 def void_func(ctx, a='uint16', returns=None): return def noargs_func(ctx, returns='uint16'): return 42 def add_property(ctx, returns=None): ctx.dummy = True # must fail def special_vars(ctx, returns=None): def _is_address(a): return isinstance(a, bytes) and len(a) == 20 assert ctx.msg_data assert _is_address(ctx.msg_sender) assert ctx.msg_value == 0 assert ctx.tx_gasprice assert _is_address(ctx.tx_origin) assert _is_address(ctx.block_coinbase) assert ctx.block_difficulty assert ctx.block_number == 0 assert ctx.block_gaslimit assert 0 == ctx.get_balance(ctx.address) assert _is_address(ctx.address) assert ctx.balance == 0 assert ctx.balance == ctx.get_balance(ctx.address) if ctx.block_number > 0: assert ctx.get_block_hash(ctx.block_number - 1) == ctx.block_prevhash def test_suicide(ctx, returns=None): ctx.suicide(ctx.block_coinbase) def get_address(ctx, returns='string'): return ctx.address
def test_init_market(self): self.init_market() assert utils.int_to_addr(self.m.first_currency()) == self.c1.address assert utils.int_to_addr(self.m.second_currency()) == self.c2.address
DAO_FORK_BLKHASH=decode_hex( '4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb'), DAO_FORK_BLKEXTRA=decode_hex('64616f2d686172642d666f726b'), CHILD_DAO_LIST=list(map(utils.normalize_address, child_dao_list)), DAO_WITHDRAWER=utils.normalize_address( '0xbf4ed7b27f1d666546e30d74d50d173d20bca754'), # Anti-DoS fork ANTI_DOS_FORK_BLKNUM=2463000, SPURIOUS_DRAGON_FORK_BLKNUM=2675000, CONTRACT_CODE_SIZE_LIMIT=0x6000, # Default consensus strategy: ethash, poa, casper, pbft CONSENSUS_STRATEGY='ethash', # Serenity fork SERENITY_FORK_BLKNUM=2**99, PREV_HEADER_DEPTH=256, SYSTEM_ENTRY_POINT=utils.int_to_addr(2**160 - 2), SERENITY_HEADER_VERIFIER=utils.int_to_addr(255), SERENITY_HEADER_POST_FINALIZER=utils.int_to_addr(254), SERENITY_GETTER_CODE=decode_hex( '60ff331436604014161560155760203560003555005b6000355460205260206020f3' ), # Custom specials CUSTOM_SPECIALS={}, ) assert default_config['NEPHEW_REWARD'] == \ default_config['BLOCK_REWARD'] // 32 class Env(object): def __init__(self, db=None, config=None, global_config=None): self.db = EphemDB() if db is None else db
def test_init(self): assert self.s.block.get_code(self.c.address) != '' assert utils.int_to_addr( self.s.block.get_storage_data(self.c.address, 0)) == tester.a0 assert self.c.size() == 0 assert self.c.top() == 0