Beispiel #1
0
    def setUp(self):
        super().setUp()

        # print(self.single_mc.translator.function_data)

        def installLogListener(logs, address):
            def _listener(log):
                if log.address == address and log.topics == [1337]:
                    logs.append(log)

            self.s.head_state.log_listeners.append(_listener)

        self.logs_naked_head = []
        installLogListener(self.logs_naked_head, self.naked_head.address)

        self.logs_single_mc = []
        installLogListener(self.logs_single_mc, self.single_mc.address)

        self.logs_multi_mc = []
        installLogListener(self.logs_multi_mc, self.multi_mc.address)

        # self.events_single_mc = []
        import sys
        sys.stdout.flush()
        self.s.head_state.log_listeners.append(lambda x: (print(
            'SINGLE_MC_EVENT', self.single_mc.translator.listen(x)),
                                                          sys.stdout.flush()))

        kall(self.t, self.s, self.ct, self.single_mc.address, "HYDRA_INIT")
        kall(self.t, self.s, self.ct, self.multi_mc.address, "HYDRA_INIT")
Beispiel #2
0
    def test_logging(self):
        # test a callback to log an event
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        kall(self.t, self.s, self.ct, self.hydra.address, "log_event")

        t = bytes_to_int(utils.sha3("LogCallBack1(uint256,uint256)"))
        self.check_logs([t], int_to_bytes(1) + int_to_bytes(2))
Beispiel #3
0
    def test_second_head_calls(self):
        # first head makes no call but second head does, should set `discrepancy`
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertFalse(self.hydra.bountyClaimed())
        kall(self.t, self.s, self.ct, self.hydra.address,
             "second_head_makes_call")
        self.assertTrue(self.hydra.bountyClaimed())
Beispiel #4
0
    def test_call_args_discrepancy(self):
        # test discrepancy in arguments to external call
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertFalse(self.hydra.bountyClaimed())
        # argument of head1 is 10, argument of head2 is 9
        kall(self.t, self.s, self.ct, self.hydra.address,
             "external_call_wrong_args", 10)
        self.assertTrue(self.hydra.bountyClaimed())
Beispiel #5
0
    def test_call_value_discrepancy(self):
        # test discrepancy in value passed to external call
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertFalse(self.hydra.bountyClaimed())
        # value of head1 is 0, value of head2 is 1
        kall(self.t, self.s, self.ct, self.hydra.address,
             "external_call_wrong_val", 0)
        self.assertTrue(self.hydra.bountyClaimed())
Beispiel #6
0
    def test_throw_discrepancy(self):
        # test discrepancy in instrumented throws
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertFalse(self.hydra.bountyClaimed())

        kall(self.t, self.s, self.ct, self.hydra.address, "throw_discrepancy")

        self.assertTrue(self.hydra.bountyClaimed())
Beispiel #7
0
    def test_call_num_discrepancy(self):
        # test discrepancy in number of calls
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertFalse(self.hydra.bountyClaimed())

        # head1 will call 5 times, head2 4 times
        kall(self.t, self.s, self.ct, self.hydra.address,
             "external_call_wrong_num", 0)
        self.assertTrue(self.hydra.bountyClaimed())
Beispiel #8
0
    def test_external_callback(self):
        # test a callback to make a call to an external contract
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        ret = kall(self.t, self.s, self.ct, self.hydra.address,
                   "external_call", 12)

        self.assertEqual(ret, 12 * 100)
        self.assertFalse(self.hydra.bountyClaimed())

        # call again for good measure
        ret = kall(self.t, self.s, self.ct, self.hydra.address,
                   "external_call", 50)
        self.assertEqual(ret, 50 * 100)
Beispiel #9
0
    def test_output_discrepancy(self):
        # test that Bounty is claimed if heads disagree
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertFalse(self.hydra.bountyClaimed())

        ret = kall(self.t, self.s, self.ct, self.hydra.address,
                   "return_one_or_two")

        self.assertTrue(self.hydra.bountyClaimed())

        # check contract is dead
        self.assertRaises(self.t.TransactionFailed, lambda: \
            kall(self.t, self.s, self.ct, self.hydra.address, "return_constant"))
