def test_extra_call_gas_constant_when_gas_price_lower(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesInt deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, -12345) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None base_gas_price = alarm.getCallBaseGasPrice(call_key) deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) call_txn_receipt = wait_for_transaction(deploy_client, call_txn_hash) assert alarm.checkIfCalled(call_key) is True recorded_gas_used = alarm.getCallGasUsed(call_key) actual_gas_used = int(call_txn_receipt['gasUsed'], 16) assert recorded_gas_used >= actual_gas_used assert abs(recorded_gas_used - actual_gas_used) in {0, 64}
def test_extra_call_gas_constant_when_gas_price_higher(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesInt deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction( alarm._meta.address, -12345) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None base_gas_price = alarm.getCallBaseGasPrice(call_key) deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key, gas_price=base_gas_price + 10) call_txn_receipt = wait_for_transaction(deploy_client, call_txn_hash) assert alarm.checkIfCalled(call_key) is True recorded_gas_used = alarm.getCallGasUsed(call_key) actual_gas_used = int(call_txn_receipt['gasUsed'], 16) assert recorded_gas_used >= actual_gas_used assert abs(recorded_gas_used - actual_gas_used) in {0, 64}
def test_caller_payout(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesUInt coinbase = deploy_client.get_coinbase() deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, 3) wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() == 0 call_key = alarm.getLastCallKey() assert call_key is not None assert alarm.getCallPayout(call_key) == 0 assert alarm.getAccountBalance(coinbase) == 0 deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) gas_used = alarm.getCallGasUsed(call_key) gas_price = alarm.getCallGasPrice(call_key) base_gas_price = alarm.getCallBaseGasPrice(call_key) scalar = 100 * base_gas_price / (abs(gas_price - base_gas_price) + base_gas_price) expected_payout = gas_used * gas_price * scalar * 101 / 10000 balance = alarm.getAccountBalance(coinbase) assert balance == expected_payout assert alarm.getCallPayout(call_key) == balance
def test_executing_scheduled_call_with_bytes32(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesBytes32 deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction( alarm._meta.address, 'abc\x00\x00\x00\x00\x00abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' ) wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() is None call_key = alarm.getLastCallKey() assert call_key is not None deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) assert client_contract.value() == 'abc\x00\x00\x00\x00\x00abc'
def test_check_if_call_successful_for_failed_call(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.InfiniteLoop deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None assert alarm.checkIfCalled(call_key) is False assert alarm.checkIfSuccess(call_key) is False deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) call_txn_receipt = wait_for_transaction(deploy_client, call_txn_hash) call_txn = deploy_client.get_transaction_by_hash(call_txn_hash) assert alarm.checkIfCalled(call_key) is True assert alarm.checkIfSuccess(call_key) is False assert int(call_txn_receipt['gasUsed'], 16) == int(call_txn['gas'], 16)
def test_caller_payout(geth_node, geth_coinbase, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesUInt deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, 3) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) assert client_contract.value.call() == 0 callKey = alarm.getLastCallKey.call() assert callKey is not None assert alarm.getCallPayout.call(callKey) == 0 assert alarm.accountBalances.call(geth_coinbase) == 0 wait_for_block(rpc_client, alarm.getCallTargetBlock.call(callKey), 120) call_txn_hash = alarm.doCall.sendTransaction(callKey) wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) gas_used = alarm.getCallGasUsed.call(callKey) gas_price = alarm.getCallGasPrice.call(callKey) base_gas_price = alarm.getCallBaseGasPrice.call(callKey) scalar = 100 * base_gas_price / (abs(gas_price - base_gas_price) + base_gas_price) expected_payout = gas_used * gas_price * scalar * 101 / 10000 balance = alarm.accountBalances.call(geth_coinbase) assert balance == expected_payout assert alarm.getCallPayout.call(callKey) == balance
def test_what_happens_when_call_throws_exception(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.Fails deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None assert client_contract.value() is False assert alarm.checkIfCalled(call_key) is False assert alarm.checkIfSuccess(call_key) is False deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 300) call_txn_hash = alarm.doCall.sendTransaction(call_key) call_txn_receipt = wait_for_transaction(deploy_client, call_txn_hash) call_txn = deploy_client.get_transaction_by_hash(call_txn_hash) assert client_contract.value() is False assert alarm.checkIfCalled(call_key) is True assert alarm.checkIfSuccess(call_key) is False gas_used = int(call_txn_receipt['gasUsed'], 16) gas = int(call_txn['gas'], 16) gas_recorded = alarm.getCallGasUsed(call_key) assert gas == gas_used assert gas == gas_recorded
def test_cost_of_duplicate_call(geth_node, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) assert client_contract.value.call() is False callKey = alarm.getLastCallKey.call() assert callKey is not None assert alarm.checkIfCalled.call(callKey) is False wait_for_block(rpc_client, alarm.getCallTargetBlock.call(callKey), 120) call_txn_hash = alarm.doCall.sendTransaction(callKey) call_txn_receipt = wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) assert alarm.checkIfCalled.call(callKey) is True call_txn_hash = alarm.doCall.sendTransaction(callKey) call_txn_receipt = wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) assert call_txn_receipt['gasUsed'] == '0x67f0'
def test_getting_gas_used(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() is False call_key = alarm.getLastCallKey() assert call_key is not None assert alarm.getCallGasUsed(call_key) == 0 deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) call_txn = deploy_client.get_transaction_by_hash(call_txn_hash) assert client_contract.value() is True assert alarm.getCallGasPrice(call_key) == int(call_txn['gasPrice'], 16)
def test_getting_called_at_block(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() is False call_key = alarm.getLastCallKey() assert call_key is not None assert alarm.getCallGasUsed(call_key) == 0 deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) call_txn = deploy_client.get_transaction_by_hash(call_txn_hash) assert client_contract.value() is True assert alarm.getCallCalledAtBlock(call_key) == int(call_txn['blockNumber'], 16)
def test_what_happens_when_call_throws_exception(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.Fails deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None assert client_contract.value() is False assert alarm.checkIfCalled(call_key) is False assert alarm.checkIfSuccess(call_key) is False deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 300) call_txn_hash = alarm.doCall.sendTransaction(call_key) call_txn_receipt = wait_for_transaction(deploy_client, call_txn_hash) call_txn = deploy_client.get_transaction_by_hash(call_txn_hash) assert client_contract.value() is False assert alarm.checkIfCalled(call_key) is True assert alarm.checkIfSuccess(call_key) is False gas_used = int(call_txn_receipt['gasUsed'], 16) gas = int(call_txn['gas'], 16) gas_recorded = alarm.getCallGasUsed(call_key) assert gas == gas_used assert gas == gas_recorded
def test_call_fee(geth_node, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesUInt deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, 3) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) assert client_contract.value.call() == 0 callKey = alarm.getLastCallKey.call() assert callKey is not None before_balance = alarm.accountBalances.call(client_contract._meta.address) wait_for_block(rpc_client, alarm.getCallTargetBlock.call(callKey), 120) call_txn_hash = alarm.doCall.sendTransaction(callKey) wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) after_balance = alarm.accountBalances.call(client_contract._meta.address) fee = alarm.getCallFee.call(callKey) payout = alarm.getCallPayout.call(callKey) assert after_balance == before_balance - payout - fee
def test_scheduled_call_execution_without_pool(geth_node, geth_coinbase, rpc_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.SpecifyBlock caller_pool = contracts.CallerPool(alarm.getCallerPoolAddress.call(), rpc_client) deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) target_block = rpc_client.get_block_number() + 45 txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, target_block) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) callKey = alarm.getLastCallKey.call() assert callKey is not None pool_manager = PoolManager(caller_pool) scheduled_call = ScheduledCall(alarm, pool_manager, callKey) assert pool_manager.in_active_pool is False scheduled_call.execute_async() wait_for_block(rpc_client, scheduled_call.target_block + 4, 180) assert pool_manager.in_active_pool is False assert scheduled_call.txn_hash assert scheduled_call.txn_receipt assert scheduled_call.txn assert alarm.checkIfCalled.call(scheduled_call.call_key) assert scheduled_call.was_called assert scheduled_call.target_block <= scheduled_call.called_at_block assert scheduled_call.called_at_block <= scheduled_call.target_block + scheduled_call.grace_period
def test_check_if_call_successful(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() is False call_key = alarm.getLastCallKey() assert call_key is not None assert alarm.checkIfCalled(call_key) is False assert alarm.checkIfSuccess(call_key) is False deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key)) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) assert client_contract.value() is True assert alarm.checkIfCalled(call_key) is True assert alarm.checkIfSuccess(call_key) is True
def test_call_fee_and_payout_deducted_from_account_balance(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesUInt deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, 3) wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() == 0 call_key = alarm.getLastCallKey() assert call_key is not None before_balance = alarm.getAccountBalance(client_contract._meta.address) deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) after_balance = alarm.getAccountBalance(client_contract._meta.address) fee = alarm.getCallFee(call_key) payout = alarm.getCallPayout(call_key) assert after_balance == before_balance - payout - fee
def test_infinite_loop_protection(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.InfiniteLoop deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) deploy_client.send_transaction(to=client_contract._meta.address, value=1000000000) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) callKey = alarm.getLastCallKey.call() assert callKey is not None deploy_client.wait_for_block(alarm.getCallTargetBlock.call(callKey), 300) call_txn_hash = alarm.doCall.sendTransaction(callKey) call_txn_receipt = wait_for_transaction(deploy_client, call_txn_hash) call_txn = deploy_client.get_transaction_by_hash(call_txn_hash) assert alarm.checkIfCalled.call(callKey) is True assert alarm.checkIfSuccess.call(callKey) is False gas_used = int(call_txn_receipt['gasUsed'], 16) expected = int(call_txn['gas'], 16) assert gas_used == expected
def test_call_fee(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesUInt deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, 3) wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() == 0 call_key = alarm.getLastCallKey() assert call_key is not None owner = '0xd3cda913deb6f67967b99d67acdfa1712c293601' assert alarm.getCallFee(call_key) == 0 assert alarm.getAccountBalance(owner) == 0 deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) balance = alarm.getAccountBalance(owner) assert balance > 0 assert alarm.getCallFee(call_key) == balance
def test_extra_call_gas_constant_when_gas_price_lower(geth_node, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesInt deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, -12345) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) callKey = alarm.getLastCallKey.call() assert callKey is not None base_gas_price = alarm.getCallBaseGasPrice.call(callKey) wait_for_block(rpc_client, alarm.getCallTargetBlock.call(callKey), 120) call_txn_hash = alarm.doCall.sendTransaction(callKey, gas_price=base_gas_price - 10) call_txn_receipt = wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) assert alarm.checkIfCalled.call(callKey) is True recorded_gas_used = alarm.getCallGasUsed.call(callKey) actual_gas_used = int(call_txn_receipt['gasUsed'], 16) try: assert actual_gas_used == recorded_gas_used except AssertionError: assert actual_gas_used == recorded_gas_used + 64
def test_authorizing_other_address(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.AuthorizesOthers coinbase = deploy_client.get_coinbase() authed_addr = alarm.authorizedAddress() unauthed_addr = alarm.unauthorizedAddress() deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(coinbase, value=deposit_amount) assert alarm.checkAuthorization(coinbase, client_contract._meta.address) is False txn_1_hash = alarm.scheduleCall.sendTransaction( client_contract._meta.address, client_contract.doIt.encoded_abi_signature, utils.decode_hex( 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' ), deploy_client.get_block_number() + 50, 255, 0) wait_for_transaction(deploy_client, txn_1_hash) call_key = alarm.getLastCallKey() assert call_key is not None deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) assert alarm.checkIfCalled(call_key) is True assert alarm.checkIfSuccess(call_key) is True assert client_contract.calledBy() == unauthed_addr wait_for_transaction( deploy_client, client_contract.authorize.sendTransaction(alarm._meta.address)) assert alarm.checkAuthorization(coinbase, client_contract._meta.address) is True txn_2_hash = alarm.scheduleCall.sendTransaction( client_contract._meta.address, client_contract.doIt.encoded_abi_signature, utils.decode_hex( 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' ), deploy_client.get_block_number() + 50, 255, 0) wait_for_transaction(deploy_client, txn_2_hash) assert call_key != alarm.getLastCallKey() call_key = alarm.getLastCallKey() assert call_key is not None deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) assert alarm.checkIfCalled(call_key) is True assert alarm.checkIfSuccess(call_key) is True assert client_contract.calledBy() == authed_addr
def test_get_scheduled_by(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key alarm.getCallScheduledBy(call_key) == deploy_client.get_coinbase()
def test_getting_base_gas_used(geth_node, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) txn = rpc_client.get_transaction_by_hash(txn_hash) callKey = alarm.getLastCallKey.call() assert callKey is not None assert alarm.getCallBaseGasPrice.call(callKey) == int(txn['gasPrice'], 16)
def test_executing_scheduled_call(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesUInt deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, 3) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None call_data = alarm.getCallData(call_key) assert call_data == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03'
def test_scheduled_call_python_object(deploy_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesUInt coinbase = deploy_client.get_coinbase() deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, 3) wait_for_transaction(deploy_client, txn_hash) txn = deploy_client.get_transaction_by_hash(txn_hash) assert client_contract.value() == 0 call_key = alarm.getLastCallKey() assert call_key is not None owner = '0xd3cda913deb6f67967b99d67acdfa1712c293601' deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) txn_receipt = wait_for_transaction(deploy_client, alarm.doCall.sendTransaction(call_key)) call_txn = deploy_client.get_transaction_by_hash(txn_receipt['transactionHash']) scheduled_call = ScheduledCall(alarm, call_key) assert scheduled_call.scheduler_account_balance == alarm.getAccountBalance(client_contract._meta.address) assert scheduled_call.target_block == alarm.getCallTargetBlock(call_key) assert scheduled_call.scheduled_by == client_contract._meta.address assert scheduled_call.called_at_block == int(txn_receipt['blockNumber'], 16) assert scheduled_call.contract_address == client_contract._meta.address assert scheduled_call.base_gas_price == int(txn['gasPrice'], 16) assert scheduled_call.gas_price == int(call_txn['gasPrice'], 16) actual_gas_used = int(txn_receipt['gasUsed'], 16) assert scheduled_call.gas_used >= actual_gas_used gas_diff = abs(scheduled_call.gas_used - actual_gas_used) assert gas_diff in {0, 64} assert scheduled_call.payout == alarm.getAccountBalance(coinbase) == alarm.getCallPayout(call_key) assert scheduled_call.fee == alarm.getAccountBalance(owner) == alarm.getCallFee(call_key) assert scheduled_call.abi_signature == client_contract.doIt.encoded_abi_signature == alarm.getCallABISignature(call_key) assert scheduled_call.is_cancelled is False assert scheduled_call.was_called is True assert scheduled_call.was_successful is True assert utils.encode_hex(scheduled_call.data_hash) == 'c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b'
def test_get_scheduled_by(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key alarm.getCallScheduledBy(call_key) == deploy_client.get_coinbase()
def test_scheduled_call_execution_without_pool(geth_node, geth_node_config, deploy_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.SpecifyBlock deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) target_block = deploy_client.get_block_number() + 45 txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, target_block) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None scheduled_call = ScheduledCall(alarm, call_key) block_sage = scheduled_call.block_sage pool_manager = PoolManager(alarm, block_sage=block_sage) time.sleep(1) assert pool_manager.in_any_pool is False scheduled_call.execute_async() # let the scheduled call do it's thing. assert block_sage.current_block_number < target_block wait_till = scheduled_call.target_block + 10 wait_for_block( deploy_client, wait_till, 2 * block_sage.estimated_time_to_block(wait_till), ) for i in range(5): if scheduled_call.txn_hash: break time.sleep(block_sage.block_time) assert scheduled_call.txn_hash assert scheduled_call.txn_receipt assert scheduled_call.txn assert alarm.checkIfCalled(scheduled_call.call_key) assert scheduled_call.was_called assert scheduled_call.target_block <= scheduled_call.called_at_block assert scheduled_call.called_at_block <= scheduled_call.target_block + scheduled_call.grace_period
def test_getting_base_gas_used(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) txn = deploy_client.get_transaction_by_hash(txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None assert alarm.getCallBaseGasPrice(call_key) == int(txn['gasPrice'], 16)
def test_scheduler(geth_node, geth_node_config, deploy_client, deployed_contracts, contracts): block_sage = BlockSage(deploy_client) alarm = deployed_contracts.Alarm client_contract = deployed_contracts.SpecifyBlock deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) anchor_block = deploy_client.get_block_number() blocks = (1, 4, 4, 8, 30, 40, 50, 60) call_keys = [] for n in blocks: wait_for_transaction( deploy_client, client_contract.scheduleIt.sendTransaction(alarm._meta.address, anchor_block + 100 + n)) last_call_key = alarm.getLastCallKey() assert last_call_key is not None call_keys.append(last_call_key) pool_manager = PoolManager(alarm, block_sage) scheduler = Scheduler(alarm, pool_manager, block_sage=block_sage) scheduler.monitor_async() final_block = anchor_block + 100 + 70 wait_for_block( deploy_client, final_block, 2 * block_sage.estimated_time_to_block(final_block), ) scheduler.stop() block_sage.stop() results = [alarm.checkIfCalled(k) for k in call_keys] assert all(results)
def test_scheduled_call_execution_without_pool( geth_node, geth_node_config, deploy_client, deployed_contracts, contracts ): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.SpecifyBlock deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) target_block = deploy_client.get_block_number() + 45 txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, target_block) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None scheduled_call = ScheduledCall(alarm, call_key) block_sage = scheduled_call.block_sage pool_manager = PoolManager(alarm, block_sage=block_sage) time.sleep(1) assert pool_manager.in_any_pool is False scheduled_call.execute_async() # let the scheduled call do it's thing. assert block_sage.current_block_number < target_block wait_till = scheduled_call.target_block + 10 wait_for_block(deploy_client, wait_till, 2 * block_sage.estimated_time_to_block(wait_till)) for i in range(5): if scheduled_call.txn_hash: break time.sleep(block_sage.block_time) assert scheduled_call.txn_hash assert scheduled_call.txn_receipt assert scheduled_call.txn assert alarm.checkIfCalled(scheduled_call.call_key) assert scheduled_call.was_called assert scheduled_call.target_block <= scheduled_call.called_at_block assert scheduled_call.called_at_block <= scheduled_call.target_block + scheduled_call.grace_period
def test_cannot_schedule_too_soon(geth_node, geth_coinbase, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.SpecifyBlock deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleDelta.sendTransaction(alarm._meta.address, 39) wait_for_transaction(rpc_client, txn_hash) call_key = alarm.getLastCallKey.call() assert call_key is None txn_hash = client_contract.scheduleDelta.sendTransaction(alarm._meta.address, 40) wait_for_transaction(rpc_client, txn_hash) call_key = alarm.getLastCallKey.call() assert call_key is not None
def test_executing_scheduled_call(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesUInt deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction( alarm._meta.address, 3) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None call_data = alarm.getCallData(call_key) assert call_data == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03'
def test_cancelling_a_call(geth_node, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.CancelsCall deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) callKey = alarm.getLastCallKey.call() assert callKey is not None assert alarm.checkIfCancelled.call(callKey) is False wait_for_transaction(rpc_client, client_contract.cancelIt.sendTransaction(alarm._meta.address, callKey)) assert alarm.checkIfCancelled.call(callKey) is True
def test_scheduled_call_python_object(geth_node, geth_coinbase, rpc_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm caller_pool = contracts.CallerPool(alarm.getCallerPoolAddress.call(), rpc_client) client_contract = deployed_contracts.PassesUInt deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, 3) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) txn = rpc_client.get_transaction_by_hash(txn_hash) assert client_contract.value.call() == 0 callKey = alarm.getLastCallKey.call() assert callKey is not None owner = '0xd3cda913deb6f67967b99d67acdfa1712c293601' wait_for_block(rpc_client, alarm.getCallTargetBlock.call(callKey), 120) txn_receipt = wait_for_transaction(alarm._meta.rpc_client, alarm.doCall.sendTransaction(callKey)) call_txn = rpc_client.get_transaction_by_hash(txn_receipt['transactionHash']) pool_manager = PoolManager(caller_pool) scheduled_call = ScheduledCall(alarm, pool_manager, callKey) assert scheduled_call.scheduler_account_balance == alarm.accountBalances.call(client_contract._meta.address) assert scheduled_call.target_block == alarm.getCallTargetBlock.call(callKey) assert scheduled_call.scheduled_by == client_contract._meta.address assert scheduled_call.called_at_block == int(txn_receipt['blockNumber'], 16) assert scheduled_call.contract_address == client_contract._meta.address assert scheduled_call.base_gas_price == int(txn['gasPrice'], 16) assert scheduled_call.gas_price == int(call_txn['gasPrice'], 16) try: assert scheduled_call.gas_used == int(txn_receipt['gasUsed'], 16) except AssertionError: assert scheduled_call.gas_used == int(txn_receipt['gasUsed'], 16) + 64 assert scheduled_call.payout == alarm.accountBalances.call(geth_coinbase) == alarm.getCallPayout.call(callKey) assert scheduled_call.fee == alarm.accountBalances.call(owner) == alarm.getCallFee.call(callKey) assert scheduled_call.abi_signature == client_contract.doIt.encoded_abi_function_signature == alarm.getCallABISignature.call(callKey) assert scheduled_call.is_cancelled is False assert scheduled_call.was_called is True assert scheduled_call.was_successful is True assert utils.encode_hex(scheduled_call.data_hash) == 'c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b'
def test_executing_scheduled_call_with_int(geth_node, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesInt deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, -12345) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) assert client_contract.value.call() == 0 callKey = alarm.getLastCallKey.call() assert callKey is not None wait_for_block(rpc_client, alarm.getCallTargetBlock.call(callKey), 120) call_txn_hash = alarm.doCall.sendTransaction(callKey) wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) assert client_contract.value.call() == -12345
def test_executing_scheduled_call_with_bytes32(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesBytes32 deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, 'abc\x00\x00\x00\x00\x00abc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() is None call_key = alarm.getLastCallKey() assert call_key is not None deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) assert client_contract.value() == 'abc\x00\x00\x00\x00\x00abc'
def test_funds_are_locked_during_execution(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.WithdrawsDuringCall wait_for_transaction( deploy_client, client_contract.setAlarm.sendTransaction(alarm._meta.address)) deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction() wait_for_transaction(deploy_client, txn_hash) assert client_contract.wasCalled() is False call_key = alarm.getLastCallKey() assert call_key is not None pre_balance = client_contract.getAlarmBalance.call() assert pre_balance == deposit_amount deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) fee = alarm.getCallFee(call_key) payout = alarm.getCallPayout(call_key) withdrawn_amount = client_contract.withdrawAmount() assert all(v > 0 for v in (fee, payout, withdrawn_amount)) post_balance = client_contract.getAlarmBalance.call() # Sanity check that an underflow error didn't occur assert post_balance < pre_balance # During the call, the WithdrawsDuringCall contract tries to withdraw it's # entire account balance. This should only leave the max call cost minus # fees left in the account. assert post_balance == pre_balance - fee - payout - withdrawn_amount assert alarm.checkIfCalled(call_key) is True
def test_cancelling_a_call(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.CancelsCall deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None assert alarm.checkIfCancelled(call_key) is False cancel_txn_hash = client_contract.cancelIt.sendTransaction(alarm._meta.address, call_key) wait_for_transaction(deploy_client, cancel_txn_hash) assert alarm.checkIfCancelled(call_key) is True
def test_executing_scheduled_call_with_address(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesAddress deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) address = "0xc948453368e5ddc7bc00bb52b5809138217a068d" txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, address) wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() == "0x0000000000000000000000000000000000000000" call_key = alarm.getLastCallKey() assert call_key is not None deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) assert client_contract.value() == address
def test_executing_scheduled_call_with_address(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.PassesAddress deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) address = '0xc948453368e5ddc7bc00bb52b5809138217a068d' txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, address) wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() == '0x0000000000000000000000000000000000000000' call_key = alarm.getLastCallKey() assert call_key is not None deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) assert client_contract.value() == address
def test_check_if_call_successful_for_failed_call(geth_node, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.InfiniteLoop deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) callKey = alarm.getLastCallKey.call() assert callKey is not None assert alarm.checkIfCalled.call(callKey) is False assert alarm.checkIfSuccess.call(callKey) is False wait_for_block(rpc_client, alarm.getCallTargetBlock.call(callKey), 300) call_txn_hash = alarm.doCall.sendTransaction(callKey) wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) assert alarm.checkIfCalled.call(callKey) is True assert alarm.checkIfSuccess.call(callKey) is False
def test_infinite_loop_protection(geth_node, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.InfiniteLoop deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) rpc_client.send_transaction(to=client_contract._meta.address, value=1000000000) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) callKey = alarm.getLastCallKey.call() assert callKey is not None wait_for_block(rpc_client, alarm.getCallTargetBlock.call(callKey), 300) call_txn_hash = alarm.doCall.sendTransaction(callKey) call_txn_receipt = wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) call_txn = rpc_client.get_transaction_by_hash(call_txn_hash) assert alarm.checkIfCalled.call(callKey) is True assert alarm.checkIfSuccess.call(callKey) is False assert call_txn_receipt['gasUsed'] == call_txn['gas']
def test_scheduler(geth_node, geth_node_config, deploy_client, deployed_contracts, contracts): block_sage = BlockSage(deploy_client) alarm = deployed_contracts.Alarm client_contract = deployed_contracts.SpecifyBlock deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) anchor_block = deploy_client.get_block_number() blocks = (1, 4, 4, 8, 30, 40, 50, 60) call_keys = [] for n in blocks: wait_for_transaction(deploy_client, client_contract.scheduleIt.sendTransaction(alarm._meta.address, anchor_block + 100 + n)) last_call_key = alarm.getLastCallKey() assert last_call_key is not None call_keys.append(last_call_key) pool_manager = PoolManager(alarm, block_sage) scheduler = Scheduler(alarm, pool_manager, block_sage=block_sage) scheduler.monitor_async() final_block = anchor_block + 100 + 70 wait_for_block( deploy_client, final_block, 2 * block_sage.estimated_time_to_block(final_block), ) scheduler.stop() block_sage.stop() results = [alarm.checkIfCalled(k) for k in call_keys] assert all(results)
def test_funds_are_locked_during_execution(geth_node, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.WithdrawsDuringCall wait_for_transaction(rpc_client, client_contract.setAlarm.sendTransaction(alarm._meta.address)) deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction() wait_for_transaction(client_contract._meta.rpc_client, txn_hash) assert client_contract.wasCalled.call() is False callKey = alarm.getLastCallKey.call() assert callKey is not None pre_balance = client_contract.getAlarmBalance.call() assert pre_balance == deposit_amount wait_for_block(rpc_client, alarm.getCallTargetBlock.call(callKey), 120) call_txn_hash = alarm.doCall.sendTransaction(callKey) wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) fee = alarm.getCallFee.call(callKey) payout = alarm.getCallPayout.call(callKey) withdrawn_amount = client_contract.withdrawAmount.call() assert all(v > 0 for v in (fee, payout, withdrawn_amount)) post_balance = client_contract.getAlarmBalance.call() # Sanity check that an underflow error didn't occur assert post_balance < pre_balance # During the call, the WithdrawsDuringCall contract tries to withdraw it's # entire account balance. This should only leave the max call cost minus # fees left in the account. assert post_balance == pre_balance - fee - payout - withdrawn_amount assert alarm.checkIfCalled.call(callKey) is True
def test_cannot_schedule_too_soon(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.SpecifyBlock deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleDelta.sendTransaction( alarm._meta.address, 39) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is None txn_hash = client_contract.scheduleDelta.sendTransaction( alarm._meta.address, 40) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None
def test_minimum_grace_period_enforced(geth_node, geth_coinbase, rpc_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) wait_for_transaction(rpc_client, client_contract.setGracePeriod.sendTransaction(8)) txn_1_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(rpc_client, txn_1_hash) call_key = alarm.getLastCallKey.call() assert call_key is None wait_for_transaction(rpc_client, client_contract.setGracePeriod.sendTransaction(16)) txn_2_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(rpc_client, txn_2_hash) call_key = alarm.getLastCallKey.call() assert call_key is not None alarm.getCallGracePeriod.call(call_key) == 16
def test_check_if_called(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) assert client_contract.value() is False call_key = alarm.getLastCallKey() assert call_key is not None assert alarm.checkIfCalled(call_key) is False deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key)) call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) assert client_contract.value() is True assert alarm.checkIfCalled(call_key) is True
def test_check_if_call_successful_for_failed_call(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.InfiniteLoop deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None assert alarm.checkIfCalled(call_key) is False assert alarm.checkIfSuccess(call_key) is False deploy_client.wait_for_block(alarm.getCallTargetBlock(call_key), 120) call_txn_hash = alarm.doCall.sendTransaction(call_key) call_txn_receipt = wait_for_transaction(deploy_client, call_txn_hash) call_txn = deploy_client.get_transaction_by_hash(call_txn_hash) assert alarm.checkIfCalled(call_key) is True assert alarm.checkIfSuccess(call_key) is False assert int(call_txn_receipt['gasUsed'], 16) == int(call_txn['gas'], 16)
def test_minimum_grace_period_enforced(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs minimum_grace_period = alarm.getMinimumGracePeriod() deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) wait_for_transaction(deploy_client, client_contract.setGracePeriod.sendTransaction(minimum_grace_period - 1)) txn_1_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_1_hash) call_key = alarm.getLastCallKey.call() assert call_key is None wait_for_transaction(deploy_client, client_contract.setGracePeriod.sendTransaction(minimum_grace_period)) txn_2_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_2_hash) call_key = alarm.getLastCallKey.call() assert call_key is not None alarm.getCallGracePeriod.call(call_key) == 16
def test_scheduled_call_execution_with_pool(geth_node, geth_coinbase, geth_node_config, deploy_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm joiner = deployed_contracts.JoinsPool client_contract = deployed_contracts.SpecifyBlock coinbase = geth_coinbase block_sage = BlockSage(deploy_client) # Put in our deposit with the alarm contract. deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) wait_for_transaction( deploy_client, joiner.setCallerPool.sendTransaction(alarm._meta.address)) assert alarm.getBondBalance(coinbase) == 0 bond_amount = alarm.getMinimumBond() * 10 # Put in our bond wait_for_transaction(deploy_client, alarm.depositBond.sendTransaction(value=bond_amount)) # Put the contract's bond in wait_for_transaction( deploy_client, deploy_client.send_transaction(to=joiner._meta.address, value=bond_amount)) wait_for_transaction(deploy_client, joiner.deposit.sendTransaction(bond_amount)) # Both join the pool wait_for_transaction(deploy_client, joiner.enter.sendTransaction()) wait_for_transaction(deploy_client, alarm.enterPool.sendTransaction()) # New pool is formed but not active first_generation_id = alarm.getNextGenerationId() assert first_generation_id > 0 # Go ahead and schedule the call. generation_start_at = alarm.getGenerationStartAt(first_generation_id) target_block = generation_start_at + 5 txn_hash = client_contract.scheduleIt.sendTransaction( alarm._meta.address, target_block) wait_for_transaction(deploy_client, txn_hash) # Wait for the pool to become active wait_for_block( deploy_client, generation_start_at, 2 * block_sage.estimated_time_to_block(generation_start_at), ) # We should both be in the pool assert alarm.getCurrentGenerationId() == first_generation_id assert alarm.isInGeneration(joiner._meta.address, first_generation_id) is True assert alarm.isInGeneration(coinbase, first_generation_id) is True call_key = alarm.getLastCallKey() assert call_key is not None scheduled_call = ScheduledCall(alarm, call_key, block_sage=block_sage) pool_manager = PoolManager(alarm, block_sage=block_sage) scheduled_call.execute_async() wait_for_block( deploy_client, scheduled_call.target_block, 2 * block_sage.estimated_time_to_block(scheduled_call.target_block), ) for i in range(alarm.getCallWindowSize() * 2): if scheduled_call.txn_hash: break time.sleep(block_sage.block_time) assert scheduled_call.txn_hash assert scheduled_call.txn_receipt assert scheduled_call.txn assert scheduled_call.was_called assert alarm.checkIfCalled(scheduled_call.call_key) assert scheduled_call.target_block <= scheduled_call.called_at_block assert scheduled_call.called_at_block <= scheduled_call.target_block + scheduled_call.grace_period
def test_call_window_divided_between_callers(deploy_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm joiner = deployed_contracts.JoinsPool client_contract = deployed_contracts.NoArgs coinbase = deploy_client.get_coinbase() # Put in our deposit with the alarm contract. deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) wait_for_transaction( deploy_client, joiner.setCallerPool.sendTransaction(alarm._meta.address)) assert alarm.getBondBalance(coinbase) == 0 deposit_amount = alarm.getMinimumBond() * 10 # Put in our bond wait_for_transaction( deploy_client, alarm.depositBond.sendTransaction(value=deposit_amount)) # Put the contract's bond in wait_for_transaction( deploy_client, deploy_client.send_transaction(to=joiner._meta.address, value=deposit_amount)) wait_for_transaction(deploy_client, joiner.deposit.sendTransaction(deposit_amount)) # Both join the pool wait_for_transaction(deploy_client, joiner.enter.sendTransaction()) wait_for_transaction(deploy_client, alarm.enterPool.sendTransaction()) # New pool is formed but not active first_generation_id = alarm.getNextGenerationId() assert first_generation_id > 0 # Wait for it to become active deploy_client.wait_for_block( alarm.getGenerationStartAt(first_generation_id), 180) # We should both be in the pool assert alarm.getCurrentGenerationId() == first_generation_id assert alarm.isInGeneration(joiner._meta.address, first_generation_id) is True assert alarm.isInGeneration(coinbase, first_generation_id) is True # Schedule the function call. for _ in range(5): txn_hash = client_contract.scheduleIt.sendTransaction( alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None target_block = alarm.getCallTargetBlock(call_key) grace_period = alarm.getCallGracePeriod(call_key) first_caller = alarm.getDesignatedCaller(call_key, target_block) if first_caller == coinbase: break else: raise ValueError("Was never first caller") deploy_client.wait_for_block(target_block, 240) before_balance = alarm.getBondBalance(joiner._meta.address) assert alarm.checkIfCalled(call_key) is False call_txn_hash = alarm.doCall.sendTransaction(call_key) wait_for_transaction(deploy_client, call_txn_hash) after_balance = alarm.getBondBalance(joiner._meta.address) assert alarm.checkIfCalled(call_key) is True assert after_balance == before_balance
def test_call_window_divided_between_callers(deploy_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm joiner = deployed_contracts.JoinsPool client_contract = deployed_contracts.NoArgs coinbase = deploy_client.get_coinbase() # Put in our deposit with the alarm contract. deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) wait_for_transaction( deploy_client, joiner.setCallerPool.sendTransaction(alarm._meta.address)) assert alarm.getBondBalance(coinbase) == 0 deposit_amount = alarm.getMinimumBond() * 10 # Put in our bond wait_for_transaction( deploy_client, alarm.depositBond.sendTransaction(value=deposit_amount)) # Put the contract's bond in wait_for_transaction( deploy_client, deploy_client.send_transaction(to=joiner._meta.address, value=deposit_amount)) wait_for_transaction(deploy_client, joiner.deposit.sendTransaction(deposit_amount)) # Both join the pool assert alarm.canEnterPool(joiner._meta.address) is True wait_for_transaction(deploy_client, joiner.enter.sendTransaction()) assert alarm.canEnterPool(coinbase) is True wait_for_transaction(deploy_client, alarm.enterPool.sendTransaction()) # New pool is formed but not active first_generation_id = alarm.getNextGenerationId() assert first_generation_id > 0 # Wait for it to become active deploy_client.wait_for_block( alarm.getGenerationStartAt(first_generation_id), 180) # We should both be in the pool assert alarm.getCurrentGenerationId() == first_generation_id assert alarm.isInGeneration(joiner._meta.address, first_generation_id) is True assert alarm.isInGeneration(coinbase, first_generation_id) is True # Schedule the function call. wait_for_transaction(deploy_client, client_contract.setDelta(250)) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None assert alarm.getGenerationIdForCall(call_key) == first_generation_id target_block = alarm.getCallTargetBlock(call_key) grace_period = alarm.getCallGracePeriod(call_key) call_window_size = alarm.getCallWindowSize() callers = [ alarm.getDesignatedCaller(call_key, target_block + n) for n in range(grace_period) ] caller_a = callers[0] caller_b = callers[call_window_size] # sanity check assert caller_a != caller_b assert { coinbase, joiner._meta.address, '0x0000000000000000000000000000000000000000' } == set(callers) call_on_block = None call_window_size = alarm.getCallWindowSize() for i, caller in enumerate(callers): if i / call_window_size + 2 > len(callers) / call_window_size: assert caller == '0x0000000000000000000000000000000000000000' elif (i / call_window_size) % 2 == 0: assert caller == caller_a else: assert caller == caller_b if call_on_block is None and i > call_window_size and caller == coinbase: call_on_block = target_block + i deploy_client.wait_for_block(call_on_block, 240) assert alarm.getNextGenerationId() == 0 before_balance = alarm.getBondBalance(joiner._meta.address) assert alarm.checkIfCalled(call_key) is False call_txn_hash = alarm.doCall.sendTransaction(call_key) call_txn_receipt = wait_for_transaction(deploy_client, call_txn_hash) call_txn = deploy_client.get_transaction_by_hash(call_txn_hash) call_block = deploy_client.get_block_by_hash(call_txn_receipt['blockHash']) after_balance = alarm.getBondBalance(joiner._meta.address) assert alarm.checkIfCalled(call_key) is True assert after_balance < before_balance minimum_bond = int(call_block['gasLimit'], 16) * int( call_txn['gasPrice'], 16) assert after_balance == before_balance - minimum_bond next_generation_id = alarm.getNextGenerationId() assert next_generation_id > 0 assert alarm.isInGeneration(joiner._meta.address, first_generation_id) is True assert alarm.isInGeneration(joiner._meta.address, next_generation_id) is False
def test_scheduled_call_execution_with_pool(geth_node, geth_coinbase, rpc_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm joiner = deployed_contracts.JoinsPool client_contract = deployed_contracts.SpecifyBlock caller_pool = contracts.CallerPool(alarm.getCallerPoolAddress.call(), rpc_client) # Put in our deposit with the alarm contract. deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) wait_for_transaction(rpc_client, joiner.setCallerPool.sendTransaction(caller_pool._meta.address)) assert caller_pool.callerBonds.call(geth_coinbase) == 0 deposit_amount = caller_pool.getMinimumBond.call() * 10 # Put in our bond wait_for_transaction(rpc_client, caller_pool.depositBond.sendTransaction(value=deposit_amount)) # Put the contract's bond in wait_for_transaction(rpc_client, rpc_client.send_transaction(to=joiner._meta.address, value=deposit_amount)) wait_for_transaction(rpc_client, joiner.deposit.sendTransaction(deposit_amount)) # Both join the pool wait_for_transaction(rpc_client, joiner.enter.sendTransaction()) wait_for_transaction(rpc_client, caller_pool.enterPool.sendTransaction()) # New pool is formed but not active first_pool_key = caller_pool.getNextPoolKey.call() assert first_pool_key > 0 # Go ahead and schedule the call. target_block = first_pool_key + 5 txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, target_block) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) # Wait for the pool to become active wait_for_block(rpc_client, first_pool_key, 180) # We should both be in the pool assert caller_pool.getActivePoolKey.call() == first_pool_key assert caller_pool.isInPool.call(joiner._meta.address, first_pool_key) is True assert caller_pool.isInPool.call(geth_coinbase, first_pool_key) is True callKey = alarm.getLastCallKey.call() assert callKey is not None pool_manager = PoolManager(caller_pool) scheduled_call = ScheduledCall(alarm, pool_manager, callKey) scheduled_call.execute_async() wait_for_block(rpc_client, scheduled_call.target_block + 8, 180) assert scheduled_call.txn_hash assert scheduled_call.txn_receipt assert scheduled_call.txn assert scheduled_call.was_called assert alarm.checkIfCalled.call(scheduled_call.call_key) assert scheduled_call.target_block <= scheduled_call.called_at_block assert scheduled_call.called_at_block <= scheduled_call.target_block + scheduled_call.grace_period
def test_free_for_all_window_awards_mega_bonus(geth_node, geth_coinbase, rpc_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm caller_pool = contracts.CallerPool(alarm.getCallerPoolAddress.call(), rpc_client) client_contract = deployed_contracts.NoArgs joiner_a = deployed_contracts.JoinsPool deploy_txn = deploy_contract(rpc_client, contracts.JoinsPool, _from=geth_coinbase, gas=get_max_gas(rpc_client)) joiner_b = contracts.JoinsPool(get_contract_address_from_txn(rpc_client, deploy_txn, 30), rpc_client) # Put in our deposit with the alarm contract. deposit_amount = get_max_gas(rpc_client) * rpc_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) wait_for_transaction(rpc_client, joiner_a.setCallerPool.sendTransaction(caller_pool._meta.address)) wait_for_transaction(rpc_client, joiner_b.setCallerPool.sendTransaction(caller_pool._meta.address)) assert caller_pool.callerBonds.call(geth_coinbase) == 0 deposit_amount = caller_pool.getMinimumBond.call() * 10 # Put in our bond wait_for_transaction(rpc_client, caller_pool.depositBond.sendTransaction(value=deposit_amount)) # Put contract A's bond in wait_for_transaction(rpc_client, rpc_client.send_transaction(to=joiner_a._meta.address, value=deposit_amount)) wait_for_transaction(rpc_client, joiner_a.deposit.sendTransaction(deposit_amount)) # Put contract B's bond in wait_for_transaction(rpc_client, rpc_client.send_transaction(to=joiner_b._meta.address, value=deposit_amount)) wait_for_transaction(rpc_client, joiner_b.deposit.sendTransaction(deposit_amount)) # All join the pool wait_for_transaction(rpc_client, joiner_a.enter.sendTransaction()) wait_for_transaction(rpc_client, joiner_b.enter.sendTransaction()) wait_for_transaction(rpc_client, caller_pool.enterPool.sendTransaction()) # New pool is formed but not active first_pool_key = caller_pool.getNextPoolKey.call() assert first_pool_key > 0 # Wait for it to become active wait_for_block(rpc_client, first_pool_key, 240) # We should both be in the pool assert caller_pool.getActivePoolKey.call() == first_pool_key assert caller_pool.isInPool.call(joiner_a._meta.address, first_pool_key) is True assert caller_pool.isInPool.call(joiner_b._meta.address, first_pool_key) is True assert caller_pool.isInPool.call(geth_coinbase, first_pool_key) is True # Schedule the function call. txn_hash = client_contract.setGracePeriod.sendTransaction(24) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(client_contract._meta.rpc_client, txn_hash) callKey = alarm.getLastCallKey.call() assert callKey is not None target_block = alarm.getCallTargetBlock.call(callKey) grace_period = alarm.getCallGracePeriod.call(callKey) wait_for_block(rpc_client, target_block + grace_period - 4, 300) my_before_balance = caller_pool.callerBonds.call(geth_coinbase) before_balance_a = caller_pool.callerBonds.call(joiner_a._meta.address) before_balance_b = caller_pool.callerBonds.call(joiner_b._meta.address) assert alarm.checkIfCalled.call(callKey) is False call_txn_hash = alarm.doCall.sendTransaction(callKey) call_txn_receipt = wait_for_transaction(alarm._meta.rpc_client, call_txn_hash) call_txn = rpc_client.get_transaction_by_hash(call_txn_hash) call_block = rpc_client.get_block_by_hash(call_txn_receipt["blockHash"]) my_after_balance = caller_pool.callerBonds.call(geth_coinbase) after_balance_a = caller_pool.callerBonds.call(joiner_a._meta.address) after_balance_b = caller_pool.callerBonds.call(joiner_b._meta.address) assert alarm.checkIfCalled.call(callKey) is True assert after_balance_a < before_balance_a assert after_balance_b < before_balance_b minimum_bond = int(call_block["gasLimit"], 16) * int(call_txn["gasPrice"], 16) assert after_balance_a == before_balance_a - minimum_bond assert after_balance_b == before_balance_b - minimum_bond assert my_after_balance > my_before_balance assert my_after_balance == my_before_balance + 2 * minimum_bond assert caller_pool.getNextPoolKey.call() == 0
def test_free_for_all_window_awards_mega_bonus(deploy_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.NoArgs joiner_a = deployed_contracts.JoinsPool coinbase = deploy_client.get_coinbase() deploy_txn = deploy_contract(deploy_client, contracts.JoinsPool, _from=coinbase, gas=get_max_gas(deploy_client)) joiner_b = contracts.JoinsPool( get_contract_address_from_txn(deploy_client, deploy_txn, 30), deploy_client) coinbase = deploy_client.get_coinbase() # Put in our deposit with the alarm contract. deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) wait_for_transaction( deploy_client, joiner_a.setCallerPool.sendTransaction(alarm._meta.address)) wait_for_transaction( deploy_client, joiner_b.setCallerPool.sendTransaction(alarm._meta.address)) assert alarm.getBondBalance(coinbase) == 0 deposit_amount = alarm.getMinimumBond() * 10 # Put in our bond wait_for_transaction( deploy_client, alarm.depositBond.sendTransaction(value=deposit_amount)) # Put contract A's bond in wait_for_transaction( deploy_client, deploy_client.send_transaction(to=joiner_a._meta.address, value=deposit_amount)) wait_for_transaction(deploy_client, joiner_a.deposit.sendTransaction(deposit_amount)) # Put contract B's bond in wait_for_transaction( deploy_client, deploy_client.send_transaction(to=joiner_b._meta.address, value=deposit_amount)) wait_for_transaction(deploy_client, joiner_b.deposit.sendTransaction(deposit_amount)) # All join the pool wait_for_transaction(deploy_client, joiner_a.enter.sendTransaction()) wait_for_transaction(deploy_client, joiner_b.enter.sendTransaction()) wait_for_transaction(deploy_client, alarm.enterPool.sendTransaction()) # New pool is formed but not active first_generation_id = alarm.getNextGenerationId() assert first_generation_id > 0 # Wait for it to become active deploy_client.wait_for_block( alarm.getGenerationStartAt(first_generation_id), 240) # We should both be in the pool assert alarm.getCurrentGenerationId() == first_generation_id assert alarm.isInGeneration(joiner_a._meta.address, first_generation_id) is True assert alarm.isInGeneration(joiner_b._meta.address, first_generation_id) is True assert alarm.isInGeneration(coinbase, first_generation_id) is True # Schedule the function call. txn_hash = client_contract.setGracePeriod.sendTransaction( alarm.getMinimumGracePeriod()) txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None target_block = alarm.getCallTargetBlock(call_key) grace_period = alarm.getCallGracePeriod(call_key) deploy_client.wait_for_block(target_block + grace_period - 4, 300) my_before_balance = alarm.getBondBalance(coinbase) before_balance_a = alarm.getBondBalance(joiner_a._meta.address) before_balance_b = alarm.getBondBalance(joiner_b._meta.address) assert alarm.checkIfCalled(call_key) is False call_txn_hash = alarm.doCall.sendTransaction(call_key) call_txn_receipt = wait_for_transaction(deploy_client, call_txn_hash) call_txn = deploy_client.get_transaction_by_hash(call_txn_hash) call_block = deploy_client.get_block_by_hash(call_txn_receipt['blockHash']) my_after_balance = alarm.getBondBalance(coinbase) after_balance_a = alarm.getBondBalance(joiner_a._meta.address) after_balance_b = alarm.getBondBalance(joiner_b._meta.address) assert alarm.checkIfCalled(call_key) is True assert after_balance_a < before_balance_a assert after_balance_b < before_balance_b minimum_bond = int(call_block['gasLimit'], 16) * int( call_txn['gasPrice'], 16) assert after_balance_a == before_balance_a - minimum_bond assert after_balance_b == before_balance_b - minimum_bond assert my_after_balance > my_before_balance assert my_after_balance == my_before_balance + 2 * minimum_bond assert alarm.getNextGenerationId() == 0