def test_channel_unlock_with_a_large_expiration(
    web3: Web3,
    custom_token: Contract,
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    close_and_update_channel: Callable,
    reveal_secrets: Callable,
) -> None:
    """ 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.hash_of_packed_transfers
    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
Example #2
0
def print_gas_channel_cycle(
    web3: Web3,
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    withdraw_channel: Callable,
    secret_registry_contract: Contract,
    get_accounts: Callable,
    print_gas: Callable,
    create_balance_proof: Callable,
    create_balance_proof_countersignature: Callable,
) -> None:
    """Abusing pytest to print gas costs of TokenNetwork's operations"""
    (A, B, C, D) = get_accounts(4)
    settle_timeout = 11

    (channel_identifier, txn_hash) = create_channel(A, B, settle_timeout)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".openChannel")

    (_, txn_hash) = create_channel(C, D, settle_timeout)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".openChannel")

    txn_hash = channel_deposit(channel_identifier, A, 20, B)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".setTotalDeposit")

    txn_hash = channel_deposit(channel_identifier, B, 10, A)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".setTotalDeposit")

    txn_hash = withdraw_channel(channel_identifier, A, 5, UINT256_MAX, B)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".setTotalWithdraw")

    pending_transfers_tree1 = get_pending_transfers_tree(
        web3, [1, 1, 2, 3], [2, 1])
    locksroot1 = pending_transfers_tree1.hash_of_packed_transfers
    locked_amount1 = get_locked_amount(pending_transfers_tree1.transfers)

    pending_transfers_tree2 = get_pending_transfers_tree(web3, [3], [], 7)
    locksroot2 = pending_transfers_tree2.hash_of_packed_transfers
    locked_amount2 = get_locked_amount(pending_transfers_tree2.transfers)

    balance_proof_A = create_balance_proof(channel_identifier, A, 10,
                                           locked_amount1, 5, locksroot1)
    balance_proof_update_signature_B = create_balance_proof_countersignature(
        participant=B,
        channel_identifier=channel_identifier,
        msg_type=MessageTypeId.BALANCE_PROOF_UPDATE,
        **balance_proof_A._asdict(),
    )
    balance_proof_B = create_balance_proof(channel_identifier, B, 5,
                                           locked_amount2, 3, locksroot2)
    closing_sig_A = create_balance_proof_countersignature(
        participant=A,
        channel_identifier=channel_identifier,
        msg_type=MessageTypeId.BALANCE_PROOF,
        **balance_proof_B._asdict(),
    )

    for lock in pending_transfers_tree1.unlockable:
        txn_hash = call_and_transact(
            secret_registry_contract.functions.registerSecret(lock[3]),
            {"from": A})
    print_gas(txn_hash, CONTRACT_SECRET_REGISTRY + ".registerSecret")

    for lock in pending_transfers_tree2.unlockable:
        txn_hash = call_and_transact(
            secret_registry_contract.functions.registerSecret(lock[3]),
            {"from": A})
    print_gas(txn_hash, CONTRACT_SECRET_REGISTRY + ".registerSecret")

    txn_hash = call_and_transact(
        token_network.functions.closeChannel(
            channel_identifier, B, A,
            *balance_proof_B._asdict().values(), closing_sig_A),
        {"from": A},
    )
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".closeChannel")

    txn_hash = call_and_transact(
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier,
            A,
            B,
            *balance_proof_A._asdict().values(),
            balance_proof_update_signature_B,
        ),
        {"from": B},
    )
    print_gas(txn_hash,
              CONTRACT_TOKEN_NETWORK + ".updateNonClosingBalanceProof")

    mine_blocks(web3, settle_timeout)
    txn_hash = call_and_transact(
        token_network.functions.settleChannel(
            channel_identifier,
            B,
            5,
            locked_amount2,
            locksroot2,
            A,
            10,
            locked_amount1,
            locksroot1,
        ))
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".settleChannel")

    txn_hash = call_and_transact(
        token_network.functions.unlock(
            channel_identifier, A, B,
            pending_transfers_tree2.packed_transfers))
    print_gas(
        txn_hash,
        "{0}.unlock {1} locks".format(CONTRACT_TOKEN_NETWORK,
                                      len(pending_transfers_tree2.transfers)),
    )

    txn_hash = call_and_transact(
        token_network.functions.unlock(
            channel_identifier, B, A,
            pending_transfers_tree1.packed_transfers))
    print_gas(
        txn_hash,
        "{0}.unlock {1} locks".format(CONTRACT_TOKEN_NETWORK,
                                      len(pending_transfers_tree1.transfers)),
    )
