Exemple #1
0
def test_settlement_with_unauthorized_token_transfer(
    web3,
    get_accounts,
    custom_token,
    token_network,
    create_channel_and_deposit,
    withdraw_channel,
    close_and_update_channel,
):
    externally_transferred_amount = 5
    (A, B) = get_accounts(2)
    (vals_A, vals_B) = (
        ChannelValues(deposit=35, withdrawn=10, transferred=0, locked=0),
        ChannelValues(deposit=40, withdrawn=10, transferred=0, locked=0),
    )
    vals_A.locksroot = fake_bytes(32, '02')
    vals_B.locksroot = fake_bytes(32, '03')

    create_channel_and_deposit(A, B, vals_A.deposit, vals_B.deposit)

    withdraw_channel(A, vals_A.withdrawn, B)
    withdraw_channel(B, vals_B.withdrawn, A)

    close_and_update_channel(
        A,
        vals_A,
        B,
        vals_B,
    )

    # A does a transfer to the token_network without appropriate function call - tokens are lost
    custom_token.functions.transfer(
        token_network.address,
        externally_transferred_amount,
    ).transact({'from': A})

    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN)

    # Compute expected settlement amounts
    settlement = get_settlement_amounts(vals_A, vals_B)

    # Channel is settled
    call_settle(token_network, A, vals_A, B, vals_B)

    # Fetch onchain balances after settlement
    post_balance_A = custom_token.functions.balanceOf(A).call()
    post_balance_B = custom_token.functions.balanceOf(B).call()
    post_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # A has lost the externally_transferred_amount
    assert (vals_A.withdrawn + settlement.participant1_balance -
            externally_transferred_amount == post_balance_A)

    # B's settlement works correctly
    assert (settlement.participant2_balance +
            vals_B.withdrawn == post_balance_B)

    # The externally_transferred_amount stays in the contract
    assert (post_balance_contract == externally_transferred_amount)
Exemple #2
0
def test_channel_unlock_with_a_large_expiration(
    web3,
    custom_token,
    token_network,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
):
    """ unlock() should still work after a delayed settleChannel() call """
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(deposit=20, transferred=5)
    values_B = ChannelValues(deposit=30, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data with large expiration date
    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout + 100)
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree.transfers))

    # Reveal secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree.unlockable)

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)

    # Settle channel after a "long" time
    web3.testing.mine(settle_timeout + 50)

    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Unlock the tokens must still work
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree.packed_transfers).call_and_transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()
    assert balance_A == pre_balance_A + 9
    assert balance_B == pre_balance_B + 6
    assert balance_contract == pre_balance_contract - values_B.locked_amounts.locked
Exemple #3
0
def test_settle_with_locked_but_unregistered(
    web3,
    token_network,
    get_accounts,
    create_channel_and_deposit,
    withdraw_channel,
    close_and_update_channel,
    custom_token,
):
    (A, B) = get_accounts(2)
    settle_timeout = TEST_SETTLE_TIMEOUT_MIN

    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout)
    locked_A = pending_transfers_tree.locked_amount
    (vals_A, vals_B) = (
        ChannelValues(deposit=35, withdrawn=10, transferred=0,
                      locked=locked_A),
        ChannelValues(deposit=40, withdrawn=10, transferred=20, locked=0),
    )

    vals_A.locksroot = '0x' + get_merkle_root(
        pending_transfers_tree.merkle_tree).hex()
    vals_B.locksroot = fake_bytes(32, '03')
    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)
    withdraw_channel(channel_identifier, A, vals_A.withdrawn, B)
    withdraw_channel(channel_identifier, B, vals_B.withdrawn, A)

    close_and_update_channel(
        channel_identifier,
        A,
        vals_A,
        B,
        vals_B,
    )

    # Secret hasn't been registered before settlement timeout
    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN)
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Someone unlocks A's pending transfers - all tokens should be refunded
    token_network.functions.unlock(
        channel_identifier,
        B,
        A,
        pending_transfers_tree.packed_transfers,
    ).transact({'from': A})

    # A gets back locked tokens
    assert (custom_token.functions.balanceOf(A).call() == vals_A.deposit -
            vals_A.transferred + vals_B.transferred)
def test_deposit_wrong_state_fail(
    web3: Web3,
    get_accounts: Callable,
    token_network: Contract,
    create_channel: Callable,
    assign_tokens: Callable,
) -> None:
    """ setTotalDeposit() fails on Closed or Settled channels. """
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(deposit=2, transferred=0)
    vals_B = ChannelValues(deposit=2, transferred=0)
    channel_identifier = create_channel(A, B, TEST_SETTLE_TIMEOUT_MIN)[0]
    assign_tokens(A, vals_A.deposit)
    assign_tokens(B, vals_B.deposit)
    token_network.functions.setTotalDeposit(channel_identifier, A,
                                            vals_A.deposit,
                                            B).call_and_transact({"from": A})
    token_network.functions.setTotalDeposit(channel_identifier, B,
                                            vals_B.deposit,
                                            A).call_and_transact({"from": B})

    token_network.functions.closeChannel(
        channel_identifier, B, EMPTY_BALANCE_HASH, 0, EMPTY_ADDITIONAL_HASH,
        EMPTY_SIGNATURE).call_and_transact({"from": A})

    assign_tokens(A, 10)
    assign_tokens(B, 10)
    vals_A.deposit += 5
    vals_B.deposit += 5
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(channel_identifier, A,
                                                vals_A.deposit,
                                                B).call({"from": A})
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(channel_identifier, B,
                                                vals_B.deposit,
                                                A).call({"from": B})

    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN + 1)
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(channel_identifier, A,
                                                vals_A.deposit,
                                                B).call({"from": A})
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(channel_identifier, B,
                                                vals_B.deposit,
                                                A).call({"from": B})
def test_channel_unlock_unregistered_locks(
    web3: Web3,
    token_network: Contract,
    get_accounts: Callable,
    create_channel_and_deposit: Callable,
    withdraw_channel: Callable,
    close_and_update_channel: Callable,
    custom_token: Contract,
) -> None:
    """ unlock() should refund tokens locked by secrets not registered before settlement """
    (A, B) = get_accounts(2)
    settle_timeout = TEST_SETTLE_TIMEOUT_MIN

    pending_transfers_tree = get_pending_transfers_tree(web3, [1, 3, 5], [2, 4], settle_timeout)
    locked_A = pending_transfers_tree.locked_amount
    (vals_A, vals_B) = (
        ChannelValues(
            deposit=35,
            withdrawn=10,
            transferred=0,
            locked_amounts=LockedAmounts(claimable_locked=locked_A),
        ),
        ChannelValues(deposit=40, withdrawn=10, transferred=20),
    )

    vals_A.locksroot = pending_transfers_tree.hash_of_packed_transfers
    vals_B.locksroot = fake_bytes(32, "03")
    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit, vals_B.deposit)
    withdraw_channel(channel_identifier, A, vals_A.withdrawn, B)
    withdraw_channel(channel_identifier, B, vals_B.withdrawn, A)

    close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)

    # Secret hasn't been registered before settlement timeout
    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN + 1)
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Someone unlocks A's pending transfers - all tokens should be refunded
    token_network.functions.unlock(
        channel_identifier, B, A, pending_transfers_tree.packed_transfers
    ).call_and_transact({"from": A})

    # A gets back locked tokens
    assert (
        custom_token.functions.balanceOf(A).call()
        == vals_A.deposit - vals_A.transferred + vals_B.transferred
    )