Beispiel #10
0
    def test_explicit_throw(self):
        # test that the wrapper throws if a head throws explicitly (e.g., OOG)
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertFalse(self.hydra.bountyClaimed())

        self.assertRaises(self.t.TransactionFailed, lambda: \
            kall(self.t, self.s, self.ct, self.hydra.address, "return_or_throw"))

        self.assertFalse(self.hydra.bountyClaimed())

        self.assertRaises(self.t.TransactionFailed, lambda: \
            kall(self.t, self.s, self.ct, self.hydra.address, "explicit_throw"))

        self.assertFalse(self.hydra.bountyClaimed())
Beispiel #11
0
def deploy_montyhall_mc(_tester, chain):
    mc_path = META_CONTRACT
    head_files = [
        PATH_TO_HEADS + 'MontyHall_florian.sol',
        PATH_TO_HEADS + 'MontyHall_florian.se',
        ]

    pyeth_deploy = PyEthereumHydraDeployment(chain, _tester.k0, _tester.a0,
                                             mc_path, head_files,
                                             instrument=True)
    deployed_contracts = pyeth_deploy.build_and_deploy()

    hydra = deployed_contracts[0][1]
    heads = [addr for (addr, abi) in deployed_contracts[1:]]

    print('MetaContract deployed at: 0x{}'.format(utils.encode_hex(hydra.address)))

    for i in range(len(heads)):
        print('Head {} deployed at: 0x{}'.format(i, utils.encode_hex(heads[i])))

    ct = get_contract_translator(head_files[0])

    for function_name in ct.function_data:
        hydra_kall = lambda _, *args, function_name=function_name, **kwargs: \
            kall(_tester, chain, ct, hydra.address, function_name, *args, **kwargs)
        function = hydra_kall
        method = types.MethodType(function, hydra)
        setattr(hydra, function_name, method)

    return hydra, heads, ct
Beispiel #12
0
def deploy_erc20_mc(_tester, chain):
    mc_path = META_CONTRACT
    head_files = [
        PATH_TO_CONTRACTS + '/nonviper/ERC20_solidity_1.sol',
        PATH_TO_CONTRACTS + '/nonviper/ERC20_solidity_2.sol',
        PATH_TO_CONTRACTS + '/nonviper/ERC20_serpent.se',
        PATH_TO_CONTRACTS + '/ERC20.v.py'
        ]

    pyeth_deploy = PyEthereumHydraDeployment(chain,
                                             _tester.k0, _tester.a0,
                                             mc_path, head_files,
                                             instrument=True, instrumenter_path=INSTRUMENTER_PATH)
    deployed_contracts = pyeth_deploy.build_and_deploy(include_constructor=False, debug=False)

    hydra = deployed_contracts[0][1]
    heads = [addr for (addr, abi) in deployed_contracts[1:]]

    print('MetaContract deployed at: 0x{}'.format(utils.encode_hex(hydra.address)))

    for i in range(len(heads)):
        print('Head {} deployed at: 0x{}'.format(i, utils.encode_hex(heads[i])))

    ct = get_contract_translator(head_files[0])

    for function_name in ct.function_data:
        hydra_kall = lambda _, *args, function_name=function_name, **kwargs: \
            kall(_tester, chain, ct, hydra.address, function_name, *args, **kwargs)
        function = hydra_kall
        method = types.MethodType(function, hydra)
        setattr(hydra, function_name, method)

    return hydra, heads, ct