def test_channel_unlock_both_participants(
    web3: Web3,
    custom_token: Contract,
    token_network: Contract,
    secret_registry_contract: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    close_and_update_channel: Callable,
    reveal_secrets: Callable,
) -> None:
    """ 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.hash_of_packed_transfers
    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.hash_of_packed_transfers
    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
def test_channel_unlock_before_settlement_fails(
    web3: Web3,
    custom_token: Contract,
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    close_and_update_channel: Callable,
    reveal_secrets: Callable,
) -> None:
    """ 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.hash_of_packed_transfers
    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
def test_channel_unlock_registered_expired_lock_refunds(
    web3: Web3,
    custom_token: Contract,
    token_network: Contract,
    secret_registry_contract: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    close_and_update_channel: Callable,
) -> None:
    """ 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.hash_of_packed_transfers
    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
def test_channel_unlock(
    web3: Web3,
    custom_token: Contract,
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    close_and_update_channel: Callable,
    reveal_secrets: Callable,
) -> None:
    """ 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.hash_of_packed_transfers
    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] == NONEXISTENT_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
def test_unlock_channel_event(
    web3: Web3,
    token_network: Contract,
    secret_registry_contract: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    close_and_update_channel: Callable,
    reveal_secrets: Callable,
    event_handler: Callable,
) -> None:
    """ 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.hash_of_packed_transfers
    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 print_gas_channel_cycle(
    web3: Web3,
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    withdraw_channel: Callable,
    secret_registry_contract: Contract,
    get_accounts: Callable,
    print_gas: Callable,
    create_balance_proof: Callable,
    create_balance_proof_update_signature: Callable,
) -> None:
    """ Abusing pytest to print gas costs of TokenNetwork's operations """
    (A, B, C, D) = get_accounts(4)
    settle_timeout = 11

    (channel_identifier, txn_hash) = create_channel(A, B, settle_timeout)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".openChannel")

    (_, txn_hash) = create_channel(C, D, settle_timeout)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".openChannel")

    txn_hash = channel_deposit(channel_identifier, A, 20, B)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".setTotalDeposit")

    txn_hash = channel_deposit(channel_identifier, B, 10, A)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".setTotalDeposit")

    txn_hash = withdraw_channel(channel_identifier, A, 5, B)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".setTotalWithdraw")

    pending_transfers_tree1 = get_pending_transfers_tree(web3, [1, 1, 2, 3], [2, 1])
    locksroot1 = pending_transfers_tree1.hash_of_packed_transfers
    locked_amount1 = get_locked_amount(pending_transfers_tree1.transfers)

    pending_transfers_tree2 = get_pending_transfers_tree(web3, [3], [], 7)
    locksroot2 = pending_transfers_tree2.hash_of_packed_transfers
    locked_amount2 = get_locked_amount(pending_transfers_tree2.transfers)

    balance_proof_A = create_balance_proof(
        channel_identifier, A, 10, locked_amount1, 5, locksroot1
    )
    balance_proof_B = create_balance_proof(channel_identifier, B, 5, locked_amount2, 3, locksroot2)
    balance_proof_update_signature_B = create_balance_proof_update_signature(
        B, channel_identifier, *balance_proof_A
    )

    for lock in pending_transfers_tree1.unlockable:
        txn_hash = secret_registry_contract.functions.registerSecret(lock[3]).call_and_transact(
            {"from": A}
        )
    print_gas(txn_hash, CONTRACT_SECRET_REGISTRY + ".registerSecret")

    for lock in pending_transfers_tree2.unlockable:
        txn_hash = secret_registry_contract.functions.registerSecret(lock[3]).call_and_transact(
            {"from": A}
        )
    print_gas(txn_hash, CONTRACT_SECRET_REGISTRY + ".registerSecret")

    txn_hash = token_network.functions.closeChannel(
        channel_identifier, B, *balance_proof_B
    ).call_and_transact({"from": A})
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".closeChannel")

    txn_hash = token_network.functions.updateNonClosingBalanceProof(
        channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B
    ).call_and_transact({"from": B})
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".updateNonClosingBalanceProof")

    web3.testing.mine(settle_timeout)
    txn_hash = token_network.functions.settleChannel(
        channel_identifier, B, 5, locked_amount2, locksroot2, A, 10, locked_amount1, locksroot1
    ).call_and_transact()
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + ".settleChannel")

    txn_hash = token_network.functions.unlock(
        channel_identifier, A, B, pending_transfers_tree2.packed_transfers
    ).call_and_transact()
    print_gas(
        txn_hash,
        "{0}.unlock {1} locks".format(
            CONTRACT_TOKEN_NETWORK, len(pending_transfers_tree2.transfers)
        ),
    )

    txn_hash = token_network.functions.unlock(
        channel_identifier, B, A, pending_transfers_tree1.packed_transfers
    ).call_and_transact()
    print_gas(
        txn_hash,
        "{0}.unlock {1} locks".format(
            CONTRACT_TOKEN_NETWORK, len(pending_transfers_tree1.transfers)
        ),
    )