def test_settle_wrong_state_fail(
    web3,
    get_accounts,
    token_network,
    create_channel_and_deposit,
    get_block,
):
    """ settleChannel() fails on OPENED state and on CLOSED state before the settlement block """
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(deposit=35)
    vals_B = ChannelValues(deposit=40)
    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)

    (settle_timeout, state) = token_network.functions.getChannelInfo(
        channel_identifier,
        A,
        B,
    ).call()
    assert state == ChannelState.OPENED
    assert settle_timeout == TEST_SETTLE_TIMEOUT_MIN

    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    txn_hash = token_network.functions.closeChannel(
        channel_identifier,
        B,
        EMPTY_BALANCE_HASH,
        0,
        EMPTY_ADDITIONAL_HASH,
        EMPTY_SIGNATURE,
    ).transact({'from': A})

    (settle_block_number, state) = token_network.functions.getChannelInfo(
        channel_identifier,
        A,
        B,
    ).call()
    assert state == ChannelState.CLOSED
    assert settle_block_number == TEST_SETTLE_TIMEOUT_MIN + get_block(txn_hash)
    assert web3.eth.blockNumber < settle_block_number

    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN)
    assert web3.eth.blockNumber >= settle_block_number

    # Channel is settled
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    (settle_block_number, state) = token_network.functions.getChannelInfo(
        channel_identifier,
        A,
        B,
    ).call()
    assert state == ChannelState.REMOVED
    assert settle_block_number == 0
def test_settle_wrong_state_fail(
    web3: Web3,
    get_accounts: Callable,
    token_network: Contract,
    create_channel_and_deposit: Callable,
    get_block: Callable,
    create_close_signature_for_no_balance_proof: Callable,
) -> None:
    """ settleChannel() fails on OPENED state and on CLOSED state before the settlement block """
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(deposit=35)
    vals_B = ChannelValues(deposit=40)
    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)

    (settle_timeout,
     state) = token_network.functions.getChannelInfo(channel_identifier, A,
                                                     B).call()
    assert state == ChannelState.OPENED
    assert settle_timeout == TEST_SETTLE_TIMEOUT_MIN

    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    closing_sig = create_close_signature_for_no_balance_proof(
        A, channel_identifier)
    txn_hash = token_network.functions.closeChannel(
        channel_identifier,
        B,
        A,
        EMPTY_BALANCE_HASH,
        0,
        EMPTY_ADDITIONAL_HASH,
        EMPTY_SIGNATURE,
        closing_sig,
    ).call_and_transact({"from": A})

    (settle_block_number,
     state) = token_network.functions.getChannelInfo(channel_identifier, A,
                                                     B).call()
    assert state == ChannelState.CLOSED
    assert settle_block_number == TEST_SETTLE_TIMEOUT_MIN + get_block(txn_hash)
    assert web3.eth.blockNumber < settle_block_number

    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN + 1)
    assert web3.eth.blockNumber > settle_block_number

    # Channel is settled
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    (settle_block_number,
     state) = token_network.functions.getChannelInfo(channel_identifier, A,
                                                     B).call()
    assert state == ChannelState.REMOVED
    assert settle_block_number == 0
def test_deprecation_switch_settle(
    web3: Web3,
    get_accounts: Callable,
    token_network: Contract,
    custom_token: Contract,
    reveal_secrets: Callable,
    create_channel: Callable,
    channel_deposit: Callable,
    close_and_update_channel: Callable,
) -> None:
    """ Channel close and settlement still work after the depracation switch is turned on """
    deprecation_executor = token_network.functions.deprecation_executor().call(
    )
    (A, B) = get_accounts(2)
    deposit = 100

    (vals_A, vals_B) = (
        ChannelValues(
            deposit=deposit,
            withdrawn=0,
            transferred=5,
            locked_amounts=LockedAmounts(claimable_locked=2,
                                         unclaimable_locked=4),
        ),
        ChannelValues(
            deposit=deposit,
            withdrawn=0,
            transferred=10,
            locked_amounts=LockedAmounts(claimable_locked=4,
                                         unclaimable_locked=6),
        ),
    )

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    channel_identifier = create_channel(A, B)[0]
    channel_deposit(channel_identifier, A, vals_A.deposit, B)
    channel_deposit(channel_identifier, B, vals_B.deposit, A)

    # Mock pending transfers data for A -> B
    pending_transfers_tree_A = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_A.locked_amounts.claimable_locked,
        expired_amount=vals_A.locked_amounts.unclaimable_locked,
    )
    vals_A.locksroot = pending_transfers_tree_A.hash_of_packed_transfers
    # Reveal A's secrets.
    reveal_secrets(A, pending_transfers_tree_A.unlockable)

    # Mock pending transfers data for B -> A
    pending_transfers_tree_B = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_B.locked_amounts.claimable_locked,
        expired_amount=vals_B.locked_amounts.unclaimable_locked,
    )
    vals_B.locksroot = pending_transfers_tree_B.hash_of_packed_transfers
    # Reveal B's secrets
    reveal_secrets(B, pending_transfers_tree_B.unlockable)

    # Set the deprecation switch to true
    token_network.functions.deprecate().call_and_transact(
        {"from": deprecation_executor})
    assert token_network.functions.safety_deprecation_switch().call() is True

    # We need to make sure we can still close, settle & unlock the channels
    close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)
    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN + 1)

    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Unlock B's pending transfers that were sent to A
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree_B.packed_transfers).call_and_transact()

    # Unlock A's pending transfers that were sent to B
    token_network.functions.unlock(
        channel_identifier, B, A,
        pending_transfers_tree_A.packed_transfers).call_and_transact()

    assert custom_token.functions.balanceOf(A).call() == pre_balance_A + 107
    assert custom_token.functions.balanceOf(B).call() == pre_balance_B + 93
    assert custom_token.functions.balanceOf(
        token_network.address).call() == pre_balance_contract
Exemple #9
0
def test_channel_unlock_both_participants(
    web3,
    custom_token,
    token_network,
    secret_registry_contract,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
):
    """ A scenario where both parties get some of the pending transfers """
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(deposit=100, transferred=5)
    values_B = ChannelValues(deposit=100, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data for A
    pending_transfers_tree_A = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout)
    values_A.locksroot = pending_transfers_tree_A.merkle_root
    values_A.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree_A.transfers))

    # Reveal A's secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree_A.unlockable)

    # Mock pending transfers data for B
    pending_transfers_tree_B = get_pending_transfers_tree(
        web3, [2, 4, 6], [5, 10], settle_timeout)
    values_B.locksroot = pending_transfers_tree_B.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree_B.transfers))

    # Reveal B's secrets before settlement window ends
    reveal_secrets(B, pending_transfers_tree_B.unlockable)

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)

    # Settle channel
    web3.testing.mine(settle_timeout)

    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # A unlock's
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree_B.packed_transfers).call_and_transact()

    # B unlock's
    token_network.functions.unlock(
        channel_identifier, B, A,
        pending_transfers_tree_A.packed_transfers).call_and_transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Unlocked pending transfers A -> B, that belong to B
    unlockable_A = get_unlocked_amount(
        secret_registry_contract, pending_transfers_tree_A.packed_transfers)

    # Expired pending transfers A -> B, that belong to A
    expired_A = get_locked_amount(pending_transfers_tree_A.expired)

    # Unlocked pending transfers B -> A, that belong to A
    unlockable_B = get_unlocked_amount(
        secret_registry_contract, pending_transfers_tree_B.packed_transfers)

    # Expired pending transfers B -> A, that belong to B
    expired_B = get_locked_amount(pending_transfers_tree_B.expired)

    # check that A and B both received the expected amounts
    assert balance_contract == (pre_balance_contract -
                                values_B.locked_amounts.locked -
                                values_A.locked_amounts.locked)
    assert balance_A == pre_balance_A + unlockable_B + expired_A
    assert balance_B == pre_balance_B + unlockable_A + expired_B
Exemple #10
0
def test_channel_unlock_before_settlement_fails(
    web3,
    custom_token,
    token_network,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
):
    """ unlock() should not work before settlement """
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(deposit=20, transferred=5)
    values_B = ChannelValues(deposit=30, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout)
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree.transfers))

    # Reveal secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree.unlockable)

    # Unlock fails before channel is not settled
    with pytest.raises(TransactionFailed):
        token_network.functions.unlock(
            channel_identifier, A, B,
            pending_transfers_tree.packed_transfers).call()

    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Unlock fails before channel is not settled
    with pytest.raises(TransactionFailed):
        token_network.functions.unlock(
            channel_identifier, A, B,
            pending_transfers_tree.packed_transfers).call()

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)

    # Unlock fails before settlement window is over and channel is not settled
    with pytest.raises(TransactionFailed):
        token_network.functions.unlock(
            channel_identifier, A, B,
            pending_transfers_tree.packed_transfers).call()

    # Settlement window must be over before settling the channel
    web3.testing.mine(settle_timeout)

    # Unlock fails before settle is called
    with pytest.raises(TransactionFailed):
        token_network.functions.unlock(
            channel_identifier, A, B,
            pending_transfers_tree.packed_transfers).call()

    # settle channel
    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Unlock works after channel is settled
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree.packed_transfers).call_and_transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()
    assert balance_A == pre_balance_A + 9
    assert balance_B == pre_balance_B + 6
    assert balance_contract == pre_balance_contract - values_B.locked_amounts.locked