Beispiel #13
0
    def test_oog(self):
        # test that running with too little gas does not trigger a discrepancy
        # that releases the bounty

        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        min_gas = 0
        max_gas = 2**20

        ret = kall(self.t,
                   self.s,
                   self.ct,
                   self.hydra.address,
                   "return_constant",
                   startgas=max_gas)
        self.assertEqual(utils.encode_hex(ret), "abababab")

        self.assertRaises(
            InsufficientStartGas, lambda: kall(self.t,
                                               self.s,
                                               self.ct,
                                               self.hydra.address,
                                               "return_constant",
                                               startgas=min_gas))

        self.assertFalse(self.hydra.bountyClaimed())

        while max_gas - min_gas > 1:
            gas = int((max_gas + min_gas) / 2)
            try:
                ret = kall(self.t,
                           self.s,
                           self.ct,
                           self.hydra.address,
                           "return_constant",
                           startgas=gas)

                print("\ttransaction succeeded with {} gas".format(gas))
                self.assertFalse(self.hydra.bountyClaimed())
                self.assertEqual(utils.encode_hex(ret), "abababab")
                max_gas = gas

            except (TransactionFailed, InsufficientStartGas):
                print("\ttransaction failed with {} gas".format(gas))
                min_gas = gas

        self.assertFalse(self.hydra.bountyClaimed())
Beispiel #14
0
    def test_Bla(self):
        from ethereum.slogging import configure_logging
        config_string = ':trace'

        self.naked_head.doStuff(self.external_distort.address)
        print('naked head done')
        #configure_logging(config_string=config_string)
        kall(self.t, self.s, self.ct, self.single_mc.address, "doStuff",
             self.external_distort.address)
        print('single mc done')
        kall(self.t, self.s, self.ct, self.multi_mc.address, "doStuff",
             self.external_distort.address)
        print('multi mc done')

        self.assertEqual([(l.data, l.topics) for l in self.logs_naked_head],
                         [(l.data, l.topics) for l in self.logs_single_mc])
        self.assertEqual([(l.data, l.topics) for l in self.logs_naked_head],
                         [(l.data, l.topics) for l in self.logs_multi_mc])
Beispiel #15
0
    def test_discrepancy_before_throw(self):
        # heads have a call discrepancy but agree they should throw
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertFalse(self.hydra.bountyClaimed())
        self.assertRaises(self.t.TransactionFailed, lambda: \
            kall(self.t, self.s, self.ct, self.hydra.address, "callback_discrepancy_but_throws"))

        self.assertFalse(self.hydra.bountyClaimed())
Beispiel #16
0
    def test_external_call_throws(self):
        # heads call an external contract that throws and uses up all the gas
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        min_gas = 0
        max_gas = 2**24

        ret = kall(self.t,
                   self.s,
                   self.ct,
                   self.hydra.address,
                   "external_call_throws",
                   startgas=max_gas)
        self.assertEqual(ret, 0)
        self.assertRaises(
            InsufficientStartGas, lambda: kall(self.t,
                                               self.s,
                                               self.ct,
                                               self.hydra.address,
                                               "external_call_throws",
                                               startgas=min_gas))

        self.assertFalse(self.hydra.bountyClaimed())

        while max_gas - min_gas > 1:
            gas = int((max_gas + min_gas) / 2)
            try:
                ret = kall(self.t,
                           self.s,
                           self.ct,
                           self.hydra.address,
                           "external_call_throws",
                           startgas=gas)

                print("\ttransaction succeeded with {} gas".format(gas))
                self.assertFalse(self.hydra.bountyClaimed())
                self.assertEqual(ret, 0)
                max_gas = gas

            except (TransactionFailed, InsufficientStartGas):
                print("\ttransaction failed with {} gas".format(gas))
                min_gas = gas

        self.assertFalse(self.hydra.bountyClaimed())
Beispiel #17
0
    def test_calls_to_mutliple_heads(self):
        # test outputs when heads all agree
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertFalse(self.hydra.getMutex())

        ret = kall(self.t, self.s, self.ct, self.hydra.address,
                   "return_constant")
        self.assertEqual(utils.encode_hex(ret), "abababab")
        self.assertFalse(self.hydra.getMutex())

        ret = kall(self.t, self.s, self.ct, self.hydra.address,
                   "return_constant")
        self.assertEqual(utils.encode_hex(ret), "abababab")
        self.assertFalse(self.hydra.getMutex())

        ret = kall(self.t, self.s, self.ct, self.hydra.address,
                   "mul_by_hundred", 5)
        self.assertEqual(ret, 500)
        self.assertFalse(self.hydra.getMutex())
