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
Exemplo n.º 4
0
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'
Exemplo n.º 9
0
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
Exemplo n.º 15
0
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
Exemplo n.º 16
0
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
Exemplo n.º 17
0
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'
Exemplo n.º 24
0
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()
Exemplo n.º 25
0
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)
Exemplo n.º 27
0
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
Exemplo n.º 30
0
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
Exemplo n.º 36
0
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
Exemplo n.º 49
0
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
Exemplo n.º 53
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