Exemple #11
0
def test_channel_unlock_registered_expired_lock_refunds(
    web3,
    custom_token,
    token_network,
    secret_registry_contract,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
):
    """ unlock() should refund tokens locked with secrets revealed after the expiration """
    (A, B) = get_accounts(2)
    max_lock_expiration = 3
    settle_timeout = 8

    values_A = ChannelValues(deposit=20, transferred=5)
    values_B = ChannelValues(deposit=30, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(
        web3,
        [1, 3, 5],
        [2, 4],
        min_expiration_delta=max_lock_expiration - 2,
        max_expiration_delta=max_lock_expiration,
    )
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree.transfers))

    # Locks expire
    web3.testing.mine(max_lock_expiration)

    # Secrets are revealed before settlement window, but after expiration
    for (_, _, secrethash, secret) in pending_transfers_tree.unlockable:
        secret_registry_contract.functions.registerSecret(
            secret).call_and_transact({"from": A})
        assert (secret_registry_contract.functions.getSecretRevealBlockHeight(
            secrethash).call() == web3.eth.blockNumber)

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)
    web3.testing.mine(settle_timeout)

    # settle channel
    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Unlock works after channel is settled
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree.packed_transfers).call_and_transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # check that all tokens have been refunded, as locks have expired already
    assert balance_A == pre_balance_A
    assert balance_B == pre_balance_B + values_B.locked_amounts.locked
    assert balance_contract == pre_balance_contract - values_B.locked_amounts.locked
Exemple #12
0
def test_channel_unlock(
    web3,
    custom_token,
    token_network,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
):
    """ unlock() on pending transfers with unlockable and expired locks should
    split the locked amount accordingly, to both parties """
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(deposit=20, transferred=5)
    values_B = ChannelValues(deposit=30, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout)
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree.transfers))

    # Reveal secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree.unlockable)

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)

    # Settlement window must be over before settling the channel
    web3.testing.mine(settle_timeout)

    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    info_B = token_network.functions.getChannelParticipantInfo(
        channel_identifier, B, A).call()
    assert info_B[ParticipantInfoIndex.LOCKSROOT] == values_B.locksroot
    assert info_B[
        ParticipantInfoIndex.LOCKED_AMOUNT] == values_B.locked_amounts.locked

    # Unlock the tokens
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree.packed_transfers).call_and_transact()

    info_B = token_network.functions.getChannelParticipantInfo(
        channel_identifier, B, A).call()
    assert info_B[ParticipantInfoIndex.LOCKSROOT] == EMPTY_LOCKSROOT
    assert info_B[ParticipantInfoIndex.LOCKED_AMOUNT] == 0

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()
    assert balance_A == pre_balance_A + 9
    assert balance_B == pre_balance_B + 6
    assert balance_contract == pre_balance_contract - values_B.locked_amounts.locked
Exemple #13
0
def test_unlock_channel_event(
    web3,
    token_network,
    secret_registry_contract,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
    event_handler,
):
    """ Successful unlock() should cause an UNLOCKED event """
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(deposit=20, transferred=5)
    values_B = ChannelValues(deposit=30, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout + 100)
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree.transfers))

    # Reveal secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree.unlockable)

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)

    # Settlement window must be over before settling the channel
    web3.testing.mine(settle_timeout)

    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    ev_handler = event_handler(token_network)

    # Unlock the tokens
    txn_hash = token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree.packed_transfers).call_and_transact()

    unlocked_amount = get_unlocked_amount(
        secret_registry_contract, pending_transfers_tree.packed_transfers)

    # Add event
    ev_handler.add(
        txn_hash,
        ChannelEvent.UNLOCKED,
        check_channel_unlocked(
            channel_identifier,
            A,
            B,
            values_B.locksroot,
            unlocked_amount,
            values_B.locked_amounts.locked - unlocked_amount,
        ),
    )

    # Check that event was properly emitted
    ev_handler.check()
def test_unlock_channel_event(
        web3,
        token_network,
        secret_registry_contract,
        create_channel,
        channel_deposit,
        get_accounts,
        close_and_update_channel,
        event_handler,
):
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(
        deposit=20,
        transferred=5,
        locked=0,
        locksroot=EMPTY_MERKLE_ROOT,
    )
    values_B = ChannelValues(
        deposit=30,
        transferred=40,
    )

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(A, values_A.deposit, B)
    channel_deposit(B, values_B.deposit, A)

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(web3, [1, 3, 5], [2, 4],
                                                        settle_timeout + 100)
    locksroot_bytes = get_merkle_root(pending_transfers_tree.merkle_tree)
    values_B.locksroot = '0x' + locksroot_bytes.hex()
    values_B.locked = get_locked_amount(pending_transfers_tree.transfers)

    # Reveal secrets before settlement window ends
    for lock in pending_transfers_tree.unlockable:
        secret_registry_contract.functions.registerSecret(lock[3]).transact({'from': A})
        assert secret_registry_contract.functions.getSecretRevealBlockHeight(
            lock[2],
        ).call() == web3.eth.blockNumber

    close_and_update_channel(
        A,
        values_A,
        B,
        values_B,
    )

    # Settlement window must be over before settling the channel
    web3.testing.mine(settle_timeout)

    call_settle(token_network, A, values_A, B, values_B)

    ev_handler = event_handler(token_network)

    # Unlock the tokens
    txn_hash = token_network.functions.unlock(
        A,
        B,
        pending_transfers_tree.packed_transfers,
    ).transact()

    unlocked_amount = get_unlocked_amount(
        secret_registry_contract,
        pending_transfers_tree.packed_transfers,
    )

    # Add event
    ev_handler.add(txn_hash, EVENT_CHANNEL_UNLOCKED, check_channel_unlocked(
        channel_identifier,
        A,
        unlocked_amount,
        values_B.locked - unlocked_amount,
    ))

    # Check that event was properly emitted
    ev_handler.check()
def test_settlement_with_unauthorized_token_transfer(
    web3: Web3,
    get_accounts: Callable,
    custom_token: Contract,
    token_network: Contract,
    assign_tokens: Callable,
    create_channel_and_deposit: Callable,
    withdraw_channel: Callable,
    close_and_update_channel: Callable,
) -> None:
    """A participant transfers some tokens to the contract and so loses them"""
    externally_transferred_amount = 5
    (A, B) = get_accounts(2)
    (vals_A, vals_B) = (
        ChannelValues(deposit=35, withdrawn=10, transferred=0),
        ChannelValues(deposit=40, withdrawn=10, transferred=0),
    )
    vals_A.locksroot = fake_bytes(32, "02")
    vals_B.locksroot = fake_bytes(32, "03")

    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)

    withdraw_channel(channel_identifier, A, vals_A.withdrawn, UINT256_MAX, B)
    withdraw_channel(channel_identifier, B, vals_B.withdrawn, UINT256_MAX, A)

    close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)

    # Assign additional tokens to A
    assign_tokens(A, externally_transferred_amount)
    assert custom_token.functions.balanceOf(
        A).call() >= externally_transferred_amount

    # Fetch onchain balances after settlement
    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # A does a transfer to the token_network without appropriate function call - tokens are lost
    call_and_transact(
        custom_token.functions.transfer(token_network.address,
                                        externally_transferred_amount),
        {"from": A},
    )
    assert custom_token.functions.balanceOf(
        token_network.address).call() == (pre_balance_contract +
                                          externally_transferred_amount)

    mine_blocks(web3, TEST_SETTLE_TIMEOUT_MIN + 1)

    # Compute expected settlement amounts
    settlement = get_settlement_amounts(vals_A, vals_B)

    # Channel is settled
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Fetch onchain balances after settlement
    post_balance_A = custom_token.functions.balanceOf(A).call()
    post_balance_B = custom_token.functions.balanceOf(B).call()
    post_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # A has lost the externally_transferred_amount
    assert (pre_balance_A + settlement.participant1_balance -
            externally_transferred_amount) == post_balance_A

    # B's settlement works correctly
    assert pre_balance_B + settlement.participant2_balance == post_balance_B

    # The externally_transferred_amount stays in the contract
    assert (pre_balance_contract - settlement.participant1_balance -
            settlement.participant2_balance +
            externally_transferred_amount) == post_balance_contract
