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
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
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_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
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
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
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
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_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_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_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_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
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_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)
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, ): (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 + 100, ) 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( 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( A, B, values_B.locksroot, unlocked_amount, values_B.locked - unlocked_amount, )) # Check that event was properly emitted ev_handler.check()