def print_gas_channel_cycle(
    web3,
    token_network,
    create_channel,
    channel_deposit,
    secret_registry_contract,
    get_accounts,
    print_gas,
    create_balance_proof,
    create_balance_proof_update_signature,
):
    """ Abusing pytest to print gas costs of TokenNetwork's operations """
    (A, B, C, D) = get_accounts(4)
    settle_timeout = 11

    (channel_identifier, txn_hash) = create_channel(A, B, settle_timeout)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + '.openChannel')

    (_, txn_hash) = create_channel(C, D, settle_timeout)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + '.openChannel')

    txn_hash = channel_deposit(channel_identifier, A, 20, B)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + '.setTotalDeposit')

    txn_hash = channel_deposit(channel_identifier, B, 10, A)
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + '.setTotalDeposit')

    pending_transfers_tree1 = get_pending_transfers_tree(
        web3, [1, 1, 2, 3], [2, 1])
    locksroot1 = get_merkle_root(pending_transfers_tree1.merkle_tree)
    locked_amount1 = get_locked_amount(pending_transfers_tree1.transfers)

    pending_transfers_tree2 = get_pending_transfers_tree(web3, [3], [], 7)
    locksroot2 = get_merkle_root(pending_transfers_tree2.merkle_tree)
    locked_amount2 = get_locked_amount(pending_transfers_tree2.transfers)

    balance_proof_A = create_balance_proof(
        channel_identifier,
        A,
        10,
        locked_amount1,
        5,
        locksroot1,
    )
    balance_proof_B = create_balance_proof(
        channel_identifier,
        B,
        5,
        locked_amount2,
        3,
        locksroot2,
    )
    balance_proof_update_signature_B = create_balance_proof_update_signature(
        B,
        channel_identifier,
        *balance_proof_A,
    )

    for lock in pending_transfers_tree1.unlockable:
        txn_hash = secret_registry_contract.functions.registerSecret(
            lock[3]).transact({'from': A})
    print_gas(txn_hash, CONTRACT_SECRET_REGISTRY + '.registerSecret')

    for lock in pending_transfers_tree2.unlockable:
        txn_hash = secret_registry_contract.functions.registerSecret(
            lock[3]).transact({'from': A})
    print_gas(txn_hash, CONTRACT_SECRET_REGISTRY + '.registerSecret')

    txn_hash = token_network.functions.closeChannel(
        channel_identifier,
        B,
        *balance_proof_B,
    ).transact({'from': A})
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + '.closeChannel')

    txn_hash = token_network.functions.updateNonClosingBalanceProof(
        channel_identifier,
        A,
        B,
        *balance_proof_A,
        balance_proof_update_signature_B,
    ).transact({'from': B})
    print_gas(txn_hash,
              CONTRACT_TOKEN_NETWORK + '.updateNonClosingBalanceProof')

    web3.testing.mine(settle_timeout)
    txn_hash = token_network.functions.settleChannel(
        channel_identifier,
        B,
        5,
        locked_amount2,
        locksroot2,
        A,
        10,
        locked_amount1,
        locksroot1,
    ).transact()
    print_gas(txn_hash, CONTRACT_TOKEN_NETWORK + '.settleChannel')

    txn_hash = token_network.functions.unlock(
        channel_identifier,
        A,
        B,
        pending_transfers_tree2.packed_transfers,
    ).transact()
    print_gas(
        txn_hash, '{0}.unlock {1} locks'.format(
            CONTRACT_TOKEN_NETWORK,
            len(pending_transfers_tree2.transfers),
        ))

    txn_hash = token_network.functions.unlock(
        channel_identifier,
        B,
        A,
        pending_transfers_tree1.packed_transfers,
    ).transact()
    print_gas(
        txn_hash, '{0}.unlock {1} locks'.format(
            CONTRACT_TOKEN_NETWORK,
            len(pending_transfers_tree1.transfers),
        ))