def test_deposit_wrong_state_fail(
    web3: Web3,
    get_accounts: Callable,
    token_network: Contract,
    create_channel: Callable,
    assign_tokens: Callable,
    create_close_signature_for_no_balance_proof: Callable,
) -> None:
    """ setTotalDeposit() fails on Closed or Settled channels. """
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(deposit=2, transferred=0)
    vals_B = ChannelValues(deposit=2, transferred=0)
    channel_identifier = create_channel(A, B, TEST_SETTLE_TIMEOUT_MIN)[0]
    assign_tokens(A, vals_A.deposit)
    assign_tokens(B, vals_B.deposit)
    call_and_transact(
        token_network.functions.setTotalDeposit(channel_identifier, A,
                                                vals_A.deposit, B),
        {"from": A},
    )
    call_and_transact(
        token_network.functions.setTotalDeposit(channel_identifier, B,
                                                vals_B.deposit, A),
        {"from": B},
    )
    assert (
        vals_A.deposit == token_network.functions.getChannelParticipantInfo(
            channel_identifier, A, B).call()[0])
    assert (
        vals_B.deposit == token_network.functions.getChannelParticipantInfo(
            channel_identifier, B, A).call()[0])

    closing_sig = create_close_signature_for_no_balance_proof(
        A, channel_identifier)

    call_and_transact(
        token_network.functions.closeChannel(
            channel_identifier=channel_identifier,
            non_closing_participant=B,
            closing_participant=A,
            balance_hash=EMPTY_BALANCE_HASH,
            nonce=0,
            additional_hash=EMPTY_ADDITIONAL_HASH,
            non_closing_signature=EMPTY_SIGNATURE,
            closing_signature=closing_sig,
        ),
        {"from": A},
    )

    assign_tokens(A, 10)
    assign_tokens(B, 10)
    vals_A.deposit += 5
    vals_B.deposit += 5
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(channel_identifier, A,
                                                vals_A.deposit,
                                                B).call({"from": A})
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(channel_identifier, B,
                                                vals_B.deposit,
                                                A).call({"from": B})

    mine_blocks(web3, TEST_SETTLE_TIMEOUT_MIN + 1)
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(channel_identifier, A,
                                                vals_A.deposit,
                                                B).call({"from": A})
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(channel_identifier, B,
                                                vals_B.deposit,
                                                A).call({"from": B})
def test_settle_wrong_balance_hash(
    web3,
    get_accounts,
    token_network,
    create_channel_and_deposit,
    close_and_update_channel,
    get_block,
    reveal_secrets,
):
    """ Calling settleChannel() with various wrong arguments and see failures """
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(
        deposit=35,
        withdrawn=0,
        transferred=5,
        claimable_locked=10,
        unclaimable_locked=2,
    )
    vals_B = ChannelValues(
        deposit=40,
        withdrawn=0,
        transferred=15,
        claimable_locked=5,
        unclaimable_locked=4,
    )
    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)

    # Mock pending transfers data for A -> B
    pending_transfers_tree_A = get_pending_transfers_tree(
        web3,
        unlockable_amount=vals_A.claimable_locked,
        expired_amount=vals_A.unclaimable_locked,
    )
    vals_A.locksroot = pending_transfers_tree_A.merkle_root
    # Reveal A's secrets.
    reveal_secrets(A, pending_transfers_tree_A.unlockable)

    # Mock pending transfers data for B -> A
    pending_transfers_tree_B = get_pending_transfers_tree(
        web3,
        unlockable_amount=vals_B.claimable_locked,
        expired_amount=vals_B.unclaimable_locked,
    )
    vals_B.locksroot = pending_transfers_tree_B.merkle_root
    # Reveal B's secrets
    reveal_secrets(B, pending_transfers_tree_B.unlockable)

    close_and_update_channel(
        channel_identifier,
        A,
        vals_A,
        B,
        vals_B,
    )

    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN)

    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_A, A, vals_B)

    vals_A_fail = deepcopy(vals_A)
    vals_A_fail.transferred += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.transferred = 0
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.transferred = MAX_UINT256
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_B, A,
                    vals_A_fail)

    vals_A_fail = deepcopy(vals_A)
    vals_A_fail.locked += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.locked = 0
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.locked = MAX_UINT256
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_B, A,
                    vals_A_fail)

    vals_A_fail = deepcopy(vals_A)
    vals_A_fail.locksroot = EMPTY_LOCKSROOT
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.locksroot = fake_bytes(32, '01')
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_B_fail = deepcopy(vals_B)
    vals_B_fail.transferred += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail.transferred = 0
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_B_fail, A,
                    vals_A)

    vals_B_fail.transferred = MAX_UINT256
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail = deepcopy(vals_B)
    vals_B_fail.locked += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail.locked = 0
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_B_fail, A,
                    vals_A)

    vals_B_fail.locked = MAX_UINT256
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail = deepcopy(vals_B)
    vals_B_fail.locksroot = EMPTY_LOCKSROOT
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail.locksroot = fake_bytes(32, '01')
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    # Channel is settled
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)
def test_channel_settle_invalid_balance_proof_values(
    web3,
    get_accounts,
    custom_token,
    token_network,
    create_channel_and_deposit,
    withdraw_channel,
    close_and_update_channel,
    settle_state_tests,
    reveal_secrets,
    channel_test_values,
):
    """ Check the settlement results with invalid balance proofs """
    (A, B, C, D) = get_accounts(4)
    (vals_A, vals_B) = channel_test_values

    # We just need to test that settleChannel does not fail
    # We cannot ensure correctly computed final balances if the balance proofs
    # are invalid.
    # We can just test that participants do not get more tokens than the channel deposit

    # We make sure the contract has more tokens than A, B will deposit
    create_channel_and_deposit(C, D, 40, 60)

    # Start channel lifecycle for A, B
    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)
    withdraw_channel(channel_identifier, A, vals_A.withdrawn, B)
    withdraw_channel(channel_identifier, B, vals_B.withdrawn, A)

    # For the purpose of this test, it is not important when the secrets are revealed,
    # as long as the secrets connected to pending transfers that should be finalized,
    # are revealed before their expiration.

    # Mock pending transfers data for A -> B
    pending_transfers_tree_A = get_pending_transfers_tree(
        web3,
        unlockable_amount=vals_A.locked_amounts.claimable_locked,
        expired_amount=vals_A.locked_amounts.unclaimable_locked,
    )
    vals_A.locksroot = pending_transfers_tree_A.merkle_root
    # Reveal A's secrets.
    reveal_secrets(A, pending_transfers_tree_A.unlockable)

    # Mock pending transfers data for B -> A
    pending_transfers_tree_B = get_pending_transfers_tree(
        web3,
        unlockable_amount=vals_B.locked_amounts.claimable_locked,
        expired_amount=vals_B.locked_amounts.unclaimable_locked,
    )
    vals_B.locksroot = pending_transfers_tree_B.merkle_root
    # Reveal B's secrets
    reveal_secrets(B, pending_transfers_tree_B.unlockable)

    close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)

    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN + 1)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # We do the balance & state tests here for each channel and also compare with
    # the expected settlement amounts
    settle_state_tests(
        channel_identifier,
        A,
        vals_A,
        B,
        vals_B,
        pre_balance_A,
        pre_balance_B,
        pre_balance_contract,
    )
