Add new features

add/feats
Nikhil Parasaram 9 months ago
parent 13969337fd
commit e881b855fb
  1. 2
      mythril/analysis/symbolic.py
  2. 1
      mythril/concolic/concolic_execution.py
  3. 10
      mythril/concolic/find_trace.py
  4. 1
      mythril/interfaces/cli.py
  5. 2
      mythril/laser/plugin/plugins/__init__.py
  6. 1
      mythril/laser/plugin/plugins/coverage_metrics/__init__.py
  7. 1
      mythril/laser/plugin/plugins/coverage_metrics/constants.py
  8. 73
      mythril/laser/plugin/plugins/coverage_metrics/coverage_data.py
  9. 131
      mythril/laser/plugin/plugins/coverage_metrics/metrics_plugin.py
  10. 48
      mythril/laser/plugin/plugins/trace.py
  11. 240
      tests/concolic/concolic_tests.py
  12. 19
      tests/integration_tests/coverage_metrics_test.py
  13. 54
      tests/testdata/concolic_io/multi_contract_example.sol
  14. 108
      tests/testdata/concolic_io/multi_contract_example_input.json
  15. 25
      tests/testdata/concolic_io/multiple_example.sol
  16. 48
      tests/testdata/concolic_io/multiple_example_input.json
  17. 19
      tests/testdata/concolic_io/simple_example.sol
  18. 48
      tests/testdata/concolic_io/simple_example_input.json
  19. 42
      tests/testdata/concolic_io/two_contract.sol
  20. 78
      tests/testdata/concolic_io/two_contract_input.json
  21. 1
      tests/testdata/inputs/coverage.sol.o

@ -24,6 +24,7 @@ from mythril.laser.plugin.plugins import (
MutationPrunerBuilder, MutationPrunerBuilder,
DependencyPrunerBuilder, DependencyPrunerBuilder,
CoveragePluginBuilder, CoveragePluginBuilder,
CoverageMetricsPluginBuilder,
CallDepthLimitBuilder, CallDepthLimitBuilder,
InstructionProfilerBuilder, InstructionProfilerBuilder,
SymbolicSummaryPluginBuilder, SymbolicSummaryPluginBuilder,
@ -143,6 +144,7 @@ class SymExecWrapper:
) )
plugin_loader = LaserPluginLoader() plugin_loader = LaserPluginLoader()
plugin_loader.load(CoverageMetricsPluginBuilder())
if not args.disable_coverage_strategy: if not args.disable_coverage_strategy:
plugin_loader.load(CoveragePluginBuilder()) plugin_loader.load(CoveragePluginBuilder())
if not args.disable_mutation_pruner: if not args.disable_mutation_pruner:

@ -74,7 +74,6 @@ def concolic_execution(
:param solver_timeout: Solver timeout :param solver_timeout: Solver timeout
""" """
init_state, trace = concrete_execution(concrete_data) init_state, trace = concrete_execution(concrete_data)
args.solver_timeout = solver_timeout args.solver_timeout = solver_timeout
output_list = flip_branches( output_list = flip_branches(

@ -12,11 +12,13 @@ from mythril.laser.ethereum.svm import LaserEVM
from mythril.laser.ethereum.state.world_state import WorldState from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.time_handler import time_handler from mythril.laser.ethereum.time_handler import time_handler
from mythril.laser.plugin.plugins import TraceFinderBuilder
from mythril.laser.ethereum.transaction.concolic import execute_transaction from mythril.laser.ethereum.transaction.concolic import execute_transaction
from mythril.laser.plugin.loader import LaserPluginLoader from mythril.laser.plugin.loader import LaserPluginLoader
from mythril.laser.smt import Expression, BitVec, symbol_factory from mythril.laser.smt import Expression, BitVec, symbol_factory
from mythril.laser.ethereum.transaction.transaction_models import tx_id_manager from mythril.laser.ethereum.transaction.transaction_models import tx_id_manager
from mythril.plugin.discovery import PluginDiscovery from mythril.plugin.discovery import PluginDiscovery
from mythril.support.support_args import args
def setup_concrete_initial_state(concrete_data: ConcreteData) -> WorldState: def setup_concrete_initial_state(concrete_data: ConcreteData) -> WorldState:
@ -30,12 +32,11 @@ def setup_concrete_initial_state(concrete_data: ConcreteData) -> WorldState:
account = Account(address, concrete_storage=True) account = Account(address, concrete_storage=True)
account.code = Disassembly(details["code"][2:]) account.code = Disassembly(details["code"][2:])
account.nonce = details["nonce"] account.nonce = details["nonce"]
if isinstance(type(details["storage"]), str): if isinstance(details["storage"], str):
details["storage"] = eval(details["storage"]) # type: ignore details["storage"] = eval(details["storage"]) # type: ignore
for key, value in details["storage"].items(): for key, value in details["storage"].items():
key_bitvec = symbol_factory.BitVecVal(int(key, 16), 256) key_bitvec = symbol_factory.BitVecVal(int(key, 16), 256)
account.storage[key_bitvec] = symbol_factory.BitVecVal(int(value, 16), 256) account.storage[key_bitvec] = symbol_factory.BitVecVal(int(value, 16), 256)
world_state.put_account(account) world_state.put_account(account)
account.set_balance(int(details["balance"], 16)) account.set_balance(int(details["balance"], 16))
return world_state return world_state
@ -47,16 +48,15 @@ def concrete_execution(concrete_data: ConcreteData) -> Tuple[WorldState, List]:
:param concrete_data: Concrete data :param concrete_data: Concrete data
:return: path trace :return: path trace
""" """
args.pruning_factor = 1
tx_id_manager.restart_counter() tx_id_manager.restart_counter()
init_state = setup_concrete_initial_state(concrete_data) init_state = setup_concrete_initial_state(concrete_data)
laser_evm = LaserEVM(execution_timeout=1000) laser_evm = LaserEVM(execution_timeout=1000)
laser_evm.open_states = [deepcopy(init_state)] laser_evm.open_states = [deepcopy(init_state)]
plugin_loader = LaserPluginLoader() plugin_loader = LaserPluginLoader()
assert PluginDiscovery().is_installed("myth_concolic_execution") plugin_loader.load(TraceFinderBuilder())
trace_plugin = PluginDiscovery().installed_plugins["myth_concolic_execution"]()
time_handler.start_execution(laser_evm.execution_timeout) time_handler.start_execution(laser_evm.execution_timeout)
plugin_loader.load(trace_plugin)
laser_evm.time = datetime.now() laser_evm.time = datetime.now()
plugin_loader.instrument_virtual_machine(laser_evm, None) plugin_loader.instrument_virtual_machine(laser_evm, None)
for transaction in concrete_data["steps"]: for transaction in concrete_data["steps"]:

@ -300,7 +300,6 @@ def main() -> None:
) )
create_disassemble_parser(disassemble_parser) create_disassemble_parser(disassemble_parser)
if PluginDiscovery().is_installed("myth_concolic_execution"):
concolic_parser = subparsers.add_parser( concolic_parser = subparsers.add_parser(
CONCOLIC_LIST[0], CONCOLIC_LIST[0],
help="Runs concolic execution to flip the desired branches", help="Runs concolic execution to flip the desired branches",

@ -12,3 +12,5 @@ from mythril.laser.plugin.plugins.mutation_pruner import MutationPrunerBuilder
from mythril.laser.plugin.plugins.call_depth_limiter import CallDepthLimitBuilder from mythril.laser.plugin.plugins.call_depth_limiter import CallDepthLimitBuilder
from mythril.laser.plugin.plugins.instruction_profiler import InstructionProfilerBuilder from mythril.laser.plugin.plugins.instruction_profiler import InstructionProfilerBuilder
from mythril.laser.plugin.plugins.summary import SymbolicSummaryPluginBuilder from mythril.laser.plugin.plugins.summary import SymbolicSummaryPluginBuilder
from mythril.laser.plugin.plugins.trace import TraceFinderBuilder
from mythril.laser.plugin.plugins.coverage_metrics import CoverageMetricsPluginBuilder

@ -0,0 +1 @@
from .metrics_plugin import CoverageMetricsPluginBuilder

@ -0,0 +1,73 @@
import json
from typing import Dict, List
from mythril.support.support_utils import get_code_hash
from mythril.laser.execution_info import ExecutionInfo
class InstructionCoverageInfo(ExecutionInfo):
def __init__(self):
self._instruction_coverage = {} # type: Dict[str, int]
def as_dict(self):
return dict(instruction_discovery_time=self._instruction_coverage)
def get_code_instr_hex(self, code: str, instruction: int):
code_hash = get_code_hash(code)[2:]
instruction_hex = hex(instruction)[2:]
return "{}:{}".format(code_hash, instruction_hex)
def is_covered(self, code: str, instruction: int):
code_instr_hex = self.get_code_instr_hex(code, instruction)
return code_instr_hex in self._instruction_coverage
def add_data(self, code: str, instruction: int, discovery_time: int):
code_instr_hex = self.get_code_instr_hex(code, instruction)
self._instruction_coverage[code_instr_hex] = discovery_time
def output(self, filename: str):
with open(filename, "w") as outfile:
json.dump(
self._instruction_coverage, default=lambda o: o.__dict__, fp=outfile
)
class CoverageData:
def __init__(
self,
instructions_covered: int,
total_instructions: int,
branches_covered: int,
tx_id: int,
total_branches: int,
state_counter: int,
code: str,
time_elapsed: int,
):
self.instructions_covered = instructions_covered
self.total_instructions = total_instructions
self.branches_covered = branches_covered
self.tx_id = tx_id
self.total_branches = total_branches
self.state_counter = state_counter
self.code_hash = get_code_hash(code)[2:]
self.time_elapsed = time_elapsed
def as_dict(self):
return self.__dict__
class CoverageTimeSeries(ExecutionInfo):
def __init__(self):
self.coverage = [] # type: List[CoverageData]
def output(self, filename: str):
with open(filename, "w") as outfile:
json.dump(self.coverage, default=lambda o: o.__dict__, fp=outfile)
def as_dict(self):
return dict(coverage=self.coverage)
def add_data(self, *args, **kwargs):
cov_data = CoverageData(*args, **kwargs)
self.coverage.append(cov_data.as_dict())

@ -0,0 +1,131 @@
from mythril.laser.ethereum.svm import LaserEVM
from mythril.laser.plugin.interface import LaserPlugin
from mythril.laser.plugin.builder import PluginBuilder
from mythril.laser.ethereum.state.global_state import GlobalState
from .coverage_data import (
CoverageTimeSeries,
InstructionCoverageInfo,
)
from .constants import BATCH_OF_STATES
from typing import Dict, Tuple, List
import time
import logging
log = logging.getLogger(__name__)
class CoverageMetricsPluginBuilder(PluginBuilder):
"""CoveragePlugin
Checks Instruction and branch coverage and puts it to data.json file
which appears in the directory in which mythril is run.
"""
plugin_default_enabled = True
enabled = True
author = "MythX Development Team"
plugin_name = "MythX Coverage Metrics"
plugin_license = "All rights reserved."
plugin_type = "Laser Plugin"
plugin_description = (
"This plugin measures coverage throughout symbolic execution,"
" reporting it at the end in the MythX coverage format."
)
def __call__(self, *args, **kwargs):
"""Constructs the plugin"""
return LaserCoveragePlugin()
class LaserCoveragePlugin(LaserPlugin):
def __init__(self):
self.instruction_coverage_data = {} # type: Dict[str, Tuple[int, Dict[bool]]]
self.branch_possibilities = {} # type: Dict[str, Dict[int, List]]
self.tx_id = 0
self.state_counter = 0
self.coverage = CoverageTimeSeries()
self.instruction_coverage_info = InstructionCoverageInfo()
self.start_time = time.time_ns()
def initialize(self, symbolic_vm: LaserEVM) -> None:
"""Initializes the instruction coverage plugin
Introduces hooks for each instruction
:param symbolic_vm: The symbolic virtual machine to initialise this plugin for
"""
log.info("Initializing coverage metrics plugin")
self.instruction_coverage_data = {}
self.branch_possibilities = {}
self.tx_id = 0
# Add the instruction coverage ExecutionInfo to laser vm for use in reporting
symbolic_vm.execution_info.append(self.instruction_coverage_info)
symbolic_vm.execution_info.append(self.coverage)
@symbolic_vm.laser_hook("execute_state")
def execute_state_hook(global_state: GlobalState):
self._update_instruction_coverage_data(global_state)
self._update_branch_coverage_data(global_state)
self.state_counter += 1
if self.state_counter == BATCH_OF_STATES:
self._record_coverage()
self.state_counter = 0
@symbolic_vm.laser_hook("stop_sym_trans")
def execute_stop_sym_trans_hook():
self.tx_id += 1
# The following is useful for debugging
# @symbolic_vm.laser_hook("stop_sym_exec")
# def execute_stop_sym_exec_hook():
# self.coverage.output("coverage_data.json")
# self.instruction_coverage_info.output("instruction_discovery_data.json")
def _update_instruction_coverage_data(self, global_state: GlobalState):
"""Records instruction coverage"""
code = global_state.environment.code.bytecode
if code not in self.instruction_coverage_data.keys():
number_of_instructions = len(global_state.environment.code.instruction_list)
self.instruction_coverage_data[code] = (number_of_instructions, {})
current_instr = global_state.get_current_instruction()["address"]
if self.instruction_coverage_info.is_covered(code, current_instr) is False:
self.instruction_coverage_info.add_data(
code, current_instr, time.time_ns() - self.start_time
)
self.instruction_coverage_data[code][1][current_instr] = True
def _update_branch_coverage_data(self, global_state: GlobalState):
"""Records branch coverage"""
code = global_state.environment.code.bytecode
if code not in self.branch_possibilities:
self.branch_possibilities[code] = {}
if global_state.get_current_instruction()["opcode"] != "JUMPI":
return
addr = global_state.get_current_instruction()["address"]
jump_addr = global_state.mstate.stack[-1]
if jump_addr.symbolic:
log.debug("Encountered a symbolic jump, ignoring it for branch coverage")
return
self.branch_possibilities[code][addr] = [addr + 1, jump_addr.value]
def _record_coverage(self):
for code, code_cov in self.instruction_coverage_data.items():
total_branches = 0
branches_covered = 0
for jumps, branches in self.branch_possibilities[code].items():
for branch in branches:
total_branches += 1
branches_covered += branch in code_cov[1]
self.coverage.add_data(
code=code,
instructions_covered=len(code_cov[1]),
total_instructions=code_cov[0],
branches_covered=branches_covered,
tx_id=self.tx_id,
total_branches=total_branches,
state_counter=self.state_counter,
time_elapsed=time.time_ns() - self.start_time,
)

@ -0,0 +1,48 @@
from mythril.laser.plugin.interface import LaserPlugin
from mythril.laser.plugin.builder import PluginBuilder
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.svm import LaserEVM
from typing import List, Tuple
class TraceFinderBuilder(PluginBuilder):
name = "trace-finder"
plugin_default_enabled = True
enabled = True
author = "MythX Development Team"
name = "MythX Trace Finder"
plugin_license = "All rights reserved."
plugin_type = "Laser Plugin"
plugin_version = "0.0.1 "
plugin_description = "This plugin merges states after the end of a transaction"
def __call__(self, *args, **kwargs):
return TraceFinder()
class TraceFinder(LaserPlugin):
def __init__(self):
self._reset()
def _reset(self):
self.tx_trace: List[List[Tuple[int, str]]] = []
def initialize(self, symbolic_vm: LaserEVM):
"""Initializes Trace Finder
Introduces hooks during the start of the execution and each execution state
:param symbolic_vm:
:return:
"""
self._reset()
@symbolic_vm.laser_hook("start_exec")
def start_sym_trans_hook():
self.tx_trace.append([])
@symbolic_vm.laser_hook("execute_state")
def trace_jumpi_hook(global_state: GlobalState):
self.tx_trace[-1].append(
(global_state.mstate.pc, global_state.current_transaction.id)
)

@ -0,0 +1,240 @@
import binascii
import json
import pathlib
import pytest
import subprocess
from copy import deepcopy
from datetime import datetime
from mock import patch
from subprocess import check_output, CalledProcessError
from tests import BaseTestCase, PROJECT_DIR, TESTDATA
from mythril.concolic import concrete_execution
from mythril.concolic.find_trace import setup_concrete_initial_state
from mythril.disassembler.asm import disassemble
from mythril.concolic.concrete_data import ConcreteData
from mythril.laser.ethereum import util
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.svm import LaserEVM
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.time_handler import time_handler
from mythril.laser.ethereum.transaction.concolic import execute_transaction
from mythril.laser.plugin.loader import LaserPluginLoader
from mythril.laser.smt import Expression, BitVec, symbol_factory
from mythril.laser.plugin.plugins import TraceFinderBuilder
MYTH = str(PROJECT_DIR / "myth")
def output_of(command):
try:
return json.loads(check_output(command, shell=True).decode("UTF-8"))
except CalledProcessError as exc:
return json.loads(exc.output.decode("UTF-8"))
# TODO: Try using some python EVM for these tests
def validate_simple_example(output, branches):
for branch_output, branch in zip(output, branches):
if branch == "153":
# Validation for initialState
# Validation for tx steps
tx_step = branch_output["steps"][1]
assert tx_step["input"] == tx_step["calldata"]
assert int(tx_step["input"][10:], 16) == 3
def validate_multiple_example(output, branches):
for branch_output, branch in zip(output, branches):
if branch == "153":
# Validation for initialState
# Validation for tx steps
tx_step = branch_output["steps"][1]
assert tx_step["input"] == tx_step["calldata"]
assert int(tx_step["input"][10:], 16) == 3
elif branch == "192":
# Validation for initialState
# Validation for tx steps
tx_step = branch_output["steps"][1]
assert tx_step["input"] == tx_step["calldata"]
assert int(tx_step["input"][10:], 16) == 5
elif branch == "243":
# Validation for initialState
# Validation for tx steps
tx_step = branch_output["steps"][1]
assert tx_step["input"] == tx_step["calldata"]
assert int(tx_step["input"][10:], 16) == 7
def validate_two_contract(output, branches):
for branch_output, branch in zip(output, branches):
if branch == "311":
# Validation for initialState
# Validation for tx steps
assert (
int(branch_output["steps"][1]["input"][10:], 16)
+ int(branch_output["steps"][3]["input"][10:], 16)
== 11
)
if branch == "341":
# Validation for initialState
# Validation for tx steps
assert (
int(branch_output["steps"][1]["input"][10:], 16)
+ int(branch_output["steps"][3]["input"][10:], 16)
== 30
)
if branch == "371":
# Validation for initialState
# Validation for tx steps
assert (
int(branch_output["steps"][1]["input"][10:], 16)
+ int(branch_output["steps"][3]["input"][10:], 16)
== 20
)
def validate_multi_contract(output, branches):
for branch_output, branch in zip(output, branches):
if branch == "453":
# Validation for initialState
# Validation for tx steps
assert (
int(branch_output["steps"][1]["input"][10:], 16)
+ int(branch_output["steps"][3]["input"][10:], 16)
+ int(branch_output["steps"][5]["input"][10:], 16)
== 10
)
if branch == "483":
# Validation for initialState
# Validation for tx steps
assert (
int(branch_output["steps"][1]["input"][10:], 16)
+ int(branch_output["steps"][3]["input"][10:], 16)
+ int(branch_output["steps"][5]["input"][10:], 16)
== 25
)
validate_test_data = (
("simple_example_input.json", validate_simple_example, "153"),
("multiple_example_input.json", validate_multiple_example, "153,192,243"),
("two_contract_input.json", validate_two_contract, "311,341,371"),
("multi_contract_example_input.json", validate_multi_contract, "453,483"),
)
check_state_validity_test_data = (
("simple_example_input.json", "153"),
("multiple_example_input.json", "153,192,243"),
("two_contract_input.json", "311,341,371"),
("multi_contract_example_input.json", "453,483"),
)
test_data_error = (("simple_example_input.json", "508"),)
@pytest.mark.parametrize("input_file,validate_function,branches", validate_test_data)
def test_concolic_conditions(input_file, validate_function, branches):
input_path = str(TESTDATA / "concolic_io" / input_file)
command = f"{MYTH} concolic {input_path} --branches {branches}"
received_output = output_of(command)
branches = [branch for branch in branches.split(",")]
validate_function(received_output, branches)
@pytest.mark.parametrize("input_file,branch", test_data_error)
def test_concolic_error(input_file, branch):
input_path = str(TESTDATA / "concolic_io" / input_file)
command = f"{MYTH} concolic {input_path} --branches {branch}"
received_output = subprocess.run(
command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
assert (
f"The branch {branch} does not lead to a jump address, skipping this branch"
in received_output.stderr.decode("UTF-8")
)
def get_pc_from_disassembler(concrete_data, branches):
init_state = setup_concrete_initial_state(concrete_data)
laser_evm = LaserEVM(execution_timeout=100)
laser_evm.open_states = [deepcopy(init_state)]
plugin_loader = LaserPluginLoader()
trace_plugin = TraceFinderBuilder()
plugin_loader.load(trace_plugin)
laser_evm.time = datetime.now()
plugin_loader.instrument_virtual_machine(laser_evm, None)
for transaction in concrete_data["steps"][:-1]:
execute_transaction(
laser_evm,
callee_address=transaction["address"],
caller_address=symbol_factory.BitVecVal(
int(transaction["origin"], 16), 256
),
origin_address=symbol_factory.BitVecVal(
int(transaction["origin"], 16), 256
),
gas_limit=int(transaction.get("gasLimit", "0x9999999999999999999999"), 16),
data=binascii.a2b_hex(transaction["input"][2:]),
gas_price=int(transaction.get("gasPrice", "0x773594000"), 16),
value=int(transaction["value"], 16),
track_gas=False,
)
contract_addr = concrete_data["steps"][-1]["address"]
assert len(laser_evm.open_states) == 1
instruction_list = (
laser_evm.open_states[0].accounts[int(contract_addr, 16)].code.instruction_list
)
branches = [
util.get_instruction_index(instruction_list, branch) for branch in branches
]
return branches
def run_concolic(input_path, output, branches):
with open(input_path) as f:
concrete_data = json.load(f)
_, input_trace = concrete_execution(concrete_data)
input_last_tx = input_trace[-1]
branches = [int(branch) for branch in branches.split(",")]
time_handler.start_execution(1000)
branches = get_pc_from_disassembler(concrete_data, branches)
for out, branch in zip(output, branches):
_, trace = concrete_execution(out)
last_tx = trace[-1]
tx_id = last_tx[0][1]
branch_idx = last_tx.index((branch, tx_id))
input_idx = input_last_tx.index((branch, tx_id))
assert (branch_idx == input_idx) and last_tx[branch_idx + 1][
0
] != input_last_tx[branch_idx + 1][0]
@pytest.mark.parametrize("input_file,branches", check_state_validity_test_data)
def test_validate_concolic_output(input_file, branches):
input_path = str(TESTDATA / "concolic_io" / input_file)
command = f"{MYTH} concolic {input_path} --branches {branches}"
received_output = output_of(command)
run_concolic(input_path, received_output, branches)

@ -0,0 +1,19 @@
import pytest
from tests import PROJECT_DIR, TESTDATA
from utils import output_of
MYTH = str(PROJECT_DIR / "myth")
test_data = [
(open(f"{TESTDATA}/inputs/coverage.sol.o").read(), True),
]
@pytest.mark.parametrize("code, exists", test_data)
def test_basic_coverage(code, exists):
assert (
"instruction_discovery_time"
in output_of(f"{MYTH} a -c 0x{code} --solver-timeout 1000 -o jsonv2")
) == exists

@ -0,0 +1,54 @@
pragma solidity 0.8.6;
/**
* @title Storage
* @dev Store & retreive value in a variable
*/
contract D1 {
uint256 number;
function store(uint256 num) public {
number =num;
}
function retval() public returns(uint256){
return number;
}
}
contract D2 {
uint256 number;
function store(uint256 num) external {
number = num;
}
function retval() public returns(uint256){
return number;
}
}
contract D3 {
D2 d2;
D1 d1;
constructor() public
{
d1 = D1(0x0901d12ebE1b195E5AA8748E62Bd7734aE19B51F);
d2 = D2(0x384f682f4a5AbefC8795Cc38a340dE9446dFAE7A);
}
function test(uint256 num) public returns(uint256) {
uint256 sum = d1.retval() + d2.retval() + num;
if (sum == 10) {
return sum + 10;
}
else if(sum == 25) {
return sum * 2;
}
else return sum*10;
return sum;
}
}

@ -0,0 +1,108 @@
{
"initialState": {
"accounts": {
"0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe": {
"balance": "0x1000000",
"code": "",
"nonce": 0,
"storage": {}
},
"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {
"balance": "0x0",
"code": "",
"nonce": 0,
"storage": {}
}
}
},
"steps": [{
"address": "",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636057361d1461003b5780639c88345314610057575b600080fd5b6100556004803603810190610050919061009d565b610075565b005b61005f61007f565b60405161006c91906100d9565b60405180910390f35b8060008190555050565b60008054905090565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea2646970667358221220773ac8f6769c8b896b1ac993a29718d8f1463998522b37ec8e410ded6f1bd3d464736f6c63430008060033",
"name": "unknown",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
},
{
"address": "0x0901d12ebE1b195E5AA8748E62Bd7734aE19B51F",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x6057361d0000000000000000000000000000000000000000000000000000000000000001",
"name": "unknown",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
},
{
"address": "",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636057361d1461003b5780639c88345314610057575b600080fd5b6100556004803603810190610050919061009d565b610075565b005b61005f61007f565b60405161006c91906100d9565b60405180910390f35b8060008190555050565b60008054905090565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea264697066735822122046b7cc08908c1d17c2b2b523dfb5fc5a50e56068ce85f705f6f75ff54c7b16c864736f6c63430008060033",
"name": "unknown",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
},
{
"address": "0x384f682f4a5AbefC8795Cc38a340dE9446dFAE7A",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x6057361d0000000000000000000000000000000000000000000000000000000000000001",
"name": "unknown",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
},
{
"address": "",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x608060405234801561001057600080fd5b50730901d12ebe1b195e5aa8748e62bd7734ae19b51f600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555073384f682f4a5abefc8795cc38a340de9446dfae7a6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506103f7806100c96000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806329e99f0714610030575b600080fd5b61004a60048036038101906100459190610238565b610060565b60405161005791906102a1565b60405180910390f35b6000808260008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639c8834536040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156100cc57600080fd5b505af11580156100e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101049190610265565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639c8834536040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a69190610265565b6101b091906102bc565b6101ba91906102bc565b9050600a8114156101da57600a816101d291906102bc565b915050610209565b60198114156101f8576002816101f09190610312565b915050610209565b600a816102059190610312565b9150505b919050565b60008135905061021d816103aa565b92915050565b600081519050610232816103aa565b92915050565b60006020828403121561024e5761024d6103a5565b5b600061025c8482850161020e565b91505092915050565b60006020828403121561027b5761027a6103a5565b5b600061028984828501610223565b91505092915050565b61029b8161036c565b82525050565b60006020820190506102b66000830184610292565b92915050565b60006102c78261036c565b91506102d28361036c565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561030757610306610376565b5b828201905092915050565b600061031d8261036c565b91506103288361036c565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561036157610360610376565b5b828202905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b6103b38161036c565b81146103be57600080fd5b5056fea2646970667358221220f0c85d3c193689a686ebf30f33bdac178593d7fe1036cce209c44c7833209cb464736f6c63430008060033",
"name": "unknown",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
},
{
"address": "0xc538a4c3f414cbf7f78373e253c1beadd6310d45",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "0x29e99f070000000000000000000000000000000000000000000000000000000000000006",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x29e99f070000000000000000000000000000000000000000000000000000000000000006",
"name": "",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
}]
}

@ -0,0 +1,25 @@
// source of the bytecode, as a reference for the test.
pragma solidity 0.8.6;
contract Example1 {
uint256 private initialized = 0;
uint256 public count = 1;
function init() public {
initialized = 1;
}
function run(uint256 input, uint val) public {
if (val == 3) {
count += input;
}
else if(val == 5) {
count += 2 * input;
}
else if(val == 7) {
count += 10 + input;
}
else
count++;
}
}

@ -0,0 +1,48 @@
{
"initialState": {
"accounts": {
"0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe": {
"balance": "0x10000",
"code": "",
"nonce": 0,
"storage": {}
},
"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {
"balance": "0x0",
"code": "",
"nonce": 0,
"storage": {}
}
}
},
"steps": [{
"address": "",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x6080604052600080556001805534801561001857600080fd5b50610349806100286000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806306661abd146100465780637357f5d214610064578063e1c7392a14610080575b600080fd5b61004e61008a565b60405161005b91906101aa565b60405180910390f35b61007e6004803603810190610079919061015b565b610090565b005b61008861013c565b005b60015481565b60038114156100b75781600160008282546100ab91906101c5565b92505081905550610138565b60058114156100ea578160026100cd919061021b565b600160008282546100de91906101c5565b92505081905550610137565b600781141561011d5781600a61010091906101c5565b6001600082825461011191906101c5565b92505081905550610136565b600160008154809291906101309061027f565b91905055505b5b5b5050565b6001600081905550565b600081359050610155816102fc565b92915050565b60008060408385031215610172576101716102f7565b5b600061018085828601610146565b925050602061019185828601610146565b9150509250929050565b6101a481610275565b82525050565b60006020820190506101bf600083018461019b565b92915050565b60006101d082610275565b91506101db83610275565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156102105761020f6102c8565b5b828201905092915050565b600061022682610275565b915061023183610275565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561026a576102696102c8565b5b828202905092915050565b6000819050919050565b600061028a82610275565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156102bd576102bc6102c8565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b61030581610275565b811461031057600080fd5b5056fea26469706673582212202f9c24200282a71edb4cfb1018bca4a5608551f6bf5910ca1569133908c2605464736f6c63430008060033",
"name": "unknown",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
},
{
"address": "0x901d12ebe1b195e5aa8748e62bd7734ae19b51f",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "0x7357f5d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x7357f5d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"name": "run(uint256,uint256)",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
}]
}

@ -0,0 +1,19 @@
// source of the bytecode, as a reference for the test.
pragma solidity 0.8.6;
contract Example1 {
uint256 private initialized = 0;
uint256 public count = 1;
function init() public {
initialized = 1;
}
function run(uint256 input, uint val) public {
if (val == 3) {
count += input;
}
else
count++;
}
}

@ -0,0 +1,48 @@
{
"initialState": {
"accounts": {
"0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe": {
"balance": "0x10000",
"code": "",
"nonce": 0,
"storage": {}
},
"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {
"balance": "0x0",
"code": "",
"nonce": 0,
"storage": {}
}
}
},
"steps": [{
"address": "",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x6080604052600080556001805534801561001857600080fd5b50610287806100286000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806306661abd146100465780637357f5d214610064578063e1c7392a14610080575b600080fd5b61004e61008a565b60405161005b9190610142565b60405180910390f35b61007e600480360381019061007991906100f3565b610090565b005b6100886100d4565b005b60015481565b60038114156100b75781600160008282546100ab919061015d565b925050819055506100d0565b600160008154809291906100ca906101bd565b91905055505b5050565b6001600081905550565b6000813590506100ed8161023a565b92915050565b6000806040838503121561010a57610109610235565b5b6000610118858286016100de565b9250506020610129858286016100de565b9150509250929050565b61013c816101b3565b82525050565b60006020820190506101576000830184610133565b92915050565b6000610168826101b3565b9150610173836101b3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156101a8576101a7610206565b5b828201905092915050565b6000819050919050565b60006101c8826101b3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156101fb576101fa610206565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610243816101b3565b811461024e57600080fd5b5056fea2646970667358221220de20d82abee4e4f81661465126dda93179255f9249d58bde7c3ea5f5f8bc3dbb64736f6c63430008060033",
"name": "unknown",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
},
{
"address": "0x901d12ebe1b195e5aa8748e62bd7734ae19b51f",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "0x7357f5d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x7357f5d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"name": "run(uint256,uint256)",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
}]
}

@ -0,0 +1,42 @@
pragma solidity 0.8.6;
/**
* @title Storage
* @dev Store & retreive value in a variable
*/
contract D1 {
uint256 number;
function store(uint256 num) public {
assert(num < 5);
number =num;
}
function retval() public returns(uint256){
return number;
}
}
contract D2 {
D1 d1;
constructor() public
{
d1 = D1(0x0901d12ebE1b195E5AA8748E62Bd7734aE19B51F);
}
function test(uint256 num) public returns(uint256) {
uint256 sum = d1.retval() + num;
if (sum == 10) {
return sum + 10;
}
else if(sum == 11) {
return sum + 12;
}
else if(sum == 30) {
return sum * 2;
}
assert(sum != 20);
return sum;
}
}

@ -0,0 +1,78 @@
{
"initialState": {
"accounts": {
"0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe": {
"balance": "0x10000000000000000000000000000",
"code": "",
"nonce": 0,
"storage": {}
},
"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {
"balance": "0x0",
"code": "",
"nonce": 0,
"storage": {}
}
}
},
"steps": [{
"address": "",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x608060405234801561001057600080fd5b50610190806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636057361d1461003b5780639c88345314610057575b600080fd5b610055600480360381019061005091906100ae565b610075565b005b61005f610090565b60405161006c91906100ea565b60405180910390f35b600581106100865761008561010f565b5b8060008190555050565b60008054905090565b6000813590506100a881610143565b92915050565b6000602082840312156100c4576100c361013e565b5b60006100d284828501610099565b91505092915050565b6100e481610105565b82525050565b60006020820190506100ff60008301846100db565b92915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600080fd5b61014c81610105565b811461015757600080fd5b5056fea26469706673582212200d02c19e8a2bae5958a822a8cfde054e94c216f2113e4b13c9dfcebaa7fd6d1564736f6c63430008060033",
"name": "unknown",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
},
{
"address": "0x0901d12ebE1b195E5AA8748E62Bd7734aE19B51F",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x6057361d0000000000000000000000000000000000000000000000000000000000000001",
"name": "unknown",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
},
{
"address": "",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x608060405234801561001057600080fd5b50730901d12ebe1b195e5aa8748e62bd7734ae19b51f6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061039e806100746000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806329e99f0714610030575b600080fd5b61004a600480360381019061004591906101b0565b610060565b6040516100579190610219565b60405180910390f35b6000808260008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639c8834536040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156100cc57600080fd5b505af11580156100e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061010491906101dd565b61010e9190610234565b9050600a81141561012e57600a816101269190610234565b915050610181565b600b81141561014c57600c816101449190610234565b915050610181565b601e81141561016a57600281610162919061028a565b915050610181565b601481141561017c5761017b6102ee565b5b809150505b919050565b60008135905061019581610351565b92915050565b6000815190506101aa81610351565b92915050565b6000602082840312156101c6576101c561034c565b5b60006101d484828501610186565b91505092915050565b6000602082840312156101f3576101f261034c565b5b60006102018482850161019b565b91505092915050565b610213816102e4565b82525050565b600060208201905061022e600083018461020a565b92915050565b600061023f826102e4565b915061024a836102e4565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561027f5761027e61031d565b5b828201905092915050565b6000610295826102e4565b91506102a0836102e4565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156102d9576102d861031d565b5b828202905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b61035a816102e4565b811461036557600080fd5b5056fea26469706673582212205af1f2d3a496abf9b24e8953ec8c2869d565a0a6057c1ff82097fbff424f6e3464736f6c63430008060033",
"name": "unknown",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
},
{
"address": "0x384f682f4a5AbefC8795Cc38a340dE9446dFAE7A",
"blockCoinbase": "0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb",
"blockDifficulty": "0xa7d7343662e26",
"blockGasLimit": "0x7d0000",
"blockNumber": "0x66e393",
"blockTime": "0x5bfa4639",
"calldata": "0x29e99f07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x7d000",
"gasPrice": "0x773594000",
"input": "0x29e99f07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"name": "",
"origin": "0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe",
"value": "0x0"
}]
}

@ -0,0 +1 @@
608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610340806100606000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063228cb733146100725780633eb6a67e1461009d5780638da5cb5b146100a7578063ae169a50146100fe578063e834a8341461012b575b600080fd5b34801561007e57600080fd5b5061008761015a565b6040518082815260200191505060405180910390f35b6100a5610160565b005b3480156100b357600080fd5b506100bc61024a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561010a57600080fd5b506101296004803603810190808035906020019092919050505061026f565b005b34801561013757600080fd5b50610140610301565b604051808215151515815260200191505060405180910390f35b60015481565b600060149054906101000a900460ff1615151561017c57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156101d757600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc6001549081150290604051600060405180830381858888f19350505050158015610240573d6000803e3d6000fd5b5034600181905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060149054906101000a900460ff1615151561028b57600080fd5b600a8110151561029a57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc6001549081150290604051600060405180830381858888f193505050501580156102e2573d6000803e3d6000fd5b506001600060146101000a81548160ff02191690831515021790555050565b600060149054906101000a900460ff16815600a165627a7a723058207bb1caf5a53e1b9c9895f50b1740af67a18d256f4c2724858bdcd660db1729310029
Loading…
Cancel
Save