Beispiel #18
0
    def test_reentrancy_lock(self):
        # make sure the external contract cannot re-enter the Meta-Contract
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.external.get_money(value=1234)
        self.assertEqual(self.s.head_state.get_balance(self.external.address),
                         1234)

        # calls `try_reentrance` in External.sol. Will attempt to send
        # money to the meta contract during a callback
        ret = kall(self.t, self.s, self.ct, self.hydra.address,
                   "external_call_reentrant", 0)
        self.assertEqual(ret, 1)
        self.assertEqual(self.s.head_state.get_balance(self.external.address),
                         1234)
Beispiel #19
0
    def test_balance_callback(self):
        # test a callback to get the balance of an external contract
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertEqual(self.hydra.bountyValue(), 4567)

        self.assertEqual(self.s.head_state.get_balance(self.external.address),
                         0)

        self.external.get_money(value=1234)

        self.assertEqual(self.s.head_state.get_balance(self.external.address),
                         1234)

        ret = kall(self.t, self.s, self.ct, self.hydra.address, "get_balance")
        self.assertEqual(ret, 1234)
Beispiel #20
0
    def setUpClass(cls):
        super(TestMetaContract, cls).setUpClass()

        heads = [ASSETS + 'Head1.sol', ASSETS + 'Head2.sol']

        pyeth_deploy = PyEthereumHydraDeployment(cls.s,
                                                 cls.t.k0,
                                                 cls.t.a0,
                                                 META_CONTRACT,
                                                 heads,
                                                 instrument=False)
        deployed_contracts = pyeth_deploy.build_and_deploy(value=4567)

        cls.hydra, cls.head1, cls.head2 = \
            [abi for (addr, abi) in deployed_contracts]

        cls.ct = cls.head1.translator

        with open(ASSETS + 'External.sol', 'r') as in_file:
            code_external = in_file.read()

        cls.external = cls.s.contract(code_external, language='solidity')

        print()
        print('Head1 deployed at: 0x' + utils.encode_hex(cls.head1.address))
        print('Head2 deployed at: 0x' + utils.encode_hex(cls.head2.address))
        print('MetaContract deployed at: 0x' +
              utils.encode_hex(cls.hydra.address))
        print('External contract deployed at: 0x' +
              utils.encode_hex(cls.external.address))
        print('Caller is: 0x' + utils.encode_hex(cls.t.a0))

        for function_name in cls.ct.function_data:
            hydra_kall = lambda _, *args, function_name=function_name, **kwargs: \
                kall(cls.t, cls.s, cls.ct, cls.hydra.address, function_name, *args, **kwargs)
            function = hydra_kall
            method = types.MethodType(function, cls.hydra)
            setattr(cls.hydra, function_name, method)

        cls.initial_state = cls.s.snapshot()
Beispiel #21
0
 def test_uninitialized_call_fails(self):
     # call should fail if MetaContract has not been initialized
     self.assert_tx_failed(lambda: kall(self.t, self.s, self.ct, self.hydra.
                                        address, "return_constant"))
Beispiel #22
0
    def test_function_not_in_jump_table(self):
        # try to call a function that wasn't explicitly marked in the jumptable
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertRaises(self.t.TransactionFailed, lambda: \
            kall(self.t, self.s, self.ct, self.hydra.address, "not_in_abi"))
Beispiel #23
0
    def test_no_ret_val(self):
        # test output of a function with no return value
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        ret = kall(self.t, self.s, self.ct, self.hydra.address, "return_stop")
        self.assertTrue(ret is None)
Beispiel #24
0
    def test_instrumented_throw(self):
        # test an instrumented throw (i.e., return_size = -1)
        self.hydra.HYDRA_INIT(self.external.address, self.hydra.address)

        self.assertRaises(self.t.TransactionFailed, lambda: \
            kall(self.t, self.s, self.ct, self.hydra.address, "instrumented_throw"))