def test_channel_unlock_with_a_large_expiration(
        web3,
        custom_token,
        token_network,
        secret_registry_contract,
        create_channel,
        channel_deposit,
        get_accounts,
        close_and_update_channel,
):
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(
        deposit=20,
        transferred=5,
        locked=0,
        locksroot=EMPTY_MERKLE_ROOT,
    )
    values_B = ChannelValues(
        deposit=30,
        transferred=40,
    )

    # Create channel and deposit
    create_channel(A, B, settle_timeout)[0]
    channel_deposit(A, values_A.deposit, B)
    channel_deposit(B, values_B.deposit, A)

    # Mock pending transfers data with large expiration date
    pending_transfers_tree = get_pending_transfers_tree(web3, [1, 3, 5], [2, 4],
                                                        settle_timeout + 100)
    locksroot_bytes = get_merkle_root(pending_transfers_tree.merkle_tree)
    values_B.locksroot = '0x' + locksroot_bytes.hex()
    values_B.locked = get_locked_amount(pending_transfers_tree.transfers)

    # Reveal secrets before settlement window ends
    for lock in pending_transfers_tree.unlockable:
        secret_registry_contract.functions.registerSecret(lock[3]).transact({'from': A})
        assert secret_registry_contract.functions.getSecretRevealBlockHeight(
            lock[2],
        ).call() == web3.eth.blockNumber

    close_and_update_channel(
        A,
        values_A,
        B,
        values_B,
    )

    # Settle channel after a "long" time
    web3.testing.mine(settle_timeout + 50)

    call_settle(token_network, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(token_network.address).call()

    # Unlock the tokens must still work
    token_network.functions.unlock(
        A,
        B,
        pending_transfers_tree.packed_transfers,
    ).transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(token_network.address).call()
    assert balance_A == pre_balance_A + 9
    assert balance_B == pre_balance_B + 6
    assert balance_contract == pre_balance_contract - values_B.locked
def test_channel_unlock_both_participants(
        web3,
        custom_token,
        token_network,
        secret_registry_contract,
        create_channel,
        channel_deposit,
        get_accounts,
        close_and_update_channel,
        reveal_secrets,
):
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(
        deposit=100,
        transferred=5,
    )
    values_B = ChannelValues(
        deposit=100,
        transferred=40,
    )

    # Create channel and deposit
    create_channel(A, B, settle_timeout)[0]
    channel_deposit(A, values_A.deposit, B)
    channel_deposit(B, values_B.deposit, A)

    # Mock pending transfers data for A
    pending_transfers_tree_A = get_pending_transfers_tree(web3, [1, 3, 5], [2, 4], settle_timeout)
    locksroot_bytes = get_merkle_root(pending_transfers_tree_A.merkle_tree)
    values_B.locksroot = '0x' + locksroot_bytes.hex()
    values_B.locked = get_locked_amount(pending_transfers_tree_A.transfers)

    # Reveal A's secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree_A.unlockable)

    # Mock pending transfers data for B
    pending_transfers_tree_B = get_pending_transfers_tree(web3, [2, 4, 6], [5, 10], settle_timeout)
    locksroot_bytes = get_merkle_root(pending_transfers_tree_B.merkle_tree)
    values_A.locksroot = '0x' + locksroot_bytes.hex()
    values_A.locked = get_locked_amount(pending_transfers_tree_B.transfers)

    # Reveal B's secrets before settlement window ends
    for lock in pending_transfers_tree_B.unlockable:
        secret_registry_contract.functions.registerSecret(lock[3]).transact({'from': B})
        assert secret_registry_contract.functions.getSecretRevealBlockHeight(
            lock[2],
        ).call() == web3.eth.blockNumber

    close_and_update_channel(
        A,
        values_A,
        B,
        values_B,
    )

    # Settle channel
    web3.testing.mine(settle_timeout)

    call_settle(token_network, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(token_network.address).call()

    # A unlock's
    token_network.functions.unlock(
        A,
        B,
        pending_transfers_tree_A.packed_transfers,
    ).transact()

    # B unlock's
    token_network.functions.unlock(
        B,
        A,
        pending_transfers_tree_B.packed_transfers,
    ).transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(token_network.address).call()
    unlockable_A = get_unlocked_amount(
        secret_registry_contract,
        pending_transfers_tree_A.packed_transfers,
    )
    expired_A = get_locked_amount(pending_transfers_tree_A.expired)
    unlockable_B = get_unlocked_amount(
        secret_registry_contract,
        pending_transfers_tree_B.packed_transfers,
    )
    expired_B = get_locked_amount(pending_transfers_tree_B.expired)

    # check that A and B both received the expected amounts
    assert balance_contract == pre_balance_contract - values_B.locked - values_A.locked
    assert balance_A == pre_balance_A + unlockable_A + expired_B
    assert balance_B == pre_balance_B + unlockable_B + expired_A
def test_channel_unlock_before_settlement_fails(
        web3,
        custom_token,
        token_network,
        secret_registry_contract,
        create_channel,
        channel_deposit,
        get_accounts,
        close_and_update_channel,
):
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(
        deposit=20,
        transferred=5,
        locked=0,
        locksroot=EMPTY_MERKLE_ROOT,
    )
    values_B = ChannelValues(
        deposit=30,
        transferred=40,
    )

    # Create channel and deposit
    create_channel(A, B, settle_timeout)[0]
    channel_deposit(A, values_A.deposit, B)
    channel_deposit(B, values_B.deposit, A)

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(web3, [1, 3, 5], [2, 4], settle_timeout)
    locksroot_bytes = get_merkle_root(pending_transfers_tree.merkle_tree)
    values_B.locksroot = '0x' + locksroot_bytes.hex()
    values_B.locked = get_locked_amount(pending_transfers_tree.transfers)

    # Reveal secrets before settlement window ends
    for lock in pending_transfers_tree.unlockable:
        secret_registry_contract.functions.registerSecret(lock[3]).transact({'from': A})
        assert secret_registry_contract.functions.getSecretRevealBlockHeight(
            lock[2],
        ).call() == web3.eth.blockNumber

    close_and_update_channel(
        A,
        values_A,
        B,
        values_B,
    )

    # Unlock fails before settlement window is over and channel is not settled
    with pytest.raises(TransactionFailed):
        token_network.functions.unlock(
            A,
            B,
            pending_transfers_tree.packed_transfers,
        ).transact()

    # Settlement window must be over before settling the channel
    web3.testing.mine(settle_timeout)
    # Unlock fails before settle is called
    with pytest.raises(TransactionFailed):
        token_network.functions.unlock(
            A,
            B,
            pending_transfers_tree.packed_transfers,
        ).transact()

    # settle channel
    call_settle(token_network, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(token_network.address).call()

    # Unlock works after channel is settled
    token_network.functions.unlock(
        A,
        B,
        pending_transfers_tree.packed_transfers,
    ).transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(token_network.address).call()
    assert balance_A == pre_balance_A + 9
    assert balance_B == pre_balance_B + 6
    assert balance_contract == pre_balance_contract - values_B.locked
def test_deprecation_switch_settle(
    web3,
    get_accounts,
    token_network,
    custom_token,
    reveal_secrets,
    create_channel,
    channel_deposit,
    close_and_update_channel,
):
    deprecation_executor = token_network.functions.deprecation_executor().call(
    )
    (A, B) = get_accounts(2)
    deposit = 100

    (vals_A, vals_B) = (
        ChannelValues(
            deposit=deposit,
            withdrawn=0,
            transferred=5,
            claimable_locked=2,
            unclaimable_locked=4,
        ),
        ChannelValues(
            deposit=deposit,
            withdrawn=0,
            transferred=10,
            claimable_locked=4,
            unclaimable_locked=6,
        ),
    )

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    channel_identifier = create_channel(A, B)[0]
    channel_deposit(channel_identifier, A, vals_A.deposit, B)
    channel_deposit(channel_identifier, B, vals_B.deposit, A)

    # Mock pending transfers data for A -> B
    pending_transfers_tree_A = get_pending_transfers_tree(
        web3,
        unlockable_amount=vals_A.claimable_locked,
        expired_amount=vals_A.unclaimable_locked,
    )
    vals_A.locksroot = pending_transfers_tree_A.merkle_root
    # Reveal A's secrets.
    reveal_secrets(A, pending_transfers_tree_A.unlockable)

    # Mock pending transfers data for B -> A
    pending_transfers_tree_B = get_pending_transfers_tree(
        web3,
        unlockable_amount=vals_B.claimable_locked,
        expired_amount=vals_B.unclaimable_locked,
    )
    vals_B.locksroot = pending_transfers_tree_B.merkle_root
    # Reveal B's secrets
    reveal_secrets(B, pending_transfers_tree_B.unlockable)

    # Set the deprecation switch to true
    token_network.functions.deprecate().transact({
        'from': deprecation_executor,
    })
    assert token_network.functions.safety_deprecation_switch().call() is True

    # We need to make sure we can still close, settle & unlock the channels
    close_and_update_channel(
        channel_identifier,
        A,
        vals_A,
        B,
        vals_B,
    )
    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN)

    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Unlock B's pending transfers that were sent to A
    token_network.functions.unlock(
        channel_identifier,
        A,
        B,
        pending_transfers_tree_B.packed_transfers,
    ).transact()

    # Unlock A's pending transfers that were sent to B
    token_network.functions.unlock(
        channel_identifier,
        B,
        A,
        pending_transfers_tree_A.packed_transfers,
    ).transact()

    assert custom_token.functions.balanceOf(A).call() == pre_balance_A + 107
    assert custom_token.functions.balanceOf(B).call() == pre_balance_B + 93
    assert custom_token.functions.balanceOf(
        token_network.address, ).call() == pre_balance_contract
    def f(participants, channel_values, expected_final_balance_A0,
          expected_final_balance_B0):
        (A, B) = participants
        (vals_A, vals_B, balance_proof_type) = channel_values
        assert were_balance_proofs_valid(vals_A, vals_B)

        # Start channel lifecycle
        channel_identifier = create_channel_and_deposit(
            A, B, vals_A.deposit, vals_B.deposit)
        withdraw_channel(channel_identifier, A, vals_A.withdrawn, B)
        withdraw_channel(channel_identifier, B, vals_B.withdrawn, A)

        # For the purpose of this test, it is not important when the secrets are revealed,
        # as long as the secrets connected to pending transfers that should be finalized,
        # are revealed before their expiration.

        # Mock pending transfers data for A -> B
        pending_transfers_tree_A = get_pending_transfers_tree(
            web3,
            unlockable_amount=vals_A.locked_amounts.claimable_locked,
            expired_amount=vals_A.locked_amounts.unclaimable_locked,
        )
        vals_A.locksroot = pending_transfers_tree_A.merkle_root
        # Reveal A's secrets.
        reveal_secrets(A, pending_transfers_tree_A.unlockable)

        # Mock pending transfers data for B -> A
        pending_transfers_tree_B = get_pending_transfers_tree(
            web3,
            unlockable_amount=vals_B.locked_amounts.claimable_locked,
            expired_amount=vals_B.locked_amounts.unclaimable_locked,
        )
        vals_B.locksroot = pending_transfers_tree_B.merkle_root
        # Reveal B's secrets
        reveal_secrets(B, pending_transfers_tree_B.unlockable)

        close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)

        web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN)

        pre_balance_A = custom_token.functions.balanceOf(A).call()
        pre_balance_B = custom_token.functions.balanceOf(B).call()
        pre_balance_contract = custom_token.functions.balanceOf(
            token_network.address).call()

        call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

        # We do the balance & state tests here for each channel and also compare with
        # the expected settlement amounts
        settle_state_tests(
            channel_identifier,
            A,
            vals_A,
            B,
            vals_B,
            pre_balance_A,
            pre_balance_B,
            pre_balance_contract,
        )

        # We compute again the settlement amounts here to compare with the other channel
        # settlement test values, which should be equal

        # Calculate how much A and B should receive
        settlement_equivalent = get_settlement_amounts(vals_A, vals_B)

        # Calculate how much A and B receive according to onchain computation
        settlement_onchain_equivalent = get_onchain_settlement_amounts(
            vals_A, vals_B)

        assert (settlement_equivalent.participant1_balance ==
                settlement_onchain_equivalent.participant1_balance)
        assert (settlement_equivalent.participant2_balance ==
                settlement_onchain_equivalent.participant2_balance)
        assert (settlement_equivalent.participant1_locked ==
                settlement_onchain_equivalent.participant1_locked)
        assert (settlement_equivalent.participant2_locked ==
                settlement_onchain_equivalent.participant2_locked)

        assert (get_unlocked_amount(secret_registry_contract,
                                    pending_transfers_tree_B.packed_transfers)
                == vals_B.locked_amounts.claimable_locked)

        # A unlocks B's pending transfers
        info_B = token_network.functions.getChannelParticipantInfo(
            channel_identifier, B, A).call()
        assert (settlement_equivalent.participant2_locked == info_B[
            ParticipantInfoIndex.LOCKED_AMOUNT])

        if info_B[ParticipantInfoIndex.LOCKED_AMOUNT] == 0:
            with pytest.raises(TransactionFailed):
                token_network.functions.unlock(
                    channel_identifier, A, B,
                    pending_transfers_tree_B.packed_transfers).call()
        else:
            token_network.functions.unlock(
                channel_identifier, A, B,
                pending_transfers_tree_B.packed_transfers).call_and_transact()

        # The locked amount should have been removed from contract storage
        info_B = token_network.functions.getChannelParticipantInfo(
            channel_identifier, B, A).call()
        assert info_B[ParticipantInfoIndex.LOCKED_AMOUNT] == 0
        assert info_B[ParticipantInfoIndex.LOCKSROOT] == EMPTY_LOCKSROOT

        # B unlocks A's pending transfers
        info_A = token_network.functions.getChannelParticipantInfo(
            channel_identifier, A, B).call()
        assert (settlement_equivalent.participant1_locked == info_A[
            ParticipantInfoIndex.LOCKED_AMOUNT])

        if info_A[ParticipantInfoIndex.LOCKED_AMOUNT] == 0:
            with pytest.raises(TransactionFailed):
                token_network.functions.unlock(
                    channel_identifier, B, A,
                    pending_transfers_tree_A.packed_transfers).call()
        else:
            token_network.functions.unlock(
                channel_identifier, B, A,
                pending_transfers_tree_A.packed_transfers).call_and_transact()

        # The locked amount should have been removed from contract storage
        info_A = token_network.functions.getChannelParticipantInfo(
            channel_identifier, A, B).call()
        assert info_A[ParticipantInfoIndex.LOCKED_AMOUNT] == 0
        assert info_A[ParticipantInfoIndex.LOCKSROOT] == EMPTY_LOCKSROOT

        # Do the post settlement and unlock tests for valid balance proofs
        balance_A = custom_token.functions.balanceOf(A).call()
        balance_B = custom_token.functions.balanceOf(B).call()

        # We MUST ensure balance correctness for valid last balance proofs
        if balance_proof_type == "valid":
            # Calculate how much A and B should receive after the channel is settled and
            # unlock is called by both.
            (
                expected_final_balance_A,
                expected_final_balance_B,
            ) = get_expected_after_settlement_unlock_amounts(vals_A, vals_B)
            expected_balance_A = pre_balance_A + expected_final_balance_A
            expected_balance_B = pre_balance_B + expected_final_balance_B

            assert balance_A == expected_balance_A
            assert balance_B <= expected_balance_B

        # For balance proofs where one of them is old, we need to compare with the expected
        # final balances for the valid last balance proofs
        expected_balance_A = pre_balance_A + expected_final_balance_A0
        expected_balance_B = pre_balance_B + expected_final_balance_B0

        # Tests for when B has submitted an old balance proof for A
        # A must not receive less tokens than expected with a valid last balance proof
        # B must not receive more tokens than expected with a valid last balance proof
        if balance_proof_type == "old_last":
            assert balance_A >= expected_balance_A
            assert balance_B <= expected_balance_B

        # Tests for when A has submitted an old balance proof for B
        # A must not receive more tokens than expected with a valid last balance proof
        # B must not receive less tokens than expected with a valid last balance proof
        if balance_proof_type == "last_old":
            assert balance_A <= expected_balance_A
            assert balance_B >= expected_balance_B

        # Regardless of the tokens received by the two participants, we must make sure tokens
        # are not stolen from the other channels. And we must make sure tokens are not locked in
        # the contract after the entire channel cycle is finalized.
        final_contract_balance = custom_token.functions.balanceOf(
            token_network.address).call()
        assert final_contract_balance == pre_balance_contract - get_total_available_deposit(
            vals_A, vals_B)
        assert custom_token.functions.balanceOf(
            token_network.address).call() == (
                pre_balance_contract -
                (expected_final_balance_A0 + expected_final_balance_B0))
def test_settle_channel_state(
    web3,
    get_accounts,
    custom_token,
    token_network,
    create_channel_and_deposit,
    withdraw_channel,
    close_and_update_channel,
    settle_state_tests,
    channel_test_values,
):
    number_of_channels = 5
    accounts = get_accounts(2 * number_of_channels)
    (vals_A0, vals_B0) = channel_test_values

    # We mimic old balance proofs here, with a high locked amount and lower transferred amount
    # We expect to have the same settlement values as the original values

    def equivalent_transfers(balance_proof):
        new_balance_proof = deepcopy(balance_proof)
        new_balance_proof.locked = randint(
            balance_proof.locked,
            balance_proof.transferred + balance_proof.locked,
        )
        new_balance_proof.transferred = (balance_proof.transferred +
                                         balance_proof.locked -
                                         new_balance_proof.locked)
        return new_balance_proof

    vals_A_reversed = deepcopy(vals_A0)
    vals_A_reversed.locked = vals_A0.transferred
    vals_A_reversed.transferred = vals_A0.locked

    vals_B_reversed = deepcopy(vals_B0)
    vals_B_reversed.locked = vals_B0.transferred
    vals_B_reversed.transferred = vals_B0.locked

    new_values = [
        (vals_A0, vals_B0),
        (vals_A_reversed, vals_B_reversed),
    ] + [
        sorted(
            [
                equivalent_transfers(vals_A0),
                equivalent_transfers(vals_B0),
            ],
            key=lambda x: x.transferred + x.locked,
            reverse=False,
        ) for no in range(0, number_of_channels - 1)
    ]

    # Calculate how much A and B should receive
    settlement = get_settlement_amounts(vals_A0, vals_B0)
    # Calculate how much A and B receive according to onchain computation
    settlement2 = get_onchain_settlement_amounts(vals_A0, vals_B0)

    for no in range(0, number_of_channels + 1):
        A = accounts[no]
        B = accounts[no + 1]
        (vals_A, vals_B) = new_values[no]
        vals_A.locksroot = fake_bytes(32, '02')
        vals_B.locksroot = fake_bytes(32, '03')

        create_channel_and_deposit(A, B, vals_A.deposit, vals_B.deposit)

        withdraw_channel(A, vals_A.withdrawn, B)
        withdraw_channel(B, vals_B.withdrawn, A)

        close_and_update_channel(
            A,
            vals_A,
            B,
            vals_B,
        )

        web3.testing.mine(SETTLE_TIMEOUT_MIN)

        pre_balance_A = custom_token.functions.balanceOf(A).call()
        pre_balance_B = custom_token.functions.balanceOf(B).call()
        pre_balance_contract = custom_token.functions.balanceOf(
            token_network.address).call()

        call_settle(token_network, A, vals_A, B, vals_B)

        # We do the balance & state tests here for each channel and also compare with
        # the expected settlement amounts
        settle_state_tests(
            A,
            vals_A,
            B,
            vals_B,
            pre_balance_A,
            pre_balance_B,
            pre_balance_contract,
        )

        # We compute again the settlement amounts here to compare with the other channel
        # settlement test values, which should be equal

        # Calculate how much A and B should receive
        settlement_equivalent = get_settlement_amounts(vals_A, vals_B)
        assert (settlement.participant1_balance +
                settlement.participant2_locked ==
                settlement_equivalent.participant1_balance +
                settlement_equivalent.participant2_locked)
        assert (settlement.participant2_balance +
                settlement.participant1_locked ==
                settlement_equivalent.participant2_balance +
                settlement_equivalent.participant1_locked)

        # Calculate how much A and B receive according to onchain computation
        settlement2_equivalent = get_onchain_settlement_amounts(vals_A, vals_B)
        assert (settlement2.participant1_balance +
                settlement2.participant2_locked ==
                settlement2_equivalent.participant1_balance +
                settlement2_equivalent.participant2_locked)
        assert (settlement2.participant2_balance +
                settlement2.participant1_locked ==
                settlement2_equivalent.participant2_balance +
                settlement2_equivalent.participant1_locked)
def test_settle_channel_state(
    web3,
    get_accounts,
    custom_token,
    token_network,
    create_channel_and_deposit,
    withdraw_channel,
    close_and_update_channel,
    settle_state_tests,
):
    """ settleChannel() with some balance proofs """
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(
        deposit=40,
        withdrawn=10,
        transferred=20020,
        claimable_locked=3,
        unclaimable_locked=4,
    )
    vals_B = ChannelValues(
        deposit=35,
        withdrawn=5,
        transferred=20030,
        claimable_locked=2,
        unclaimable_locked=3,
    )

    pending_transfers_tree_A = get_pending_transfers_tree(
        web3,
        unlockable_amount=vals_A.claimable_locked,
        expired_amount=vals_A.unclaimable_locked,
    )
    pending_transfers_tree_B = get_pending_transfers_tree(
        web3,
        unlockable_amount=vals_B.claimable_locked,
        expired_amount=vals_B.unclaimable_locked,
    )
    vals_A.locksroot = pending_transfers_tree_A.merkle_root
    vals_B.locksroot = pending_transfers_tree_B.merkle_root

    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)
    withdraw_channel(channel_identifier, A, vals_A.withdrawn, B)
    withdraw_channel(channel_identifier, B, vals_B.withdrawn, A)
    close_and_update_channel(
        channel_identifier,
        A,
        vals_A,
        B,
        vals_B,
    )

    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Balance & state tests
    settle_state_tests(
        channel_identifier,
        A,
        vals_A,
        B,
        vals_B,
        pre_balance_A,
        pre_balance_B,
        pre_balance_contract,
    )

    # Some manual checks for the final balances, in case the settlement algorithms
    # used in `settle_state_tests` are incorrect

    # FIXME after setTotalWithdraw is implemented again
    post_balance_A = pre_balance_A + 33
    post_balance_B = pre_balance_B + 15
    post_balance_contract = pre_balance_contract - 48

    # FIXME after setTotalWithdraw is implemented again
    # we add the withdrawn amount here, because it was never withdrawn due to the
    # removal of setTotalWithdraw
    assert custom_token.functions.balanceOf(A).call() == post_balance_A + 10
    assert custom_token.functions.balanceOf(B).call() == post_balance_B + 5
    assert custom_token.functions.balanceOf(
        token_network.address, ).call() == post_balance_contract - 15
Exemple #26
0
def test_channel_unlock(
    web3,
    custom_token,
    token_network,
    secret_registry_contract,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
    event_handler,
):
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(
        deposit=20,
        transferred=5,
        locked=0,
        locksroot=EMPTY_MERKLE_ROOT,
    )
    values_B = ChannelValues(
        deposit=30,
        transferred=40,
    )

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout)
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked = get_locked_amount(pending_transfers_tree.transfers)

    # Reveal secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree.unlockable)

    close_and_update_channel(
        channel_identifier,
        A,
        values_A,
        B,
        values_B,
    )

    # Settlement window must be over before settling the channel
    web3.testing.mine(settle_timeout)

    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Unlock the tokens
    token_network.functions.unlock(
        channel_identifier,
        A,
        B,
        pending_transfers_tree.packed_transfers,
    ).transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()
    assert balance_A == pre_balance_A + 9
    assert balance_B == pre_balance_B + 6
    assert balance_contract == pre_balance_contract - values_B.locked
def test_settle_channel_state(
    web3: Web3,
    get_accounts: Callable,
    custom_token: Contract,
    token_network: Contract,
    create_channel_and_deposit: Callable,
    withdraw_channel: Callable,
    close_and_update_channel: Callable,
    settle_state_tests: Callable,
) -> None:
    """settleChannel() with some balance proofs"""
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(
        deposit=40,
        withdrawn=10,
        transferred=20020,
        locked_amounts=LockedAmounts(claimable_locked=3, unclaimable_locked=4),
    )
    vals_B = ChannelValues(
        deposit=35,
        withdrawn=5,
        transferred=20030,
        locked_amounts=LockedAmounts(claimable_locked=2, unclaimable_locked=3),
    )

    pending_transfers_tree_A = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_A.locked_amounts.claimable_locked,
        expired_amount=vals_A.locked_amounts.unclaimable_locked,
    )
    pending_transfers_tree_B = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_B.locked_amounts.claimable_locked,
        expired_amount=vals_B.locked_amounts.unclaimable_locked,
    )
    vals_A.locksroot = pending_transfers_tree_A.hash_of_packed_transfers
    vals_B.locksroot = pending_transfers_tree_B.hash_of_packed_transfers

    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)
    withdraw_channel(channel_identifier, A, vals_A.withdrawn, UINT256_MAX, B)
    withdraw_channel(channel_identifier, B, vals_B.withdrawn, UINT256_MAX, A)
    close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)

    mine_blocks(web3, TEST_SETTLE_TIMEOUT_MIN + 1)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Balance & state tests
    settle_state_tests(
        channel_identifier,
        A,
        vals_A,
        B,
        vals_B,
        pre_balance_A,
        pre_balance_B,
        pre_balance_contract,
    )

    # Some manual checks for the final balances, in case the settlement algorithms
    # used in `settle_state_tests` are incorrect

    # FIXME after setTotalWithdraw is implemented again
    post_balance_A = pre_balance_A + 33
    post_balance_B = pre_balance_B + 15
    post_balance_contract = pre_balance_contract - 48

    assert custom_token.functions.balanceOf(A).call() == post_balance_A
    assert custom_token.functions.balanceOf(B).call() == post_balance_B
    assert custom_token.functions.balanceOf(
        token_network.address).call() == post_balance_contract
Exemple #28
0
def test_channel_unlock_expired_lock_refunds(
    web3,
    custom_token,
    token_network,
    secret_registry_contract,
    create_channel,
    channel_deposit,
    get_accounts,
    reveal_secrets,
    close_and_update_channel,
):
    (A, B) = get_accounts(2)
    max_lock_expiration = 3
    settle_timeout = 8

    values_A = ChannelValues(
        deposit=20,
        transferred=5,
        locked=0,
        locksroot=EMPTY_MERKLE_ROOT,
    )
    values_B = ChannelValues(
        deposit=30,
        transferred=40,
    )

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(
        web3,
        [1, 3, 5],
        [2, 4],
        min_expiration_delta=max_lock_expiration - 2,
        max_expiration_delta=max_lock_expiration,
    )
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked = get_locked_amount(pending_transfers_tree.transfers)

    # Locks expire
    web3.testing.mine(max_lock_expiration)

    # Secrets are revealed before settlement window, but after expiration
    reveal_secrets(A, pending_transfers_tree.unlockable)

    close_and_update_channel(
        channel_identifier,
        A,
        values_A,
        B,
        values_B,
    )
    web3.testing.mine(settle_timeout)

    # settle channel
    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Unlock works after channel is settled
    token_network.functions.unlock(
        channel_identifier,
        A,
        B,
        pending_transfers_tree.packed_transfers,
    ).transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # check that all tokens have been refunded, as locks have expired already
    assert balance_A == pre_balance_A
    assert balance_B == pre_balance_B + values_B.locked
    assert balance_contract == pre_balance_contract - values_B.locked
def test_settle_wrong_balance_hash(
    web3: Web3,
    get_accounts: Callable,
    token_network: Contract,
    create_channel_and_deposit: Callable,
    close_and_update_channel: Callable,
    reveal_secrets: Callable,
) -> None:
    """Calling settleChannel() with various wrong arguments and see failures"""
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(
        deposit=35,
        withdrawn=0,
        transferred=5,
        locked_amounts=LockedAmounts(claimable_locked=10,
                                     unclaimable_locked=2),
    )
    vals_B = ChannelValues(
        deposit=40,
        withdrawn=0,
        transferred=15,
        locked_amounts=LockedAmounts(claimable_locked=5, unclaimable_locked=4),
    )
    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)

    # Mock pending transfers data for A -> B
    pending_transfers_tree_A = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_A.locked_amounts.claimable_locked,
        expired_amount=vals_A.locked_amounts.unclaimable_locked,
    )
    vals_A.locksroot = pending_transfers_tree_A.hash_of_packed_transfers
    # Reveal A's secrets.
    reveal_secrets(A, pending_transfers_tree_A.unlockable)

    # Mock pending transfers data for B -> A
    pending_transfers_tree_B = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_B.locked_amounts.claimable_locked,
        expired_amount=vals_B.locked_amounts.unclaimable_locked,
    )
    vals_B.locksroot = pending_transfers_tree_B.hash_of_packed_transfers
    # Reveal B's secrets
    reveal_secrets(B, pending_transfers_tree_B.unlockable)

    close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)

    mine_blocks(web3, TEST_SETTLE_TIMEOUT_MIN + 1)

    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_A, A, vals_B)

    vals_A_fail = deepcopy(vals_A)
    vals_A_fail.transferred += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.transferred = 0
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.transferred = UINT256_MAX
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_B, A,
                    vals_A_fail)

    vals_A_fail = deepcopy(vals_A)
    vals_A_fail.locked_amounts.claimable_locked += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.locked_amounts.claimable_locked = 0
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.locked_amounts.unclaimable_locked = 0
    vals_A_fail.locked_amounts.claimable_locked = UINT256_MAX
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_B, A,
                    vals_A_fail)

    vals_A_fail = deepcopy(vals_A)
    vals_A_fail.locksroot = LOCKSROOT_OF_NO_LOCKS
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.locksroot = fake_bytes(32, "01")
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_B_fail = deepcopy(vals_B)
    vals_B_fail.transferred += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail.transferred = 0
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_B_fail, A,
                    vals_A)

    vals_B_fail.transferred = UINT256_MAX
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail = deepcopy(vals_B)
    vals_B_fail.locked_amounts.claimable_locked += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail.locked_amounts.claimable_locked = 0
    with pytest.raises(AssertionError):
        call_settle(token_network, channel_identifier, B, vals_B_fail, A,
                    vals_A)

    vals_B_fail.locked_amounts.unclaimable_locked = 0
    vals_B_fail.locked_amounts.claimable_locked = UINT256_MAX
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail = deepcopy(vals_B)
    vals_B_fail.locksroot = LOCKSROOT_OF_NO_LOCKS
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail.locksroot = fake_bytes(32, "01")
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    # Channel is settled
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)
Exemple #30
0
def test_deposit_wrong_state_fail(
        web3,
        get_accounts,
        token_network,
        create_channel,
        assign_tokens,
        close_and_update_channel,
):
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(deposit=2, transferred=0, locked=0)
    vals_B = ChannelValues(deposit=2, transferred=0, locked=0)
    channel_identifier = create_channel(A, B, TEST_SETTLE_TIMEOUT_MIN)[0]
    assign_tokens(A, vals_A.deposit)
    assign_tokens(B, vals_B.deposit)
    token_network.functions.setTotalDeposit(
        channel_identifier,
        A,
        vals_A.deposit,
        B,
    ).transact({'from': A})
    token_network.functions.setTotalDeposit(
        channel_identifier,
        B,
        vals_B.deposit,
        A,
    ).transact({'from': B})

    token_network.functions.closeChannel(
        channel_identifier,
        B,
        EMPTY_BALANCE_HASH,
        0,
        EMPTY_ADDITIONAL_HASH,
        EMPTY_SIGNATURE,
    ).transact({'from': A})

    assign_tokens(A, 10)
    assign_tokens(B, 10)
    vals_A.deposit += 5
    vals_B.deposit += 5
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(
            channel_identifier,
            A,
            vals_A.deposit,
            B,
        ).transact({'from': A})
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(
            channel_identifier,
            B,
            vals_B.deposit,
            A,
        ).transact({'from': B})

    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN)
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(
            channel_identifier,
            A,
            vals_A.deposit,
            B,
        ).transact({'from': A})
    with pytest.raises(TransactionFailed):
        token_network.functions.setTotalDeposit(
            channel_identifier,
            B,
            vals_B.deposit,
            A,
        ).transact({'from': B})