ETH Price: $3,574.76 (-0.29%)
Gas: 34 Gwei

Contract

0x5b606943b36F3569E00EC4178A9f83eea8730184
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Settle Channel109972622020-10-05 18:07:161269 days ago1601921236IN
0x5b606943...ea8730184
0 ETH0.0034717949.5410998
Update Non Closi...109970502020-10-05 17:20:211269 days ago1601918421IN
0x5b606943...ea8730184
0 ETH0.00942666107.92571428
Close Channel109969992020-10-05 17:09:071269 days ago1601917747IN
0x5b606943...ea8730184
0 ETH0.0096336581.57545597
Close Channel109350752020-09-26 0:42:301279 days ago1601080950IN
0x5b606943...ea8730184
0 ETH0.0048675270
Set Total Deposi...106531892020-08-13 18:16:521322 days ago1597342612IN
0x5b606943...ea8730184
0 ETH0.00707051130.86025641
Set Total Deposi...106200502020-08-08 15:38:501327 days ago1596901130IN
0x5b606943...ea8730184
0 ETH0.0046156266.86309543
Set Total Deposi...106081392020-08-06 19:27:571329 days ago1596742077IN
0x5b606943...ea8730184
0 ETH0.0044261552.67289748
Open Channel106081222020-08-06 19:25:191329 days ago1596741919IN
0x5b606943...ea8730184
0 ETH0.0053989752.67289748
Set Total Deposi...105760652020-08-01 20:25:341334 days ago1596313534IN
0x5b606943...ea8730184
0 ETH0.0037494954.30820029
Open Channel105760522020-08-01 20:22:201334 days ago1596313340IN
0x5b606943...ea8730184
0 ETH0.0056380555
Close Channel105628022020-07-30 19:28:481336 days ago1596137328IN
0x5b606943...ea8730184
0 ETH0.0035702851.33191287
Set Total Deposi...105626142020-07-30 18:50:101336 days ago1596135010IN
0x5b606943...ea8730184
0 ETH0.0045794754.49096064
Open Channel105626012020-07-30 18:47:321336 days ago1596134852IN
0x5b606943...ea8730184
0 ETH0.0059582358.1166585
Set Total Deposi...105025852020-07-21 11:53:391346 days ago1595332419IN
0x5b606943...ea8730184
0 ETH0.0077346392.05818212
Set Total Withdr...104318222020-07-10 12:39:431356 days ago1594384783IN
0x5b606943...ea8730184
0 ETH0.0022171525
Set Total Withdr...104268602020-07-09 18:25:381357 days ago1594319138IN
0x5b606943...ea8730184
0 ETH0.000666225
Set Total Deposi...104079372020-07-06 20:14:201360 days ago1594066460IN
0x5b606943...ea8730184
0 ETH0.0017260225
Open Channel103154402020-06-22 12:09:371375 days ago1592827777IN
0x5b606943...ea8730184
0 ETH0.0037933137
Settle Channel102966822020-06-19 14:24:011377 days ago1592576641IN
0x5b606943...ea8730184
0 ETH0.0025453544.00000141
Update Non Closi...102961842020-06-19 12:28:531377 days ago1592569733IN
0x5b606943...ea8730184
0 ETH0.0035729840.9
Close Channel102961742020-06-19 12:26:521377 days ago1592569612IN
0x5b606943...ea8730184
0 ETH0.0022942933
Set Total Deposi...102503452020-06-12 10:32:181385 days ago1591957938IN
0x5b606943...ea8730184
0 ETH0.0032922739.17931602
Open Channel102503292020-06-12 10:27:471385 days ago1591957667IN
0x5b606943...ea8730184
0 ETH0.0039462538.50000004
Set Total Deposi...102308882020-06-09 10:11:211388 days ago1591697481IN
0x5b606943...ea8730184
0 ETH0.0027223832.39358146
Open Channel102308712020-06-09 10:07:131388 days ago1591697233IN
0x5b606943...ea8730184
0 ETH0.0032803232.00000058
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Txn Hash Block From To Value
100957932020-05-19 10:19:031409 days ago1589883543  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TokenNetwork

Compiler Version
v0.6.4+commit.1dca32f3

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-05-19
*/

pragma solidity 0.6.4;


library ECVerify {

    function ecverify(bytes32 hash, bytes memory signature)
        internal
        pure
        returns (address signature_address)
    {
        require(signature.length == 65);

        bytes32 r;
        bytes32 s;
        uint8 v;

        // The signature format is a compact form of:
        //   {bytes32 r}{bytes32 s}{uint8 v}
        // Compact means, uint8 is not padded to 32 bytes.
        assembly {
            r := mload(add(signature, 32))
            s := mload(add(signature, 64))

            // Here we are loading the last 32 bytes, including 31 bytes following the signature.
            v := byte(0, mload(add(signature, 96)))
        }

        // Version of signature should be 27 or 28, but 0 and 1 are also possible
        if (v < 27) {
            v += 27;
        }

        require(v == 27 || v == 28);

        signature_address = ecrecover(hash, v, r, s);

        // ecrecover returns zero on error
        require(signature_address != address(0x0));

        return signature_address;
    }
}

interface Token {

    /// @return supply total amount of tokens
    function totalSupply() external view returns (uint256 supply);

    /// @param _owner The address from which the balance will be retrieved
    /// @return balance The balance
    function balanceOf(address _owner) external view returns (uint256 balance);

    /// @notice send `_value` token to `_to` from `msg.sender`
    /// @param _to The address of the recipient
    /// @param _value The amount of token to be transferred
    /// @return success Whether the transfer was successful or not
    function transfer(address _to, uint256 _value) external returns (bool success);

    /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
    /// @param _from The address of the sender
    /// @param _to The address of the recipient
    /// @param _value The amount of token to be transferred
    /// @return success Whether the transfer was successful or not
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);

    /// @notice `msg.sender` approves `_spender` to spend `_value` tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @param _value The amount of wei to be approved for transfer
    /// @return success Whether the approval was successful or not
    function approve(address _spender, uint256 _value) external returns (bool success);

    /// @param _owner The address of the account owning tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @return remaining Amount of remaining tokens allowed to spent
    function allowance(address _owner, address _spender) external view returns (uint256 remaining);

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);

    // Optionally implemented function to show the number of decimals for the token
    function decimals() external view returns (uint8 decimals);
}

/// @title Utils
/// @notice Utils contract for various helpers used by the Raiden Network smart
/// contracts.
contract Utils {
    enum MessageTypeId {
        None,
        BalanceProof,
        BalanceProofUpdate,
        Withdraw,
        CooperativeSettle,
        IOU,
        MSReward
    }

    /// @notice Check if a contract exists
    /// @param contract_address The address to check whether a contract is
    /// deployed or not
    /// @return True if a contract exists, false otherwise
    function contractExists(address contract_address) public view returns (bool) {
        uint size;

        assembly {
            size := extcodesize(contract_address)
        }

        return size > 0;
    }
}

/// @title SecretRegistry
/// @notice SecretRegistry contract for registering secrets from Raiden Network
/// clients.
contract SecretRegistry {
    // sha256(secret) => block number at which the secret was revealed
    mapping(bytes32 => uint256) private secrethash_to_block;

    event SecretRevealed(bytes32 indexed secrethash, bytes32 secret);

    /// @notice Registers a hash time lock secret and saves the block number.
    /// This allows the lock to be unlocked after the expiration block
    /// @param secret The secret used to lock the hash time lock
    /// @return true if secret was registered, false if the secret was already
    /// registered
    function registerSecret(bytes32 secret) public returns (bool) {
        bytes32 secrethash = sha256(abi.encodePacked(secret));
        if (secrethash_to_block[secrethash] > 0) {
            return false;
        }
        secrethash_to_block[secrethash] = block.number;
        emit SecretRevealed(secrethash, secret);
        return true;
    }

    /// @notice Registers multiple hash time lock secrets and saves the block
    /// number
    /// @param secrets The array of secrets to be registered
    /// @return true if all secrets could be registered, false otherwise
    function registerSecretBatch(bytes32[] memory secrets) public returns (bool) {
        bool completeSuccess = true;
        for(uint i = 0; i < secrets.length; i++) {
            if(!registerSecret(secrets[i])) {
                completeSuccess = false;
            }
        }
        return completeSuccess;
    }

    /// @notice Get the stored block number at which the secret was revealed
    /// @param secrethash The hash of the registered secret `keccak256(secret)`
    /// @return The block number at which the secret was revealed
    function getSecretRevealBlockHeight(bytes32 secrethash) public view returns (uint256) {
        return secrethash_to_block[secrethash];
    }
}

// MIT License

// Copyright (c) 2018

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

/// @title TokenNetwork
/// @notice Stores and manages all the Raiden Network channels that use the
/// token specified
/// in this TokenNetwork contract.
contract TokenNetwork is Utils {
    // Instance of the token used by the channels
    Token public token;

    // Instance of SecretRegistry used for storing secrets revealed in a
    // mediating transfer.
    SecretRegistry public secret_registry;

    // Chain ID as specified by EIP155 used in balance proof signatures to
    // avoid replay attacks
    uint256 public chain_id;

    uint256 public settlement_timeout_min;
    uint256 public settlement_timeout_max;

    uint256 constant public MAX_SAFE_UINT256 = (
        115792089237316195423570985008687907853269984665640564039457584007913129639935
    );

    // The deposit limit per channel per participant.
    uint256 public channel_participant_deposit_limit;
    // The total combined deposit of all channels across the whole network
    uint256 public token_network_deposit_limit;

    // Global, monotonically increasing counter that keeps track of all the
    // opened channels in this contract
    uint256 public channel_counter;

    string public constant signature_prefix = '\x19Ethereum Signed Message:\n';

    // Only for the limited Red Eyes release
    address public deprecation_executor;
    bool public safety_deprecation_switch = false;

    // channel_identifier => Channel
    // channel identifier is the channel_counter value at the time of opening
    // the channel
    mapping (uint256 => Channel) public channels;

    // This is needed to enforce one channel per pair of participants
    // The key is keccak256(participant1_address, participant2_address)
    mapping (bytes32 => uint256) public participants_hash_to_channel_identifier;

    // We keep the unlock data in a separate mapping to allow channel data
    // structures to be removed when settling uncooperatively. If there are
    // locked pending transfers, we need to store data needed to unlock them at
    // a later time.
    // The key is `keccak256(uint256 channel_identifier, address participant,
    // address partner)` Where `participant` is the participant that sent the
    // pending transfers We need `partner` for knowing where to send the
    // claimable tokens
    mapping(bytes32 => UnlockData) private unlock_identifier_to_unlock_data;

    struct Participant {
        // Total amount of tokens transferred to this smart contract through
        // the `setTotalDeposit` function, for a specific channel, in the
        // participant's benefit.
        // This is a strictly monotonic value. Note that direct token transfer
        // into the contract cannot be tracked and will be stuck.
        uint256 deposit;

        // Total amount of tokens withdrawn by the participant during the
        // lifecycle of this channel.
        // This is a strictly monotonic value.
        uint256 withdrawn_amount;

        // This is a value set to true after the channel has been closed, only
        // if this is the participant who closed the channel.
        bool is_the_closer;

        // keccak256 of the balance data provided after a closeChannel or an
        // updateNonClosingBalanceProof call
        bytes32 balance_hash;

        // Monotonically increasing counter of the off-chain transfers,
        // provided along with the balance_hash
        uint256 nonce;
    }

    enum ChannelState {
        NonExistent, // 0
        Opened,      // 1
        Closed,      // 2
        Settled,     // 3; Note: The channel has at least one pending unlock
        Removed      // 4; Note: Channel data is removed, there are no pending unlocks
    }

    struct Channel {
        // After opening the channel this value represents the settlement
        // window. This is the number of blocks that need to be mined between
        // closing the channel uncooperatively and settling the channel.
        // After the channel has been uncooperatively closed, this value
        // represents the block number after which settleChannel can be called.
        uint256 settle_block_number;

        ChannelState state;

        mapping(address => Participant) participants;
    }

    struct SettlementData {
        uint256 deposit;
        uint256 withdrawn;
        uint256 transferred;
        uint256 locked;
    }

    struct UnlockData {
        // keccak256 hash of the pending locks from the Raiden client
        bytes32 locksroot;
        // Total amount of tokens locked in the pending locks corresponding
        // to the `locksroot`
        uint256 locked_amount;
    }

    event ChannelOpened(
        uint256 indexed channel_identifier,
        address indexed participant1,
        address indexed participant2,
        uint256 settle_timeout
    );

    event ChannelNewDeposit(
        uint256 indexed channel_identifier,
        address indexed participant,
        uint256 total_deposit
    );

    // Fires when the deprecation_switch's value changes
    event DeprecationSwitch(bool new_value);

    // total_withdraw is how much the participant has withdrawn during the
    // lifetime of the channel. The actual amount which the participant withdrew
    // is `total_withdraw - total_withdraw_from_previous_event_or_zero`
    event ChannelWithdraw(
        uint256 indexed channel_identifier,
        address indexed participant,
        uint256 total_withdraw
    );

    event ChannelClosed(
        uint256 indexed channel_identifier,
        address indexed closing_participant,
        uint256 indexed nonce,
        bytes32 balance_hash
    );

    event ChannelUnlocked(
        uint256 indexed channel_identifier,
        address indexed receiver,
        address indexed sender,
        bytes32 locksroot,
        uint256 unlocked_amount,
        uint256 returned_tokens
    );

    event NonClosingBalanceProofUpdated(
        uint256 indexed channel_identifier,
        address indexed closing_participant,
        uint256 indexed nonce,
        bytes32 balance_hash
    );

    event ChannelSettled(
        uint256 indexed channel_identifier,
        uint256 participant1_amount,
        bytes32 participant1_locksroot,
        uint256 participant2_amount,
        bytes32 participant2_locksroot
    );

    modifier onlyDeprecationExecutor() {
        require(msg.sender == deprecation_executor);
        _;
    }

    modifier isSafe() {
        require(safety_deprecation_switch == false);
        _;
    }

    modifier isOpen(uint256 channel_identifier) {
        require(channels[channel_identifier].state == ChannelState.Opened);
        _;
    }

    modifier settleTimeoutValid(uint256 timeout) {
        require(timeout >= settlement_timeout_min);
        require(timeout <= settlement_timeout_max);
        _;
    }

    /// @param _token_address The address of the ERC20 token contract
    /// @param _secret_registry The address of SecretRegistry contract that witnesses the onchain secret reveals
    /// @param _chain_id EIP-155 Chain ID of the blockchain where this instance is being deployed
    /// @param _settlement_timeout_min The shortest settlement period (in number of blocks)
    /// that can be chosen at the channel opening
    /// @param _settlement_timeout_max The longest settlement period (in number of blocks)
    /// that can be chosen at the channel opening
    /// @param _deprecation_executor The Ethereum address that can disable new deposits and channel creation
    /// @param _channel_participant_deposit_limit The maximum amount of tokens that can be deposited by each
    /// participant of each channel. MAX_SAFE_UINT256 means no limits
    /// @param _token_network_deposit_limit The maximum amount of tokens that this contract can hold
    /// MAX_SAFE_UINT256 means no limits
    constructor(
        address _token_address,
        address _secret_registry,
        uint256 _chain_id,
        uint256 _settlement_timeout_min,
        uint256 _settlement_timeout_max,
        address _deprecation_executor,
        uint256 _channel_participant_deposit_limit,
        uint256 _token_network_deposit_limit
    )
        public
    {
        require(_token_address != address(0x0));
        require(_secret_registry != address(0x0));
        require(_deprecation_executor != address(0x0));
        require(_chain_id > 0);
        require(_settlement_timeout_min > 0);
        require(_settlement_timeout_max > _settlement_timeout_min);
        require(contractExists(_token_address));
        require(contractExists(_secret_registry));
        require(_channel_participant_deposit_limit > 0);
        require(_token_network_deposit_limit > 0);
        require(_token_network_deposit_limit >= _channel_participant_deposit_limit);

        token = Token(_token_address);

        secret_registry = SecretRegistry(_secret_registry);
        chain_id = _chain_id;
        settlement_timeout_min = _settlement_timeout_min;
        settlement_timeout_max = _settlement_timeout_max;

        // Make sure the contract is indeed a token contract
        require(token.totalSupply() > 0);

        deprecation_executor = _deprecation_executor;
        channel_participant_deposit_limit = _channel_participant_deposit_limit;
        token_network_deposit_limit = _token_network_deposit_limit;
    }

    function deprecate() public isSafe onlyDeprecationExecutor {
        safety_deprecation_switch = true;
        emit DeprecationSwitch(safety_deprecation_switch);
    }

    /// @notice Opens a new channel between `participant1` and `participant2`.
    /// Can be called by anyone
    /// @param participant1 Ethereum address of a channel participant
    /// @param participant2 Ethereum address of the other channel participant
    /// @param settle_timeout Number of blocks that need to be mined between a
    /// call to closeChannel and settleChannel
    function openChannel(address participant1, address participant2, uint256 settle_timeout)
        public
        isSafe
        settleTimeoutValid(settle_timeout)
        returns (uint256)
    {
        bytes32 pair_hash;
        uint256 channel_identifier;

        // Red Eyes release token network limit
        require(token.balanceOf(address(this)) < token_network_deposit_limit);

        // First increment the counter
        // There will never be a channel with channel_identifier == 0
        channel_counter += 1;
        channel_identifier = channel_counter;

        pair_hash = getParticipantsHash(participant1, participant2);

        // There must only be one channel opened between two participants at
        // any moment in time.
        require(participants_hash_to_channel_identifier[pair_hash] == 0);
        participants_hash_to_channel_identifier[pair_hash] = channel_identifier;

        Channel storage channel = channels[channel_identifier];

        // We always increase the channel counter, therefore no channel data can already exist,
        // corresponding to this channel_identifier. This check must never fail.
        assert(channel.settle_block_number == 0);
        assert(channel.state == ChannelState.NonExistent);

        // Store channel information
        channel.settle_block_number = settle_timeout;
        channel.state = ChannelState.Opened;

        emit ChannelOpened(
            channel_identifier,
            participant1,
            participant2,
            settle_timeout
        );

        return channel_identifier;
    }

    /// @notice Sets the channel participant total deposit value.
    /// Can be called by anyone.
    /// @param channel_identifier Identifier for the channel on which this
    /// operation takes place
    /// @param participant Channel participant whose deposit is being set
    /// @param total_deposit The total amount of tokens that the participant
    /// will have as a deposit
    /// @param partner Channel partner address, needed to compute the total
    /// channel deposit
    function setTotalDeposit(
        uint256 channel_identifier,
        address participant,
        uint256 total_deposit,
        address partner
    )
        public
        isSafe
        isOpen(channel_identifier)
    {
        require(channel_identifier == getChannelIdentifier(participant, partner));
        require(total_deposit > 0);
        require(total_deposit <= channel_participant_deposit_limit);

        uint256 added_deposit;
        uint256 channel_deposit;

        Channel storage channel = channels[channel_identifier];
        Participant storage participant_state = channel.participants[participant];
        Participant storage partner_state = channel.participants[partner];

        // Calculate the actual amount of tokens that will be transferred
        added_deposit = total_deposit - participant_state.deposit;

        // The actual amount of tokens that will be transferred must be > 0
        require(added_deposit > 0);

        // Underflow check; we use <= because added_deposit == total_deposit for the first deposit

        require(added_deposit <= total_deposit);

        // This should never fail at this point. Added check for security, because we directly set
        // the participant_state.deposit = total_deposit, while we transfer `added_deposit` tokens
        assert(participant_state.deposit + added_deposit == total_deposit);

        // Red Eyes release token network limit
        require(token.balanceOf(address(this)) + added_deposit <= token_network_deposit_limit);

        // Update the participant's channel deposit
        participant_state.deposit = total_deposit;

        // Calculate the entire channel deposit, to avoid overflow
        channel_deposit = participant_state.deposit + partner_state.deposit;
        // Overflow check
        require(channel_deposit >= participant_state.deposit);

        emit ChannelNewDeposit(
            channel_identifier,
            participant,
            participant_state.deposit
        );

        // Do the transfer
        require(token.transferFrom(msg.sender, address(this), added_deposit));
    }

    /// @notice Allows `participant` to withdraw tokens from the channel that he
    /// has with `partner`, without closing it. Can be called by anyone. Can
    /// only be called once per each signed withdraw message
    /// @param channel_identifier Identifier for the channel on which this
    /// operation takes place
    /// @param participant Channel participant, who will receive the withdrawn
    /// amount
    /// @param total_withdraw Total amount of tokens that are marked as
    /// withdrawn from the channel during the channel lifecycle
    /// @param participant_signature Participant's signature on the withdraw
    /// data
    /// @param partner_signature Partner's signature on the withdraw data
    function setTotalWithdraw(
        uint256 channel_identifier,
        address participant,
        uint256 total_withdraw,
        uint256 expiration_block,
        bytes calldata participant_signature,
        bytes calldata partner_signature
    )
        external
        isOpen(channel_identifier)
    {
        uint256 total_deposit;
        uint256 current_withdraw;
        address partner;

        require(total_withdraw > 0);
        require(block.number < expiration_block);

        // Authenticate both channel partners via their signatures.
        // `participant` is a part of the signed message, so given in the calldata.
        require(participant == recoverAddressFromWithdrawMessage(
            channel_identifier,
            participant,
            total_withdraw,
            expiration_block,
            participant_signature
        ));
        partner = recoverAddressFromWithdrawMessage(
            channel_identifier,
            participant,
            total_withdraw,
            expiration_block,
            partner_signature
        );

        // Validate that authenticated partners and the channel identifier match
        require(channel_identifier == getChannelIdentifier(participant, partner));

        // Read channel state after validating the function input
        Channel storage channel = channels[channel_identifier];
        Participant storage participant_state = channel.participants[participant];
        Participant storage partner_state = channel.participants[partner];

        total_deposit = participant_state.deposit + partner_state.deposit;

        // Entire withdrawn amount must not be bigger than the current channel deposit
        require((total_withdraw + partner_state.withdrawn_amount) <= total_deposit);
        require(total_withdraw <= (total_withdraw + partner_state.withdrawn_amount));

        // Using the total_withdraw (monotonically increasing) in the signed
        // message ensures that we do not allow replay attack to happen, by
        // using the same withdraw proof twice.
        // Next two lines enforce the monotonicity of total_withdraw and check for an underflow:
        // (we use <= because current_withdraw == total_withdraw for the first withdraw)
        current_withdraw = total_withdraw - participant_state.withdrawn_amount;
        require(current_withdraw <= total_withdraw);

        // The actual amount of tokens that will be transferred must be > 0 to disable the reuse of
        // withdraw messages completely.
        require(current_withdraw > 0);

        // This should never fail at this point. Added check for security, because we directly set
        // the participant_state.withdrawn_amount = total_withdraw,
        // while we transfer `current_withdraw` tokens.
        assert(participant_state.withdrawn_amount + current_withdraw == total_withdraw);

        emit ChannelWithdraw(
            channel_identifier,
            participant,
            total_withdraw
        );

        // Do the state change and tokens transfer
        participant_state.withdrawn_amount = total_withdraw;
        require(token.transfer(participant, current_withdraw));

        // This should never happen, as we have an overflow check in setTotalDeposit
        assert(total_deposit >= participant_state.deposit);
        assert(total_deposit >= partner_state.deposit);

        // A withdraw should never happen if a participant already has a
        // balance proof in storage. This should never fail as we use isOpen.
        assert(participant_state.nonce == 0);
        assert(partner_state.nonce == 0);

    }

    /// @notice Close the channel defined by the two participant addresses.
    /// Anybody can call this function on behalf of a participant (called
    /// the closing participant), providing a balance proof signed by
    /// both parties. Callable only once
    /// @param channel_identifier Identifier for the channel on which this
    /// operation takes place
    /// @param closing_participant Channel participant who closes the channel
    /// @param non_closing_participant Channel partner of the `closing_participant`,
    /// who provided the balance proof
    /// @param balance_hash Hash of (transferred_amount, locked_amount,
    /// locksroot)
    /// @param additional_hash Computed from the message. Used for message
    /// authentication
    /// @param nonce Strictly monotonic value used to order transfers
    /// @param non_closing_signature Non-closing participant's signature of the balance proof data
    /// @param closing_signature Closing participant's signature of the balance
    /// proof data
    function closeChannel(
        uint256 channel_identifier,
        address non_closing_participant,
        address closing_participant,
        // The next four arguments form a balance proof.
        bytes32 balance_hash,
        uint256 nonce,
        bytes32 additional_hash,
        bytes memory non_closing_signature,
        bytes memory closing_signature
    )
        public
        isOpen(channel_identifier)
    {
        require(channel_identifier == getChannelIdentifier(closing_participant, non_closing_participant));

        address recovered_non_closing_participant_address;

        Channel storage channel = channels[channel_identifier];

        channel.state = ChannelState.Closed;
        channel.participants[closing_participant].is_the_closer = true;

        // This is the block number at which the channel can be settled.
        channel.settle_block_number += uint256(block.number);

        // The closing participant must have signed the balance proof.
        address recovered_closing_participant_address = recoverAddressFromBalanceProofCounterSignature(
            MessageTypeId.BalanceProof,
            channel_identifier,
            balance_hash,
            nonce,
            additional_hash,
            non_closing_signature,
            closing_signature
        );
        require(closing_participant == recovered_closing_participant_address);

        // Nonce 0 means that the closer never received a transfer, therefore
        // never received a balance proof, or he is intentionally not providing
        // the latest transfer, in which case the closing party is going to
        // lose the tokens that were transferred to him.
        if (nonce > 0) {
            recovered_non_closing_participant_address = recoverAddressFromBalanceProof(
                channel_identifier,
                balance_hash,
                nonce,
                additional_hash,
                non_closing_signature
            );
            // Signature must be from the channel partner
            require(non_closing_participant == recovered_non_closing_participant_address);

            updateBalanceProofData(
                channel,
                recovered_non_closing_participant_address,
                nonce,
                balance_hash
            );
        }

        emit ChannelClosed(channel_identifier, closing_participant, nonce, balance_hash);
    }

    /// @notice Called on a closed channel, the function allows the non-closing
    /// participant to provide the last balance proof, which modifies the
    /// closing participant's state. Can be called multiple times by anyone.
    /// @param channel_identifier Identifier for the channel on which this
    /// operation takes place
    /// @param closing_participant Channel participant who closed the channel
    /// @param non_closing_participant Channel participant who needs to update
    /// the balance proof
    /// @param balance_hash Hash of (transferred_amount, locked_amount,
    /// locksroot)
    /// @param additional_hash Computed from the message. Used for message
    /// authentication
    /// @param nonce Strictly monotonic value used to order transfers
    /// @param closing_signature Closing participant's signature of the balance
    /// proof data
    /// @param non_closing_signature Non-closing participant signature of the
    /// balance proof data
    function updateNonClosingBalanceProof(
        uint256 channel_identifier,
        address closing_participant,
        address non_closing_participant,
        // The next four arguments form a balance proof
        bytes32 balance_hash,
        uint256 nonce,
        bytes32 additional_hash,
        bytes calldata closing_signature,
        bytes calldata non_closing_signature
    )
        external
    {
        require(channel_identifier == getChannelIdentifier(
            closing_participant,
            non_closing_participant
        ));
        require(balance_hash != bytes32(0x0));
        require(nonce > 0);

        address recovered_non_closing_participant;
        address recovered_closing_participant;

        Channel storage channel = channels[channel_identifier];

        require(channel.state == ChannelState.Closed);

        // Calling this function after the settlement window is forbidden to
        // fix the following race condition:
        //
        // 1 A badly configured node A, that doesn't have a monitoring service
        //   and is temporarily offline does not call update during the
        //   settlement window.
        // 2 The well behaved partner B, who called close, sees the
        //   settlement window is over and calls settle. At this point the B's
        //   balance proofs which should be provided by A is missing, so B will
        //   call settle with its balance proof zeroed out.
        // 3 A restarts and calls update, which will change B's balance
        //   proof.
        // 4 At this point, the transactions from 2 and 3 are racing, and one
        //   of them will fail.
        //
        // To avoid the above race condition, which would require special
        // handling on both nodes, the call to update is forbidden after the
        // settlement window. This does not affect safety, since we assume the
        // nodes are always properly configured and have a monitoring service
        // available to call update on the user's behalf.
        require(channel.settle_block_number >= block.number);

        // We need the signature from the non-closing participant to allow
        // anyone to make this transaction. E.g. a monitoring service.
        recovered_non_closing_participant = recoverAddressFromBalanceProofCounterSignature(
            MessageTypeId.BalanceProofUpdate,
            channel_identifier,
            balance_hash,
            nonce,
            additional_hash,
            closing_signature,
            non_closing_signature
        );
        require(non_closing_participant == recovered_non_closing_participant);

        recovered_closing_participant = recoverAddressFromBalanceProof(
            channel_identifier,
            balance_hash,
            nonce,
            additional_hash,
            closing_signature
        );
        require(closing_participant == recovered_closing_participant);

        Participant storage closing_participant_state = channel.participants[closing_participant];
        // Make sure the first signature is from the closing participant
        require(closing_participant_state.is_the_closer);

        // Update the balance proof data for the closing_participant
        updateBalanceProofData(channel, closing_participant, nonce, balance_hash);

        emit NonClosingBalanceProofUpdated(
            channel_identifier,
            closing_participant,
            nonce,
            balance_hash
        );
    }

    /// @notice Settles the balance between the two parties. Note that arguments
    /// order counts: `participant1_transferred_amount +
    /// participant1_locked_amount` <= `participant2_transferred_amount +
    /// participant2_locked_amount`
    /// @param channel_identifier Identifier for the channel on which this
    /// operation takes place
    /// @param participant1 Channel participant
    /// @param participant1_transferred_amount The latest known amount of tokens
    /// transferred from `participant1` to `participant2`
    /// @param participant1_locked_amount Amount of tokens owed by
    /// `participant1` to `participant2`, contained in locked transfers that
    /// will be retrieved by calling `unlock` after the channel is settled
    /// @param participant1_locksroot The latest known hash of the
    /// pending hash-time locks of `participant1`, used to validate the unlocked
    /// proofs. If no balance_hash has been submitted, locksroot is ignored
    /// @param participant2 Other channel participant
    /// @param participant2_transferred_amount The latest known amount of tokens
    /// transferred from `participant2` to `participant1`
    /// @param participant2_locked_amount Amount of tokens owed by
    /// `participant2` to `participant1`, contained in locked transfers that
    /// will be retrieved by calling `unlock` after the channel is settled
    /// @param participant2_locksroot The latest known hash of the
    /// pending hash-time locks of `participant2`, used to validate the unlocked
    /// proofs. If no balance_hash has been submitted, locksroot is ignored
    function settleChannel(
        uint256 channel_identifier,
        address participant1,
        uint256 participant1_transferred_amount,
        uint256 participant1_locked_amount,
        bytes32 participant1_locksroot,
        address participant2,
        uint256 participant2_transferred_amount,
        uint256 participant2_locked_amount,
        bytes32 participant2_locksroot
    )
        public
    {
        // There are several requirements that this function MUST enforce:
        // - it MUST never fail; therefore, any overflows or underflows must be
        // handled gracefully
        // - it MUST ensure that if participants use the latest valid balance proofs,
        // provided by the official Raiden client, the participants will be able
        // to receive correct final balances at the end of the channel lifecycle
        // - it MUST ensure that the participants cannot cheat by providing an
        // old, valid balance proof of their partner; meaning that their partner MUST
        // receive at least the amount of tokens that he would have received if
        // the latest valid balance proofs are used.
        // - the contract cannot determine if a balance proof is invalid (values
        // are not within the constraints enforced by the official Raiden client),
        // therefore it cannot ensure correctness. Users MUST use the official
        // Raiden clients for signing balance proofs.

        require(channel_identifier == getChannelIdentifier(participant1, participant2));

        bytes32 pair_hash;

        pair_hash = getParticipantsHash(participant1, participant2);
        Channel storage channel = channels[channel_identifier];

        require(channel.state == ChannelState.Closed);

        // Settlement window must be over
        require(channel.settle_block_number < block.number);

        Participant storage participant1_state = channel.participants[participant1];
        Participant storage participant2_state = channel.participants[participant2];

        require(verifyBalanceHashData(
            participant1_state,
            participant1_transferred_amount,
            participant1_locked_amount,
            participant1_locksroot
        ));

        require(verifyBalanceHashData(
            participant2_state,
            participant2_transferred_amount,
            participant2_locked_amount,
            participant2_locksroot
        ));

        // We are calculating the final token amounts that need to be
        // transferred to the participants now and the amount of tokens that
        // need to remain locked in the contract. These tokens can be unlocked
        // by calling `unlock`.
        // participant1_transferred_amount = the amount of tokens that
        //   participant1 will receive in this transaction.
        // participant2_transferred_amount = the amount of tokens that
        //   participant2 will receive in this transaction.
        // participant1_locked_amount = the amount of tokens remaining in the
        //   contract, representing pending transfers from participant1 to participant2.
        // participant2_locked_amount = the amount of tokens remaining in the
        //   contract, representing pending transfers from participant2 to participant1.
        // We are reusing variables due to the local variables number limit.
        // For better readability this can be refactored further.
        (
            participant1_transferred_amount,
            participant2_transferred_amount,
            participant1_locked_amount,
            participant2_locked_amount
        ) = getSettleTransferAmounts(
            participant1_state,
            participant1_transferred_amount,
            participant1_locked_amount,
            participant2_state,
            participant2_transferred_amount,
            participant2_locked_amount
        );

        // Remove the channel data from storage
        delete channel.participants[participant1];
        delete channel.participants[participant2];
        delete channels[channel_identifier];

        // Remove the pair's channel counter
        delete participants_hash_to_channel_identifier[pair_hash];

        // Store balance data needed for `unlock`, including the calculated
        // locked amounts remaining in the contract.
        storeUnlockData(
            channel_identifier,
            participant1,
            participant2,
            participant1_locked_amount,
            participant1_locksroot
        );
        storeUnlockData(
            channel_identifier,
            participant2,
            participant1,
            participant2_locked_amount,
            participant2_locksroot
        );

        emit ChannelSettled(
            channel_identifier,
            participant1_transferred_amount,
            participant1_locksroot,
            participant2_transferred_amount,
            participant2_locksroot
        );

        // Do the actual token transfers
        if (participant1_transferred_amount > 0) {
            require(token.transfer(participant1, participant1_transferred_amount));
        }

        if (participant2_transferred_amount > 0) {
            require(token.transfer(participant2, participant2_transferred_amount));
        }
    }

    /// @notice Unlocks all pending off-chain transfers from `sender` to
    /// `receiver` and sends the locked tokens corresponding to locks with
    /// secrets registered on-chain to the `receiver`. Locked tokens
    /// corresponding to locks where the secret was not revealed on-chain will
    /// return to the `sender`. Anyone can call unlock.
    /// @param channel_identifier Identifier for the channel on which this
    /// operation takes place
    /// @param receiver Address who will receive the claimable unlocked
    /// tokens
    /// @param sender Address who sent the pending transfers and will receive
    /// the unclaimable unlocked tokens
    /// @param locks All pending locks concatenated in order of creation
    /// that `sender` sent to `receiver`
    function unlock(
        uint256 channel_identifier,
        address receiver,
        address sender,
        bytes memory locks
    )
        public
    {
        // Channel represented by channel_identifier must be settled and
        // channel data deleted
        require(channel_identifier != getChannelIdentifier(receiver, sender));

        // After the channel is settled the storage is cleared, therefore the
        // value will be NonExistent and not Settled. The value Settled is used
        // for the external APIs
        require(channels[channel_identifier].state == ChannelState.NonExistent);

        bytes32 unlock_key;
        bytes32 computed_locksroot;
        uint256 unlocked_amount;
        uint256 locked_amount;
        uint256 returned_tokens;

        // Calculate the locksroot for the pending transfers and the amount of
        // tokens corresponding to the locked transfers with secrets revealed
        // on chain.
        (computed_locksroot, unlocked_amount) = getHashAndUnlockedAmount(
            locks
        );

        // The sender must have a non-empty locksroot on-chain that must be
        // the same as the computed locksroot.
        // Get the amount of tokens that have been left in the contract, to
        // account for the pending transfers `sender` -> `receiver`.
        unlock_key = getUnlockIdentifier(channel_identifier, sender, receiver);
        UnlockData storage unlock_data = unlock_identifier_to_unlock_data[unlock_key];
        locked_amount = unlock_data.locked_amount;

        // Locksroot must be the same as the computed locksroot
        require(unlock_data.locksroot == computed_locksroot);

        // There are no pending transfers if the locked_amount is 0.
        // Transaction must fail
        require(locked_amount > 0);

        // Make sure we don't transfer more tokens than previously reserved in
        // the smart contract.
        unlocked_amount = min(unlocked_amount, locked_amount);

        // Transfer the rest of the tokens back to the sender
        returned_tokens = locked_amount - unlocked_amount;

        // Remove sender's unlock data
        delete unlock_identifier_to_unlock_data[unlock_key];

        emit ChannelUnlocked(
            channel_identifier,
            receiver,
            sender,
            computed_locksroot,
            unlocked_amount,
            returned_tokens
        );

        // Transfer the unlocked tokens to the receiver. unlocked_amount can
        // be 0
        if (unlocked_amount > 0) {
            require(token.transfer(receiver, unlocked_amount));
        }

        // Transfer the rest of the tokens back to the sender
        if (returned_tokens > 0) {
            require(token.transfer(sender, returned_tokens));
        }

        // At this point, this should always be true
        assert(locked_amount >= returned_tokens);
        assert(locked_amount >= unlocked_amount);
    }

    /* /// @notice Cooperatively settles the balances between the two channel
    /// participants and transfers the agreed upon token amounts to the
    /// participants. After this the channel lifecycle has ended and no more
    /// operations can be done on it.
    /// @param channel_identifier Identifier for the channel on which this
    /// operation takes place
    /// @param participant1_address Address of channel participant
    /// @param participant1_balance Amount of tokens that `participant1_address`
    /// must receive when the channel is settled and removed
    /// @param participant2_address Address of the other channel participant
    /// @param participant2_balance Amount of tokens that `participant2_address`
    /// must receive when the channel is settled and removed
    /// @param participant1_signature Signature of `participant1_address` on the
    /// cooperative settle message
    /// @param participant2_signature Signature of `participant2_address` on the
    /// cooperative settle message
    function cooperativeSettle(
        uint256 channel_identifier,
        address participant1_address,
        uint256 participant1_balance,
        address participant2_address,
        uint256 participant2_balance,
        bytes participant1_signature,
        bytes participant2_signature
    )
        public
    {
        require(channel_identifier == getChannelIdentifier(
            participant1_address,
            participant2_address
        ));
        bytes32 pair_hash;
        address participant1;
        address participant2;
        uint256 total_available_deposit;

        pair_hash = getParticipantsHash(participant1_address, participant2_address);
        Channel storage channel = channels[channel_identifier];

        require(channel.state == ChannelState.Opened);

        participant1 = recoverAddressFromCooperativeSettleSignature(
            channel_identifier,
            participant1_address,
            participant1_balance,
            participant2_address,
            participant2_balance,
            participant1_signature
        );
        // The provided address must be the same as the recovered one
        require(participant1 == participant1_address);

        participant2 = recoverAddressFromCooperativeSettleSignature(
            channel_identifier,
            participant1_address,
            participant1_balance,
            participant2_address,
            participant2_balance,
            participant2_signature
        );
        // The provided address must be the same as the recovered one
        require(participant2 == participant2_address);

        Participant storage participant1_state = channel.participants[participant1];
        Participant storage participant2_state = channel.participants[participant2];

        total_available_deposit = getChannelAvailableDeposit(
            participant1_state,
            participant2_state
        );
        // The sum of the provided balances must be equal to the total
        // available deposit
        require(total_available_deposit == (participant1_balance + participant2_balance));
        // Overflow check for the balances addition from the above check.
        // This overflow should never happen if the token.transfer function is implemented
        // correctly. We do not control the token implementation, therefore we add this
        // check for safety.
        require(participant1_balance <= participant1_balance + participant2_balance);

        // Remove channel data from storage before doing the token transfers
        delete channel.participants[participant1];
        delete channel.participants[participant2];
        delete channels[channel_identifier];

        // Remove the pair's channel counter
        delete participants_hash_to_channel_identifier[pair_hash];

        emit ChannelSettled(channel_identifier, participant1_balance, participant2_balance);

        // Do the token transfers
        if (participant1_balance > 0) {
            require(token.transfer(participant1, participant1_balance));
        }

        if (participant2_balance > 0) {
            require(token.transfer(participant2, participant2_balance));
        }
    } */

    /// @notice Returns the unique identifier for the channel given by the
    /// contract
    /// @param participant Address of a channel participant
    /// @param partner Address of the other channel participant
    /// @return Unique identifier for the channel. It can be 0 if channel does
    /// not exist
    function getChannelIdentifier(address participant, address partner)
        public
        view
        returns (uint256)
    {
        require(participant != address(0x0));
        require(partner != address(0x0));
        require(participant != partner);

        bytes32 pair_hash = getParticipantsHash(participant, partner);
        return participants_hash_to_channel_identifier[pair_hash];
    }

    /// @dev Returns the channel specific data.
    /// @param channel_identifier Identifier for the channel on which this
    /// operation takes place
    /// @param participant1 Address of a channel participant
    /// @param participant2 Address of the other channel participant
    /// @return Channel settle_block_number and state
    /// @notice The contract cannot really distinguish Settled and Removed
    /// states, especially when wrong participants are given as input.
    /// The contract does not remember the participants of the channel
    function getChannelInfo(
        uint256 channel_identifier,
        address participant1,
        address participant2
    )
        external
        view
        returns (uint256, ChannelState)
    {
        bytes32 unlock_key1;
        bytes32 unlock_key2;

        Channel storage channel = channels[channel_identifier];
        ChannelState state = channel.state;  // This must **not** update the storage

        if (state == ChannelState.NonExistent &&
            channel_identifier > 0 &&
            channel_identifier <= channel_counter
        ) {
            // The channel has been settled, channel data is removed Therefore,
            // the channel state in storage is actually `0`, or `NonExistent`
            // However, for this view function, we return `Settled`, in order
            // to provide a consistent external API
            state = ChannelState.Settled;

            // We might still have data stored for future unlock operations
            // Only if we do not, we can consider the channel as `Removed`
            unlock_key1 = getUnlockIdentifier(channel_identifier, participant1, participant2);
            UnlockData storage unlock_data1 = unlock_identifier_to_unlock_data[unlock_key1];

            unlock_key2 = getUnlockIdentifier(channel_identifier, participant2, participant1);
            UnlockData storage unlock_data2 = unlock_identifier_to_unlock_data[unlock_key2];

            if (unlock_data1.locked_amount == 0 && unlock_data2.locked_amount == 0) {
                state = ChannelState.Removed;
            }
        }

        return (
            channel.settle_block_number,
            state
        );
    }

    /// @dev Returns the channel specific data.
    /// @param channel_identifier Identifier for the channel on which this
    /// operation takes place
    /// @param participant Address of the channel participant whose data will be
    /// returned
    /// @param partner Address of the channel partner
    /// @return Participant's deposit, withdrawn_amount, whether the participant
    /// has called `closeChannel` or not, balance_hash, nonce, locksroot,
    /// locked_amount
    function getChannelParticipantInfo(
            uint256 channel_identifier,
            address participant,
            address partner
    )
        external
        view
        returns (uint256, uint256, bool, bytes32, uint256, bytes32, uint256)
    {
        bytes32 unlock_key;

        Participant storage participant_state = channels[channel_identifier].participants[
            participant
        ];
        unlock_key = getUnlockIdentifier(channel_identifier, participant, partner);
        UnlockData storage unlock_data = unlock_identifier_to_unlock_data[unlock_key];

        return (
            participant_state.deposit,
            participant_state.withdrawn_amount,
            participant_state.is_the_closer,
            participant_state.balance_hash,
            participant_state.nonce,
            unlock_data.locksroot,
            unlock_data.locked_amount
        );
    }

    /// @dev Get the hash of the participant addresses, ordered
    /// lexicographically
    /// @param participant Address of a channel participant
    /// @param partner Address of the other channel participant
    function getParticipantsHash(address participant, address partner)
        public
        pure
        returns (bytes32)
    {
        require(participant != address(0x0));
        require(partner != address(0x0));
        require(participant != partner);

        if (participant < partner) {
            return keccak256(abi.encodePacked(participant, partner));
        } else {
            return keccak256(abi.encodePacked(partner, participant));
        }
    }

    /// @dev Get the hash of the channel identifier and the participant
    /// addresses (whose ordering matters). The hash might be useful for
    /// the receiver to look up the appropriate UnlockData to claim
    /// @param channel_identifier Identifier for the channel which the
    /// UnlockData is about
    /// @param sender Sender of the pending transfers that the UnlockData
    /// represents
    /// @param receiver Receiver of the pending transfers that the UnlockData
    /// represents
    function getUnlockIdentifier(
        uint256 channel_identifier,
        address sender,
        address receiver
    )
        public
        pure
        returns (bytes32)
    {
        require(sender != receiver);
        return keccak256(abi.encodePacked(channel_identifier, sender, receiver));
    }

    function updateBalanceProofData(
        Channel storage channel,
        address participant,
        uint256 nonce,
        bytes32 balance_hash
    )
        internal
    {
        Participant storage participant_state = channel.participants[participant];

        // Multiple calls to updateNonClosingBalanceProof can be made and we
        // need to store the last known balance proof data.
        // This line prevents Monitoring Services from getting rewards
        // again and again using the same reward proof.
        require(nonce > participant_state.nonce);

        participant_state.nonce = nonce;
        participant_state.balance_hash = balance_hash;
    }

    function storeUnlockData(
        uint256 channel_identifier,
        address sender,
        address receiver,
        uint256 locked_amount,
        bytes32 locksroot
    )
        internal
    {
        // If there are transfers to unlock, store the locksroot and total
        // amount of tokens
        if (locked_amount == 0) {
            return;
        }

        bytes32 key = getUnlockIdentifier(channel_identifier, sender, receiver);
        UnlockData storage unlock_data = unlock_identifier_to_unlock_data[key];
        unlock_data.locksroot = locksroot;
        unlock_data.locked_amount = locked_amount;
    }

    function getChannelAvailableDeposit(
        Participant storage participant1_state,
        Participant storage participant2_state
    )
        internal
        view
        returns (uint256 total_available_deposit)
    {
        total_available_deposit = (
            participant1_state.deposit +
            participant2_state.deposit -
            participant1_state.withdrawn_amount -
            participant2_state.withdrawn_amount
        );
    }

    /// @dev Function that calculates the amount of tokens that the participants
    /// will receive when calling settleChannel.
    /// Check https://github.com/raiden-network/raiden-contracts/issues/188 for the settlement
    /// algorithm analysis and explanations.
    function getSettleTransferAmounts(
        Participant storage participant1_state,
        uint256 participant1_transferred_amount,
        uint256 participant1_locked_amount,
        Participant storage participant2_state,
        uint256 participant2_transferred_amount,
        uint256 participant2_locked_amount
    )
        private
        view
        returns (uint256, uint256, uint256, uint256)
    {
        // The scope of this function is to compute the settlement amounts that
        // the two channel participants will receive when calling settleChannel
        // and the locked amounts that remain in the contract, to account for
        // the pending, not finalized transfers, that will be received by the
        // participants when calling `unlock`.

        // The amount of tokens that participant1 MUST receive at the end of
        // the channel lifecycle (after settleChannel and unlock) is:
        // B1 = D1 - W1 + T2 - T1 + Lc2 - Lc1

        // The amount of tokens that participant2 MUST receive at the end of
        // the channel lifecycle (after settleChannel and unlock) is:
        // B2 = D2 - W2 + T1 - T2 + Lc1 - Lc2

        // B1 + B2 = TAD = D1 + D2 - W1 - W2
        // TAD = total available deposit at settlement time

        // L1 = Lc1 + Lu1
        // L2 = Lc2 + Lu2

        // where:
        // B1 = final balance of participant1 after the channel is removed
        // D1 = total amount deposited by participant1 into the channel
        // W1 = total amount withdrawn by participant1 from the channel
        // T2 = total amount transferred by participant2 to participant1 (finalized transfers)
        // T1 = total amount transferred by participant1 to participant2 (finalized transfers)
        // L1 = total amount of tokens locked in pending transfers, sent by
        //   participant1 to participant2
        // L2 = total amount of tokens locked in pending transfers, sent by
        //   participant2 to participant1
        // Lc2 = the amount that can be claimed by participant1 from the pending
        //   transfers (that have not been finalized off-chain), sent by
        //   participant2 to participant1. These are part of the locked amount
        //   value from participant2's balance proof. They are considered claimed
        //   if the secret corresponding to these locked transfers was registered
        //   on-chain, in the SecretRegistry contract, before the lock's expiration.
        // Lu1 = unclaimable locked amount from L1
        // Lc1 = the amount that can be claimed by participant2 from the pending
        //   transfers (that have not been finalized off-chain),
        //   sent by participant1 to participant2
        // Lu2 = unclaimable locked amount from L2

        // Notes:
        // 1) The unclaimble tokens from a locked amount will return to the sender.
        // At the time of calling settleChannel, the TokenNetwork contract does
        // not know what locked amounts are claimable or unclaimable.
        // 2) There are some Solidity constraints that make the calculations
        // more difficult: attention to overflows and underflows, that MUST be
        // handled without throwing.

        // Cases that require attention:
        // case1. If participant1 does NOT provide a balance proof or provides
        // an old balance proof.  participant2_transferred_amount can be [0,
        // real_participant2_transferred_amount) We MUST NOT punish
        // participant2.
        // case2. If participant2 does NOT provide a balance proof or provides
        // an old balance proof.  participant1_transferred_amount can be [0,
        // real_participant1_transferred_amount) We MUST NOT punish
        // participant1.
        // case3. If neither participants provide a balance proof, we just
        // subtract their withdrawn amounts from their deposits.

        // This is why, the algorithm implemented in Solidity is:
        // (explained at each step, below)
        // RmaxP1 = (T2 + L2) - (T1 + L1) + D1 - W1
        // RmaxP1 = min(TAD, RmaxP1)
        // RmaxP2 = TAD - RmaxP1
        // SL2 = min(RmaxP1, L2)
        // S1 = RmaxP1 - SL2
        // SL1 = min(RmaxP2, L1)
        // S2 = RmaxP2 - SL1

        // where:
        // RmaxP1 = due to possible over/underflows that only appear when using
        //    old balance proofs & the fact that settlement balance calculation
        //    is symmetric (we can calculate either RmaxP1 and RmaxP2 first,
        //    order does not affect result), this is a convention used to determine
        //    the maximum receivable amount of participant1 at settlement time
        // S1 = amount received by participant1 when calling settleChannel
        // SL1 = the maximum amount from L1 that can be locked in the
        //   TokenNetwork contract when calling settleChannel (due to overflows
        //   that only happen when using old balance proofs)
        // S2 = amount received by participant2 when calling settleChannel
        // SL2 = the maximum amount from L2 that can be locked in the
        //   TokenNetwork contract when calling settleChannel (due to overflows
        //   that only happen when using old balance proofs)

        uint256 participant1_amount;
        uint256 participant2_amount;
        uint256 total_available_deposit;

        SettlementData memory participant1_settlement;
        SettlementData memory participant2_settlement;

        participant1_settlement.deposit = participant1_state.deposit;
        participant1_settlement.withdrawn = participant1_state.withdrawn_amount;
        participant1_settlement.transferred = participant1_transferred_amount;
        participant1_settlement.locked = participant1_locked_amount;

        participant2_settlement.deposit = participant2_state.deposit;
        participant2_settlement.withdrawn = participant2_state.withdrawn_amount;
        participant2_settlement.transferred = participant2_transferred_amount;
        participant2_settlement.locked = participant2_locked_amount;

        // TAD = D1 + D2 - W1 - W2 = total available deposit at settlement time
        total_available_deposit = getChannelAvailableDeposit(
            participant1_state,
            participant2_state
        );

        // RmaxP1 = (T2 + L2) - (T1 + L1) + D1 - W1
        // This amount is the maximum possible amount that participant1 can
        // receive at settlement time and also contains the entire locked amount
        //  of the pending transfers from participant2 to participant1.
        participant1_amount = getMaxPossibleReceivableAmount(
            participant1_settlement,
            participant2_settlement
        );

        // RmaxP1 = min(TAD, RmaxP1)
        // We need to bound this to the available channel deposit in order to
        // not send tokens from other channels. The only case where TAD is
        // smaller than RmaxP1 is when at least one balance proof is old.
        participant1_amount = min(participant1_amount, total_available_deposit);

        // RmaxP2 = TAD - RmaxP1
        // Now it is safe to subtract without underflow
        participant2_amount = total_available_deposit - participant1_amount;

        // SL2 = min(RmaxP1, L2)
        // S1 = RmaxP1 - SL2
        // Both operations are done by failsafe_subtract
        // We take out participant2's pending transfers locked amount, bounding
        // it by the maximum receivable amount of participant1
        (participant1_amount, participant2_locked_amount) = failsafe_subtract(
            participant1_amount,
            participant2_locked_amount
        );

        // SL1 = min(RmaxP2, L1)
        // S2 = RmaxP2 - SL1
        // Both operations are done by failsafe_subtract
        // We take out participant1's pending transfers locked amount, bounding
        // it by the maximum receivable amount of participant2
        (participant2_amount, participant1_locked_amount) = failsafe_subtract(
            participant2_amount,
            participant1_locked_amount
        );

        // This should never throw:
        // S1 and S2 MUST be smaller than TAD
        assert(participant1_amount <= total_available_deposit);
        assert(participant2_amount <= total_available_deposit);
        // S1 + S2 + SL1 + SL2 == TAD
        assert(total_available_deposit == (
            participant1_amount +
            participant2_amount +
            participant1_locked_amount +
            participant2_locked_amount
        ));

        return (
            participant1_amount,
            participant2_amount,
            participant1_locked_amount,
            participant2_locked_amount
        );
    }

    function getMaxPossibleReceivableAmount(
        SettlementData memory participant1_settlement,
        SettlementData memory participant2_settlement
    )
        internal
        pure
        returns (uint256)
    {
        uint256 participant1_max_transferred;
        uint256 participant2_max_transferred;
        uint256 participant1_net_max_received;
        uint256 participant1_max_amount;

        // This is the maximum possible amount that participant1 could transfer
        // to participant2, if all the pending lock secrets have been
        // registered
        participant1_max_transferred = failsafe_addition(
            participant1_settlement.transferred,
            participant1_settlement.locked
        );

        // This is the maximum possible amount that participant2 could transfer
        // to participant1, if all the pending lock secrets have been
        // registered
        participant2_max_transferred = failsafe_addition(
            participant2_settlement.transferred,
            participant2_settlement.locked
        );

        // We enforce this check artificially, in order to get rid of hard
        // to deal with over/underflows. Settlement balance calculation is
        // symmetric (we can calculate either RmaxP1 and RmaxP2 first, order does
        // not affect result). This means settleChannel must be called with
        // ordered values.
        require(participant2_max_transferred >= participant1_max_transferred);

        assert(participant1_max_transferred >= participant1_settlement.transferred);
        assert(participant2_max_transferred >= participant2_settlement.transferred);

        // This is the maximum amount that participant1 can receive at settlement time
        participant1_net_max_received = (
            participant2_max_transferred -
            participant1_max_transferred
        );

        // Next, we add the participant1's deposit and subtract the already
        // withdrawn amount
        participant1_max_amount = failsafe_addition(
            participant1_net_max_received,
            participant1_settlement.deposit
        );

        // Subtract already withdrawn amount
        (participant1_max_amount, ) = failsafe_subtract(
            participant1_max_amount,
            participant1_settlement.withdrawn
        );
        return participant1_max_amount;
    }

    function verifyBalanceHashData(
        Participant storage participant,
        uint256 transferred_amount,
        uint256 locked_amount,
        bytes32 locksroot
    )
        internal
        view
        returns (bool)
    {
        // When no balance proof has been provided, we need to check this
        // separately because hashing values of 0 outputs a value != 0
        if (participant.balance_hash == 0 &&
            transferred_amount == 0 &&
            locked_amount == 0
            /* locksroot is ignored. */
        ) {
            return true;
        }

        // Make sure the hash of the provided state is the same as the stored
        // balance_hash
        return participant.balance_hash == keccak256(abi.encodePacked(
            transferred_amount,
            locked_amount,
            locksroot
        ));
    }

    function recoverAddressFromBalanceProof(
        uint256 channel_identifier,
        bytes32 balance_hash,
        uint256 nonce,
        bytes32 additional_hash,
        bytes memory signature
    )
        internal
        view
        returns (address signature_address)
    {
        // Length of the actual message: 20 + 32 + 32 + 32 + 32 + 32 + 32
        string memory message_length = '212';

        bytes32 message_hash = keccak256(abi.encodePacked(
            signature_prefix,
            message_length,
            address(this),
            chain_id,
            uint256(MessageTypeId.BalanceProof),
            channel_identifier,
            balance_hash,
            nonce,
            additional_hash
        ));

        signature_address = ECVerify.ecverify(message_hash, signature);
    }

    function recoverAddressFromBalanceProofCounterSignature(
        MessageTypeId message_type_id,
        uint256 channel_identifier,
        bytes32 balance_hash,
        uint256 nonce,
        bytes32 additional_hash,
        bytes memory closing_signature,
        bytes memory non_closing_signature
    )
        internal
        view
        returns (address signature_address)
    {
        // Length of the actual message: 20 + 32 + 32 + 32 + 32 + 32 + 32 + 65
        string memory message_length = '277';

        bytes32 message_hash = keccak256(abi.encodePacked(
            signature_prefix,
            message_length,
            address(this),
            chain_id,
            uint256(message_type_id),
            channel_identifier,
            balance_hash,
            nonce,
            additional_hash,
            closing_signature
        ));

        signature_address = ECVerify.ecverify(message_hash, non_closing_signature);
    }

    /* function recoverAddressFromCooperativeSettleSignature(
        uint256 channel_identifier,
        address participant1,
        uint256 participant1_balance,
        address participant2,
        uint256 participant2_balance,
        bytes signature
    )
        view
        internal
        returns (address signature_address)
    {
        // Length of the actual message: 20 + 32 + 32 + 32 + 20 + 32 + 20 + 32
        string memory message_length = '220';

        bytes32 message_hash = keccak256(abi.encodePacked(
            signature_prefix,
            message_length,
            address(this),
            chain_id,
            uint256(MessageTypeId.CooperativeSettle),
            channel_identifier,
            participant1,
            participant1_balance,
            participant2,
            participant2_balance
        ));

        signature_address = ECVerify.ecverify(message_hash, signature);
    } */

    function recoverAddressFromWithdrawMessage(
        uint256 channel_identifier,
        address participant,
        uint256 total_withdraw,
        uint256 expiration_block,
        bytes memory signature
    )
        internal
        view
        returns (address signature_address)
    {
        // Length of the actual message: 20 + 32 + 32 + 32 + 20 + 32 + 32
        string memory message_length = '200';

        bytes32 message_hash = keccak256(abi.encodePacked(
            signature_prefix,
            message_length,
            address(this),
            chain_id,
            uint256(MessageTypeId.Withdraw),
            channel_identifier,
            participant,
            total_withdraw,
            expiration_block
        ));

        signature_address = ECVerify.ecverify(message_hash, signature);
    }

    /// @dev Calculates the hash of the pending transfers data and
    /// calculates the amount of tokens that can be unlocked because the secret
    /// was registered on-chain.
    function getHashAndUnlockedAmount(bytes memory locks)
        internal
        view
        returns (bytes32, uint256)
    {
        uint256 length = locks.length;

        // each lock has this form:
        // (locked_amount || expiration_block || secrethash) = 3 * 32 bytes
        require(length % 96 == 0);

        uint256 i;
        uint256 total_unlocked_amount;
        uint256 unlocked_amount;
        bytes32 lockhash;
        bytes32 total_hash;

        for (i = 32; i < length; i += 96) {
            unlocked_amount = getLockedAmountFromLock(locks, i);
            total_unlocked_amount += unlocked_amount;
        }

        total_hash = keccak256(locks);

        return (total_hash, total_unlocked_amount);
    }

    function getLockedAmountFromLock(bytes memory locks, uint256 offset)
        internal
        view
        returns (uint256)
    {
        uint256 expiration_block;
        uint256 locked_amount;
        uint256 reveal_block;
        bytes32 secrethash;

        if (locks.length <= offset) {
            return 0;
        }

        assembly {
            expiration_block := mload(add(locks, offset))
            locked_amount := mload(add(locks, add(offset, 32)))
            secrethash := mload(add(locks, add(offset, 64)))
        }

        // Check if the lock's secret was revealed in the SecretRegistry The
        // secret must have been revealed in the SecretRegistry contract before
        // the lock's expiration_block in order for the hash time lock transfer
        // to be successful.
        reveal_block = secret_registry.getSecretRevealBlockHeight(secrethash);
        if (reveal_block == 0 || expiration_block <= reveal_block) {
            locked_amount = 0;
        }

        return locked_amount;
    }

    function min(uint256 a, uint256 b) internal pure returns (uint256)
    {
        return a > b ? b : a;
    }

    function max(uint256 a, uint256 b) internal pure returns (uint256)
    {
        return a > b ? a : b;
    }

    /// @dev Special subtraction function that does not fail when underflowing.
    /// @param a Minuend
    /// @param b Subtrahend
    /// @return Minimum between the result of the subtraction and 0, the maximum
    /// subtrahend for which no underflow occurs
    function failsafe_subtract(uint256 a, uint256 b)
        internal
        pure
        returns (uint256, uint256)
    {
        return a > b ? (a - b, b) : (0, a);
    }

    /// @dev Special addition function that does not fail when overflowing.
    /// @param a Addend
    /// @param b Addend
    /// @return Maximum between the result of the addition or the maximum
    /// uint256 value
    function failsafe_addition(uint256 a, uint256 b)
        internal
        pure
        returns (uint256)
    {
        uint256 sum = a + b;
        return sum >= a ? sum : MAX_SAFE_UINT256;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_token_address","type":"address"},{"internalType":"address","name":"_secret_registry","type":"address"},{"internalType":"uint256","name":"_chain_id","type":"uint256"},{"internalType":"uint256","name":"_settlement_timeout_min","type":"uint256"},{"internalType":"uint256","name":"_settlement_timeout_max","type":"uint256"},{"internalType":"address","name":"_deprecation_executor","type":"address"},{"internalType":"uint256","name":"_channel_participant_deposit_limit","type":"uint256"},{"internalType":"uint256","name":"_token_network_deposit_limit","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"indexed":true,"internalType":"address","name":"closing_participant","type":"address"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"balance_hash","type":"bytes32"}],"name":"ChannelClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"indexed":true,"internalType":"address","name":"participant","type":"address"},{"indexed":false,"internalType":"uint256","name":"total_deposit","type":"uint256"}],"name":"ChannelNewDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"indexed":true,"internalType":"address","name":"participant1","type":"address"},{"indexed":true,"internalType":"address","name":"participant2","type":"address"},{"indexed":false,"internalType":"uint256","name":"settle_timeout","type":"uint256"}],"name":"ChannelOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"participant1_amount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"participant1_locksroot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"participant2_amount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"participant2_locksroot","type":"bytes32"}],"name":"ChannelSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes32","name":"locksroot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"unlocked_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"returned_tokens","type":"uint256"}],"name":"ChannelUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"indexed":true,"internalType":"address","name":"participant","type":"address"},{"indexed":false,"internalType":"uint256","name":"total_withdraw","type":"uint256"}],"name":"ChannelWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"new_value","type":"bool"}],"name":"DeprecationSwitch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"indexed":true,"internalType":"address","name":"closing_participant","type":"address"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"balance_hash","type":"bytes32"}],"name":"NonClosingBalanceProofUpdated","type":"event"},{"inputs":[],"name":"MAX_SAFE_UINT256","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chain_id","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"channel_counter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"channel_participant_deposit_limit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"channels","outputs":[{"internalType":"uint256","name":"settle_block_number","type":"uint256"},{"internalType":"enum TokenNetwork.ChannelState","name":"state","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"internalType":"address","name":"non_closing_participant","type":"address"},{"internalType":"address","name":"closing_participant","type":"address"},{"internalType":"bytes32","name":"balance_hash","type":"bytes32"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes32","name":"additional_hash","type":"bytes32"},{"internalType":"bytes","name":"non_closing_signature","type":"bytes"},{"internalType":"bytes","name":"closing_signature","type":"bytes"}],"name":"closeChannel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contract_address","type":"address"}],"name":"contractExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deprecate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deprecation_executor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"},{"internalType":"address","name":"partner","type":"address"}],"name":"getChannelIdentifier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"internalType":"address","name":"participant1","type":"address"},{"internalType":"address","name":"participant2","type":"address"}],"name":"getChannelInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"enum TokenNetwork.ChannelState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"internalType":"address","name":"participant","type":"address"},{"internalType":"address","name":"partner","type":"address"}],"name":"getChannelParticipantInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"},{"internalType":"address","name":"partner","type":"address"}],"name":"getParticipantsHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"}],"name":"getUnlockIdentifier","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"participant1","type":"address"},{"internalType":"address","name":"participant2","type":"address"},{"internalType":"uint256","name":"settle_timeout","type":"uint256"}],"name":"openChannel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"participants_hash_to_channel_identifier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"safety_deprecation_switch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secret_registry","outputs":[{"internalType":"contract SecretRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"internalType":"address","name":"participant","type":"address"},{"internalType":"uint256","name":"total_deposit","type":"uint256"},{"internalType":"address","name":"partner","type":"address"}],"name":"setTotalDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"internalType":"address","name":"participant","type":"address"},{"internalType":"uint256","name":"total_withdraw","type":"uint256"},{"internalType":"uint256","name":"expiration_block","type":"uint256"},{"internalType":"bytes","name":"participant_signature","type":"bytes"},{"internalType":"bytes","name":"partner_signature","type":"bytes"}],"name":"setTotalWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"internalType":"address","name":"participant1","type":"address"},{"internalType":"uint256","name":"participant1_transferred_amount","type":"uint256"},{"internalType":"uint256","name":"participant1_locked_amount","type":"uint256"},{"internalType":"bytes32","name":"participant1_locksroot","type":"bytes32"},{"internalType":"address","name":"participant2","type":"address"},{"internalType":"uint256","name":"participant2_transferred_amount","type":"uint256"},{"internalType":"uint256","name":"participant2_locked_amount","type":"uint256"},{"internalType":"bytes32","name":"participant2_locksroot","type":"bytes32"}],"name":"settleChannel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settlement_timeout_max","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"settlement_timeout_min","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"signature_prefix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract Token","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token_network_deposit_limit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"locks","type":"bytes"}],"name":"unlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"channel_identifier","type":"uint256"},{"internalType":"address","name":"closing_participant","type":"address"},{"internalType":"address","name":"non_closing_participant","type":"address"},{"internalType":"bytes32","name":"balance_hash","type":"bytes32"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes32","name":"additional_hash","type":"bytes32"},{"internalType":"bytes","name":"closing_signature","type":"bytes"},{"internalType":"bytes","name":"non_closing_signature","type":"bytes"}],"name":"updateNonClosingBalanceProof","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526000600860146101000a81548160ff0219169083151502179055503480156200002c57600080fd5b5060405162003da738038062003da783398181016040526101008110156200005357600080fd5b810190808051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190505050600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415620000e557600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614156200012057600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156200015b57600080fd5b600086116200016957600080fd5b600085116200017757600080fd5b8484116200018457600080fd5b62000195886200038960201b60201c565b6200019f57600080fd5b620001b0876200038960201b60201c565b620001ba57600080fd5b60008211620001c857600080fd5b60008111620001d657600080fd5b81811015620001e457600080fd5b876000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600281905550846003819055508360048190555060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015620002e457600080fd5b505afa158015620002f9573d6000803e3d6000fd5b505050506040513d60208110156200031057600080fd5b8101908080519060200190929190505050116200032c57600080fd5b82600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816005819055508060068190555050505050505050506200039c565b600080823b905060008111915050919050565b6139fb80620003ac6000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c80637c4734f4116100f9578063b7506d7011610097578063ee4516d911610071578063ee4516d914610bcb578063fadc554b14610c7b578063fc0c546a14610db2578063fe49ba1c14610dfc576101c4565b8063b7506d7014610b34578063b8378f7514610b56578063e5949b5d14610b74576101c4565b806387234237116100d35780638723423714610882578063938bcd67146109055780639cadb1591461097d5780639e67ca5f14610a28576101c4565b80637c4734f4146105b857806382fd779514610630578063838d6e05146107eb576101c4565b80634845be761161016657806363ea01431161014057806363ea0143146104a8578063679b37631461052057806371e759921461053e5780637709bc781461055c576101c4565b80634845be761461042a578063524bef8a146104485780635d6e441b1461048a576101c4565b8063224df42f116101a2578063224df42f1461035a57806323aa81741461037857806324d73a93146103c25780633af973b11461040c576101c4565b806303d9d253146101c95780630a798f24146102ce5780630fcc0c2814610350575b600080fd5b6102cc600480360360808110156101df57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561024657600080fd5b82018360208201111561025857600080fd5b8035906020019184600183028401116401000000008311171561027a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610e7e565b005b61033a600480360360608110156102e457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506111f4565b6040518082815260200191505060405180910390f35b610358611470565b005b610362611551565b6040518082815260200191505060405180910390f35b610380611557565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103ca61157d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104146115a3565b6040518082815260200191505060405180910390f35b6104326115a9565b6040518082815260200191505060405180910390f35b6104746004803603602081101561045e57600080fd5b81019080803590602001909291905050506115af565b6040518082815260200191505060405180910390f35b6104926115c7565b6040518082815260200191505060405180910390f35b61051e600480360360808110156104be57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115cd565b005b6105286119ca565b6040518082815260200191505060405180910390f35b6105466119d0565b6040518082815260200191505060405180910390f35b61059e6004803603602081101561057257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119f4565b604051808215151515815260200191505060405180910390f35b61061a600480360360408110156105ce57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611a07565b6040518082815260200191505060405180910390f35b6107e9600480360361010081101561064757600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001906401000000008111156106cc57600080fd5b8201836020820111156106de57600080fd5b8035906020019184600183028401116401000000008311171561070057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561076357600080fd5b82018360208201111561077557600080fd5b8035906020019184600183028401116401000000008311171561079757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611c13565b005b6108576004803603606081101561080157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611e23565b6040518083815260200182600481111561086d57fe5b60ff1681526020019250505060405180910390f35b61088a611f16565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ca5780820151818401526020810190506108af565b50505050905090810190601f1680156108f75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6109676004803603604081101561091b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f4f565b6040518082815260200191505060405180910390f35b610a26600480360361012081101561099457600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050612028565b005b610b32600480360360c0811015610a3e57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190640100000000811115610a9957600080fd5b820183602082011115610aab57600080fd5b80359060200191846001830284011164010000000083111715610acd57600080fd5b909192939192939080359060200190640100000000811115610aee57600080fd5b820183602082011115610b0057600080fd5b80359060200191846001830284011164010000000083111715610b2257600080fd5b9091929391929390505050612516565b005b610b3c6128fd565b604051808215151515815260200191505060405180910390f35b610b5e612910565b6040518082815260200191505060405180910390f35b610ba060048036036020811015610b8a57600080fd5b8101908080359060200190929190505050612916565b60405180838152602001826004811115610bb657fe5b60ff1681526020019250505060405180910390f35b610c3760048036036060811015610be157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612947565b604051808881526020018781526020018615151515815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390f35b610db06004803603610100811015610c9257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190640100000000811115610d1757600080fd5b820183602082011115610d2957600080fd5b80359060200191846001830284011164010000000083111715610d4b57600080fd5b909192939192939080359060200190640100000000811115610d6c57600080fd5b820183602082011115610d7e57600080fd5b80359060200191846001830284011164010000000083111715610da057600080fd5b9091929391929390505050612a1c565b005b610dba612cd6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610e6860048036036060811015610e1257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612cfb565b6040518082815260200191505060405180910390f35b610e888383611f4f565b841415610e9457600080fd5b60006004811115610ea157fe5b6009600086815260200190815260200160002060010160009054906101000a900460ff166004811115610ed057fe5b14610eda57600080fd5b6000806000806000610eeb86612dd4565b8094508195505050610efe89888a612cfb565b94506000600b600087815260200190815260200160002090508060010154925084816000015414610f2e57600080fd5b60008311610f3b57600080fd5b610f458484612e40565b93508383039150600b6000878152602001908152602001600020600080820160009055600182016000905550508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff168b7f8c03cf01b3d4e6068cc494e6fe02aa9e3d4af069d37c32ecc3b241af5c37e6c088888760405180848152602001838152602001828152602001935050505060405180910390a460008411156110de576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a866040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561109957600080fd5b505af11580156110ad573d6000803e3d6000fd5b505050506040513d60208110156110c357600080fd5b81019080805190602001909291905050506110dd57600080fd5b5b60008211156111d4576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb89846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561118f57600080fd5b505af11580156111a3573d6000803e3d6000fd5b505050506040513d60208110156111b957600080fd5b81019080805190602001909291905050506111d357600080fd5b5b818310156111de57fe5b838310156111e857fe5b50505050505050505050565b6000801515600860149054906101000a900460ff1615151461121557600080fd5b8160035481101561122557600080fd5b60045481111561123457600080fd5b6000806006546000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156112d857600080fd5b505afa1580156112ec573d6000803e3d6000fd5b505050506040513d602081101561130257600080fd5b81019080805190602001909291905050501061131d57600080fd5b6001600760008282540192505081905550600754905061133d8787611a07565b91506000600a6000848152602001908152602001600020541461135f57600080fd5b80600a6000848152602001908152602001600020819055506000600960008381526020019081526020016000209050600081600001541461139c57fe5b600060048111156113a957fe5b8160010160009054906101000a900460ff1660048111156113c657fe5b146113cd57fe5b85816000018190555060018160010160006101000a81548160ff021916908360048111156113f757fe5b02179055508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16837f669a4b0ac0b9994c0f82ed4dbe07bb421fe74e5951725af4f139c7443ebf049d896040518082815260200191505060405180910390a4819450505050509392505050565b60001515600860149054906101000a900460ff1615151461149057600080fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114ea57600080fd5b6001600860146101000a81548160ff0219169083151502179055507f6151930a846a85f5e64d2dd1cc5deeafb010c63eec4b600458158edd0e33f15d600860149054906101000a900460ff16604051808215151515815260200191505060405180910390a1565b60045481565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60025481565b60065481565b600a6020528060005260406000206000915090505481565b60055481565b60001515600860149054906101000a900460ff161515146115ed57600080fd5b83600160048111156115fb57fe5b6009600083815260200190815260200160002060010160009054906101000a900460ff16600481111561162a57fe5b1461163457600080fd5b61163e8483611f4f565b851461164957600080fd5b6000831161165657600080fd5b60055483111561166557600080fd5b600080600060096000898152602001908152602001600020905060008160020160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260020160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508160000154880394506000851161171f57600080fd5b8785111561172c57600080fd5b87858360000154011461173b57fe5b600654856000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117dd57600080fd5b505afa1580156117f1573d6000803e3d6000fd5b505050506040513d602081101561180757600080fd5b810190808051906020019092919050505001111561182457600080fd5b87826000018190555080600001548260000154019350816000015484101561184b57600080fd5b8873ffffffffffffffffffffffffffffffffffffffff168a7f2b55547a3b586ab51f65ee9ce4927fa6d25191388299988e89e059a02f9dd44584600001546040518082815260200191505060405180910390a36000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561197a57600080fd5b505af115801561198e573d6000803e3d6000fd5b505050506040513d60208110156119a457600080fd5b81019080805190602001909291905050506119be57600080fd5b50505050505050505050565b60075481565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b600080823b905060008111915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611a4257600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611a7c57600080fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611ab557600080fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161015611b7d578282604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140192505050604051602081830303815290604052805190602001209050611c0d565b8183604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401925050506040516020818303038152906040528051906020012090505b92915050565b8760016004811115611c2157fe5b6009600083815260200190815260200160002060010160009054906101000a900460ff166004811115611c5057fe5b14611c5a57600080fd5b611c648789611f4f565b8914611c6f57600080fd5b600080600960008c8152602001908152602001600020905060028160010160006101000a81548160ff02191690836004811115611ca857fe5b021790555060018160020160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160006101000a81548160ff0219169083151502179055504381600001600082825401925050819055506000611d2e60018d8b8b8b8b8b612e59565b90508073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff1614611d6857600080fd5b6000881115611dc557611d7e8c8a8a8a8a613073565b92508273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff1614611db857600080fd5b611dc482848a8c613239565b5b878a73ffffffffffffffffffffffffffffffffffffffff168d7f09d2f946e008c38931cd739dd20e35146deff8ab3134caee6d54fe50816a81b88c6040518082815260200191505060405180910390a4505050505050505050505050565b600080600080600060096000898152602001908152602001600020905060008160010160009054906101000a900460ff16905060006004811115611e6357fe5b816004811115611e6f57fe5b148015611e7c5750600089115b8015611e8a57506007548911155b15611f005760039050611e9e898989612cfb565b93506000600b60008681526020019081526020016000209050611ec28a898b612cfb565b93506000600b6000868152602001908152602001600020905060008260010154148015611ef3575060008160010154145b15611efd57600492505b50505b8160000154819550955050505050935093915050565b6040518060400160405280601a81526020017f19457468657265756d205369676e6564204d6573736167653a0a00000000000081525081565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611f8a57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611fc457600080fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611ffd57600080fd5b60006120098484611a07565b9050600a60008281526020019081526020016000205491505092915050565b6120328885611f4f565b891461203d57600080fd5b60006120498986611a07565b90506000600960008c815260200190815260200160002090506002600481111561206f57fe5b8160010160009054906101000a900460ff16600481111561208c57fe5b1461209657600080fd5b438160000154106120a657600080fd5b60008160020160008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260020160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905061213c828c8c8c6132a7565b61214557600080fd5b612151818888886132a7565b61215a57600080fd5b612168828c8c848b8b613321565b809950819d50829a50839e50505050508260020160008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549060ff02191690556003820160009055600482016000905550508260020160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549060ff0219169055600382016000905560048201600090555050600960008e81526020019081526020016000206000808201600090556001820160006101000a81549060ff02191690555050600a6000858152602001908152602001600020600090556122be8d8d8a8d8d61342a565b6122cb8d898e898961342a565b8c7f8db0e7d323ca765ce9ab550780131837e4942ccfea3be2b635ec1084c81f72628c8b8a896040518085815260200184815260200183815260200182815260200194505050505060405180910390a260008b1115612411576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8d8d6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156123cc57600080fd5b505af11580156123e0573d6000803e3d6000fd5b505050506040513d60208110156123f657600080fd5b810190808051906020019092919050505061241057600080fd5b5b6000871115612507576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb89896040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156124c257600080fd5b505af11580156124d6573d6000803e3d6000fd5b505050506040513d60208110156124ec57600080fd5b810190808051906020019092919050505061250657600080fd5b5b50505050505050505050505050565b876001600481111561252457fe5b6009600083815260200190815260200160002060010160009054906101000a900460ff16600481111561255357fe5b1461255d57600080fd5b6000806000808a1161256e57600080fd5b88431061257a57600080fd5b6125cb8c8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061347a565b73ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff161461260257600080fd5b6126538c8c8c8c8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061347a565b905061265f8b82611f4f565b8c1461266a57600080fd5b6000600960008e8152602001908152602001600020905060008160020160008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050806000015482600001540195508581600101548e01111561272b57600080fd5b80600101548d018d111561273e57600080fd5b81600101548d0394508c85111561275457600080fd5b6000851161276157600080fd5b8c858360010154011461277057fe5b8d73ffffffffffffffffffffffffffffffffffffffff168f7f98ed0357b86b313fa9f968de5c9d2bcf591432355b34aa1ab7e3e9e92f4284088f6040518082815260200191505060405180910390a38c82600101819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8f876040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561287057600080fd5b505af1158015612884573d6000803e3d6000fd5b505050506040513d602081101561289a57600080fd5b81019080805190602001909291905050506128b457600080fd5b81600001548610156128c257fe5b80600001548610156128d057fe5b60008260040154146128de57fe5b60008160040154146128ec57fe5b505050505050505050505050505050565b600860149054906101000a900460ff1681565b60035481565b60096020528060005260406000206000915090508060000154908060010160009054906101000a900460ff16905082565b6000806000806000806000806000600960008d815260200190815260200160002060020160008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506129b58c8c8c612cfb565b91506000600b60008481526020019081526020016000209050816000015482600101548360020160009054906101000a900460ff16846003015485600401548560000154866001015499509950995099509950995099505050509397509397509397909450565b612a268989611f4f565b8a14612a3157600080fd5b6000801b871415612a4157600080fd5b60008611612a4e57600080fd5b6000806000600960008e8152602001908152602001600020905060026004811115612a7557fe5b8160010160009054906101000a900460ff166004811115612a9257fe5b14612a9c57600080fd5b4381600001541015612aad57600080fd5b612b4560028e8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612e59565b92508273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff1614612b7f57600080fd5b612bd08d8b8b8b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613073565b91508173ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff1614612c0a57600080fd5b60008160020160008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060020160009054906101000a900460ff16612c6a57600080fd5b612c76828e8c8e613239565b898d73ffffffffffffffffffffffffffffffffffffffff168f7f6fc5b4f4f9e65bfdc4c45456373906876cee8832b605478e281902468875eaed8e6040518082815260200191505060405180910390a45050505050505050505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612d3657600080fd5b838383604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140193505050506040516020818303038152906040528051906020012090509392505050565b600080600083519050600060608281612de957fe5b0614612df457600080fd5b6000806000806000602094505b85851015612e2557612e13898661366f565b92508284019350606085019450612e01565b88805190602001209050808497509750505050505050915091565b6000818311612e4f5782612e51565b815b905092915050565b600060606040518060400160405280600381526020017f3237370000000000000000000000000000000000000000000000000000000000815250905060006040518060400160405280601a81526020017f19457468657265756d205369676e6564204d6573736167653a0a00000000000081525082306002548d6006811115612ede57fe5b8d8d8d8d8d604051602001808b805190602001908083835b60208310612f195780518252602082019150602081019050602083039250612ef6565b6001836020036101000a0380198251168184511680821785525050505050509050018a805190602001908083835b60208310612f6a5780518252602082019150602081019050602083039250612f47565b6001836020036101000a0380198251168184511680821785525050505050509050018973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140188815260200187815260200186815260200185815260200184815260200183815260200182805190602001908083835b602083106130145780518252602082019150602081019050602083039250612ff1565b6001836020036101000a0380198251168184511680821785525050505050509050019a5050505050505050505050604051602081830303815290604052805190602001209050613064818561377b565b92505050979650505050505050565b600060606040518060400160405280600381526020017f3231320000000000000000000000000000000000000000000000000000000000815250905060006040518060400160405280601a81526020017f19457468657265756d205369676e6564204d6573736167653a0a0000000000008152508230600254600160068111156130f957fe5b8c8c8c8c604051602001808a805190602001908083835b602083106131335780518252602082019150602081019050602083039250613110565b6001836020036101000a03801982511681845116808217855250505050505090500189805190602001908083835b602083106131845780518252602082019150602081019050602083039250613161565b6001836020036101000a0380198251168184511680821785525050505050509050018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401878152602001868152602001858152602001848152602001838152602001828152602001995050505050505050505060405160208183030381529060405280519060200120905061322c818561377b565b9250505095945050505050565b60008460020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060040154831161328e57600080fd5b8281600401819055508181600301819055505050505050565b60008060001b85600301541480156132bf5750600084145b80156132cb5750600083145b156132d95760019050613319565b8383836040516020018084815260200183815260200182815260200193505050506040516020818303038152906040528051906020012085600301541490505b949350505050565b600080600080600080600061333461399d565b61333c61399d565b8e600001548260000181815250508e600101548260200181815250508d8260400181815250508c8260600181815250508b600001548160000181815250508b600101548160200181815250508a816040018181525050898160600181815250506133a68f8d613888565b92506133b282826138a9565b94506133be8584612e40565b945084830393506133cf858b613937565b809b5081965050506133e1848e613937565b809e508195505050828511156133f357fe5b828411156133fd57fe5b898d8587010101831461340c57fe5b84848e8c985098509850985050505050509650965096509692505050565b600082141561343857613473565b6000613445868686612cfb565b90506000600b6000838152602001908152602001600020905082816000018190555083816001018190555050505b5050505050565b600060606040518060400160405280600381526020017f3230300000000000000000000000000000000000000000000000000000000000815250905060006040518060400160405280601a81526020017f19457468657265756d205369676e6564204d6573736167653a0a00000000000081525082306002546003600681111561350057fe5b8c8c8c8c604051602001808a805190602001908083835b6020831061353a5780518252602082019150602081019050602083039250613517565b6001836020036101000a03801982511681845116808217855250505050505090500189805190602001908083835b6020831061358b5780518252602082019150602081019050602083039250613568565b6001836020036101000a0380198251168184511680821785525050505050509050018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018781526020018681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018381526020018281526020019950505050505050505050604051602081830303815290604052805190602001209050613662818561377b565b9250505095945050505050565b60008060008060008587511161368c576000945050505050613775565b858701519350602086018701519250604086018701519050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c1f62946826040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561371757600080fd5b505afa15801561372b573d6000803e3d6000fd5b505050506040513d602081101561374157600080fd5b8101908080519060200190929190505050915060008214806137635750818411155b1561376d57600092505b829450505050505b92915050565b6000604182511461378b57600080fd5b60008060006020850151925060408501519150606085015160001a9050601b8160ff1610156137bb57601b810190505b601b8160ff1614806137d05750601c8160ff16145b6137d957600080fd5b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613836573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561387c57600080fd5b83935050505092915050565b60008160010154836001015483600001548560000154010303905092915050565b60008060008060006138c38760400151886060015161395c565b93506138d78660400151876060015161395c565b9250838310156138e657600080fd5b86604001518410156138f457fe5b856040015183101561390257fe5b838303915061391582886000015161395c565b9050613925818860200151613937565b50809150508094505050505092915050565b60008082841161394c57600084819150613951565b828403835b915091509250929050565b600080828401905083811015613992577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613994565b805b91505092915050565b604051806080016040528060008152602001600081526020016000815260200160008152509056fea26469706673582212208dd315d3eefaf6a432871865941baa5fa54c8e0eaa7f48d8104ab992c364098b64736f6c63430006040033000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000070f0c29b946e63803bd0be796e17e47138668a680000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000bbf11c2f66e1887681c902095cefb1018c854c0f00000000000000000000000000000000000000000000000040fe01d848bc7ad00000000000000000000000000000000000000000000000fde03734dc203fbc80

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101c45760003560e01c80637c4734f4116100f9578063b7506d7011610097578063ee4516d911610071578063ee4516d914610bcb578063fadc554b14610c7b578063fc0c546a14610db2578063fe49ba1c14610dfc576101c4565b8063b7506d7014610b34578063b8378f7514610b56578063e5949b5d14610b74576101c4565b806387234237116100d35780638723423714610882578063938bcd67146109055780639cadb1591461097d5780639e67ca5f14610a28576101c4565b80637c4734f4146105b857806382fd779514610630578063838d6e05146107eb576101c4565b80634845be761161016657806363ea01431161014057806363ea0143146104a8578063679b37631461052057806371e759921461053e5780637709bc781461055c576101c4565b80634845be761461042a578063524bef8a146104485780635d6e441b1461048a576101c4565b8063224df42f116101a2578063224df42f1461035a57806323aa81741461037857806324d73a93146103c25780633af973b11461040c576101c4565b806303d9d253146101c95780630a798f24146102ce5780630fcc0c2814610350575b600080fd5b6102cc600480360360808110156101df57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561024657600080fd5b82018360208201111561025857600080fd5b8035906020019184600183028401116401000000008311171561027a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610e7e565b005b61033a600480360360608110156102e457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506111f4565b6040518082815260200191505060405180910390f35b610358611470565b005b610362611551565b6040518082815260200191505060405180910390f35b610380611557565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103ca61157d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104146115a3565b6040518082815260200191505060405180910390f35b6104326115a9565b6040518082815260200191505060405180910390f35b6104746004803603602081101561045e57600080fd5b81019080803590602001909291905050506115af565b6040518082815260200191505060405180910390f35b6104926115c7565b6040518082815260200191505060405180910390f35b61051e600480360360808110156104be57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115cd565b005b6105286119ca565b6040518082815260200191505060405180910390f35b6105466119d0565b6040518082815260200191505060405180910390f35b61059e6004803603602081101561057257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119f4565b604051808215151515815260200191505060405180910390f35b61061a600480360360408110156105ce57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611a07565b6040518082815260200191505060405180910390f35b6107e9600480360361010081101561064757600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001906401000000008111156106cc57600080fd5b8201836020820111156106de57600080fd5b8035906020019184600183028401116401000000008311171561070057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561076357600080fd5b82018360208201111561077557600080fd5b8035906020019184600183028401116401000000008311171561079757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611c13565b005b6108576004803603606081101561080157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611e23565b6040518083815260200182600481111561086d57fe5b60ff1681526020019250505060405180910390f35b61088a611f16565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ca5780820151818401526020810190506108af565b50505050905090810190601f1680156108f75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6109676004803603604081101561091b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f4f565b6040518082815260200191505060405180910390f35b610a26600480360361012081101561099457600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050612028565b005b610b32600480360360c0811015610a3e57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190640100000000811115610a9957600080fd5b820183602082011115610aab57600080fd5b80359060200191846001830284011164010000000083111715610acd57600080fd5b909192939192939080359060200190640100000000811115610aee57600080fd5b820183602082011115610b0057600080fd5b80359060200191846001830284011164010000000083111715610b2257600080fd5b9091929391929390505050612516565b005b610b3c6128fd565b604051808215151515815260200191505060405180910390f35b610b5e612910565b6040518082815260200191505060405180910390f35b610ba060048036036020811015610b8a57600080fd5b8101908080359060200190929190505050612916565b60405180838152602001826004811115610bb657fe5b60ff1681526020019250505060405180910390f35b610c3760048036036060811015610be157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612947565b604051808881526020018781526020018615151515815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390f35b610db06004803603610100811015610c9257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190640100000000811115610d1757600080fd5b820183602082011115610d2957600080fd5b80359060200191846001830284011164010000000083111715610d4b57600080fd5b909192939192939080359060200190640100000000811115610d6c57600080fd5b820183602082011115610d7e57600080fd5b80359060200191846001830284011164010000000083111715610da057600080fd5b9091929391929390505050612a1c565b005b610dba612cd6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610e6860048036036060811015610e1257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612cfb565b6040518082815260200191505060405180910390f35b610e888383611f4f565b841415610e9457600080fd5b60006004811115610ea157fe5b6009600086815260200190815260200160002060010160009054906101000a900460ff166004811115610ed057fe5b14610eda57600080fd5b6000806000806000610eeb86612dd4565b8094508195505050610efe89888a612cfb565b94506000600b600087815260200190815260200160002090508060010154925084816000015414610f2e57600080fd5b60008311610f3b57600080fd5b610f458484612e40565b93508383039150600b6000878152602001908152602001600020600080820160009055600182016000905550508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff168b7f8c03cf01b3d4e6068cc494e6fe02aa9e3d4af069d37c32ecc3b241af5c37e6c088888760405180848152602001838152602001828152602001935050505060405180910390a460008411156110de576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a866040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561109957600080fd5b505af11580156110ad573d6000803e3d6000fd5b505050506040513d60208110156110c357600080fd5b81019080805190602001909291905050506110dd57600080fd5b5b60008211156111d4576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb89846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561118f57600080fd5b505af11580156111a3573d6000803e3d6000fd5b505050506040513d60208110156111b957600080fd5b81019080805190602001909291905050506111d357600080fd5b5b818310156111de57fe5b838310156111e857fe5b50505050505050505050565b6000801515600860149054906101000a900460ff1615151461121557600080fd5b8160035481101561122557600080fd5b60045481111561123457600080fd5b6000806006546000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156112d857600080fd5b505afa1580156112ec573d6000803e3d6000fd5b505050506040513d602081101561130257600080fd5b81019080805190602001909291905050501061131d57600080fd5b6001600760008282540192505081905550600754905061133d8787611a07565b91506000600a6000848152602001908152602001600020541461135f57600080fd5b80600a6000848152602001908152602001600020819055506000600960008381526020019081526020016000209050600081600001541461139c57fe5b600060048111156113a957fe5b8160010160009054906101000a900460ff1660048111156113c657fe5b146113cd57fe5b85816000018190555060018160010160006101000a81548160ff021916908360048111156113f757fe5b02179055508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16837f669a4b0ac0b9994c0f82ed4dbe07bb421fe74e5951725af4f139c7443ebf049d896040518082815260200191505060405180910390a4819450505050509392505050565b60001515600860149054906101000a900460ff1615151461149057600080fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114ea57600080fd5b6001600860146101000a81548160ff0219169083151502179055507f6151930a846a85f5e64d2dd1cc5deeafb010c63eec4b600458158edd0e33f15d600860149054906101000a900460ff16604051808215151515815260200191505060405180910390a1565b60045481565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60025481565b60065481565b600a6020528060005260406000206000915090505481565b60055481565b60001515600860149054906101000a900460ff161515146115ed57600080fd5b83600160048111156115fb57fe5b6009600083815260200190815260200160002060010160009054906101000a900460ff16600481111561162a57fe5b1461163457600080fd5b61163e8483611f4f565b851461164957600080fd5b6000831161165657600080fd5b60055483111561166557600080fd5b600080600060096000898152602001908152602001600020905060008160020160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260020160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508160000154880394506000851161171f57600080fd5b8785111561172c57600080fd5b87858360000154011461173b57fe5b600654856000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117dd57600080fd5b505afa1580156117f1573d6000803e3d6000fd5b505050506040513d602081101561180757600080fd5b810190808051906020019092919050505001111561182457600080fd5b87826000018190555080600001548260000154019350816000015484101561184b57600080fd5b8873ffffffffffffffffffffffffffffffffffffffff168a7f2b55547a3b586ab51f65ee9ce4927fa6d25191388299988e89e059a02f9dd44584600001546040518082815260200191505060405180910390a36000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561197a57600080fd5b505af115801561198e573d6000803e3d6000fd5b505050506040513d60208110156119a457600080fd5b81019080805190602001909291905050506119be57600080fd5b50505050505050505050565b60075481565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b600080823b905060008111915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611a4257600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611a7c57600080fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611ab557600080fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161015611b7d578282604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140192505050604051602081830303815290604052805190602001209050611c0d565b8183604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401925050506040516020818303038152906040528051906020012090505b92915050565b8760016004811115611c2157fe5b6009600083815260200190815260200160002060010160009054906101000a900460ff166004811115611c5057fe5b14611c5a57600080fd5b611c648789611f4f565b8914611c6f57600080fd5b600080600960008c8152602001908152602001600020905060028160010160006101000a81548160ff02191690836004811115611ca857fe5b021790555060018160020160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160006101000a81548160ff0219169083151502179055504381600001600082825401925050819055506000611d2e60018d8b8b8b8b8b612e59565b90508073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff1614611d6857600080fd5b6000881115611dc557611d7e8c8a8a8a8a613073565b92508273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff1614611db857600080fd5b611dc482848a8c613239565b5b878a73ffffffffffffffffffffffffffffffffffffffff168d7f09d2f946e008c38931cd739dd20e35146deff8ab3134caee6d54fe50816a81b88c6040518082815260200191505060405180910390a4505050505050505050505050565b600080600080600060096000898152602001908152602001600020905060008160010160009054906101000a900460ff16905060006004811115611e6357fe5b816004811115611e6f57fe5b148015611e7c5750600089115b8015611e8a57506007548911155b15611f005760039050611e9e898989612cfb565b93506000600b60008681526020019081526020016000209050611ec28a898b612cfb565b93506000600b6000868152602001908152602001600020905060008260010154148015611ef3575060008160010154145b15611efd57600492505b50505b8160000154819550955050505050935093915050565b6040518060400160405280601a81526020017f19457468657265756d205369676e6564204d6573736167653a0a00000000000081525081565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611f8a57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611fc457600080fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611ffd57600080fd5b60006120098484611a07565b9050600a60008281526020019081526020016000205491505092915050565b6120328885611f4f565b891461203d57600080fd5b60006120498986611a07565b90506000600960008c815260200190815260200160002090506002600481111561206f57fe5b8160010160009054906101000a900460ff16600481111561208c57fe5b1461209657600080fd5b438160000154106120a657600080fd5b60008160020160008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260020160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905061213c828c8c8c6132a7565b61214557600080fd5b612151818888886132a7565b61215a57600080fd5b612168828c8c848b8b613321565b809950819d50829a50839e50505050508260020160008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549060ff02191690556003820160009055600482016000905550508260020160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549060ff0219169055600382016000905560048201600090555050600960008e81526020019081526020016000206000808201600090556001820160006101000a81549060ff02191690555050600a6000858152602001908152602001600020600090556122be8d8d8a8d8d61342a565b6122cb8d898e898961342a565b8c7f8db0e7d323ca765ce9ab550780131837e4942ccfea3be2b635ec1084c81f72628c8b8a896040518085815260200184815260200183815260200182815260200194505050505060405180910390a260008b1115612411576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8d8d6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156123cc57600080fd5b505af11580156123e0573d6000803e3d6000fd5b505050506040513d60208110156123f657600080fd5b810190808051906020019092919050505061241057600080fd5b5b6000871115612507576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb89896040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156124c257600080fd5b505af11580156124d6573d6000803e3d6000fd5b505050506040513d60208110156124ec57600080fd5b810190808051906020019092919050505061250657600080fd5b5b50505050505050505050505050565b876001600481111561252457fe5b6009600083815260200190815260200160002060010160009054906101000a900460ff16600481111561255357fe5b1461255d57600080fd5b6000806000808a1161256e57600080fd5b88431061257a57600080fd5b6125cb8c8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061347a565b73ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff161461260257600080fd5b6126538c8c8c8c8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061347a565b905061265f8b82611f4f565b8c1461266a57600080fd5b6000600960008e8152602001908152602001600020905060008160020160008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050806000015482600001540195508581600101548e01111561272b57600080fd5b80600101548d018d111561273e57600080fd5b81600101548d0394508c85111561275457600080fd5b6000851161276157600080fd5b8c858360010154011461277057fe5b8d73ffffffffffffffffffffffffffffffffffffffff168f7f98ed0357b86b313fa9f968de5c9d2bcf591432355b34aa1ab7e3e9e92f4284088f6040518082815260200191505060405180910390a38c82600101819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8f876040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561287057600080fd5b505af1158015612884573d6000803e3d6000fd5b505050506040513d602081101561289a57600080fd5b81019080805190602001909291905050506128b457600080fd5b81600001548610156128c257fe5b80600001548610156128d057fe5b60008260040154146128de57fe5b60008160040154146128ec57fe5b505050505050505050505050505050565b600860149054906101000a900460ff1681565b60035481565b60096020528060005260406000206000915090508060000154908060010160009054906101000a900460ff16905082565b6000806000806000806000806000600960008d815260200190815260200160002060020160008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506129b58c8c8c612cfb565b91506000600b60008481526020019081526020016000209050816000015482600101548360020160009054906101000a900460ff16846003015485600401548560000154866001015499509950995099509950995099505050509397509397509397909450565b612a268989611f4f565b8a14612a3157600080fd5b6000801b871415612a4157600080fd5b60008611612a4e57600080fd5b6000806000600960008e8152602001908152602001600020905060026004811115612a7557fe5b8160010160009054906101000a900460ff166004811115612a9257fe5b14612a9c57600080fd5b4381600001541015612aad57600080fd5b612b4560028e8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612e59565b92508273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff1614612b7f57600080fd5b612bd08d8b8b8b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613073565b91508173ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff1614612c0a57600080fd5b60008160020160008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060020160009054906101000a900460ff16612c6a57600080fd5b612c76828e8c8e613239565b898d73ffffffffffffffffffffffffffffffffffffffff168f7f6fc5b4f4f9e65bfdc4c45456373906876cee8832b605478e281902468875eaed8e6040518082815260200191505060405180910390a45050505050505050505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415612d3657600080fd5b838383604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140193505050506040516020818303038152906040528051906020012090509392505050565b600080600083519050600060608281612de957fe5b0614612df457600080fd5b6000806000806000602094505b85851015612e2557612e13898661366f565b92508284019350606085019450612e01565b88805190602001209050808497509750505050505050915091565b6000818311612e4f5782612e51565b815b905092915050565b600060606040518060400160405280600381526020017f3237370000000000000000000000000000000000000000000000000000000000815250905060006040518060400160405280601a81526020017f19457468657265756d205369676e6564204d6573736167653a0a00000000000081525082306002548d6006811115612ede57fe5b8d8d8d8d8d604051602001808b805190602001908083835b60208310612f195780518252602082019150602081019050602083039250612ef6565b6001836020036101000a0380198251168184511680821785525050505050509050018a805190602001908083835b60208310612f6a5780518252602082019150602081019050602083039250612f47565b6001836020036101000a0380198251168184511680821785525050505050509050018973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140188815260200187815260200186815260200185815260200184815260200183815260200182805190602001908083835b602083106130145780518252602082019150602081019050602083039250612ff1565b6001836020036101000a0380198251168184511680821785525050505050509050019a5050505050505050505050604051602081830303815290604052805190602001209050613064818561377b565b92505050979650505050505050565b600060606040518060400160405280600381526020017f3231320000000000000000000000000000000000000000000000000000000000815250905060006040518060400160405280601a81526020017f19457468657265756d205369676e6564204d6573736167653a0a0000000000008152508230600254600160068111156130f957fe5b8c8c8c8c604051602001808a805190602001908083835b602083106131335780518252602082019150602081019050602083039250613110565b6001836020036101000a03801982511681845116808217855250505050505090500189805190602001908083835b602083106131845780518252602082019150602081019050602083039250613161565b6001836020036101000a0380198251168184511680821785525050505050509050018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401878152602001868152602001858152602001848152602001838152602001828152602001995050505050505050505060405160208183030381529060405280519060200120905061322c818561377b565b9250505095945050505050565b60008460020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060040154831161328e57600080fd5b8281600401819055508181600301819055505050505050565b60008060001b85600301541480156132bf5750600084145b80156132cb5750600083145b156132d95760019050613319565b8383836040516020018084815260200183815260200182815260200193505050506040516020818303038152906040528051906020012085600301541490505b949350505050565b600080600080600080600061333461399d565b61333c61399d565b8e600001548260000181815250508e600101548260200181815250508d8260400181815250508c8260600181815250508b600001548160000181815250508b600101548160200181815250508a816040018181525050898160600181815250506133a68f8d613888565b92506133b282826138a9565b94506133be8584612e40565b945084830393506133cf858b613937565b809b5081965050506133e1848e613937565b809e508195505050828511156133f357fe5b828411156133fd57fe5b898d8587010101831461340c57fe5b84848e8c985098509850985050505050509650965096509692505050565b600082141561343857613473565b6000613445868686612cfb565b90506000600b6000838152602001908152602001600020905082816000018190555083816001018190555050505b5050505050565b600060606040518060400160405280600381526020017f3230300000000000000000000000000000000000000000000000000000000000815250905060006040518060400160405280601a81526020017f19457468657265756d205369676e6564204d6573736167653a0a00000000000081525082306002546003600681111561350057fe5b8c8c8c8c604051602001808a805190602001908083835b6020831061353a5780518252602082019150602081019050602083039250613517565b6001836020036101000a03801982511681845116808217855250505050505090500189805190602001908083835b6020831061358b5780518252602082019150602081019050602083039250613568565b6001836020036101000a0380198251168184511680821785525050505050509050018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018781526020018681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018381526020018281526020019950505050505050505050604051602081830303815290604052805190602001209050613662818561377b565b9250505095945050505050565b60008060008060008587511161368c576000945050505050613775565b858701519350602086018701519250604086018701519050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c1f62946826040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561371757600080fd5b505afa15801561372b573d6000803e3d6000fd5b505050506040513d602081101561374157600080fd5b8101908080519060200190929190505050915060008214806137635750818411155b1561376d57600092505b829450505050505b92915050565b6000604182511461378b57600080fd5b60008060006020850151925060408501519150606085015160001a9050601b8160ff1610156137bb57601b810190505b601b8160ff1614806137d05750601c8160ff16145b6137d957600080fd5b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613836573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561387c57600080fd5b83935050505092915050565b60008160010154836001015483600001548560000154010303905092915050565b60008060008060006138c38760400151886060015161395c565b93506138d78660400151876060015161395c565b9250838310156138e657600080fd5b86604001518410156138f457fe5b856040015183101561390257fe5b838303915061391582886000015161395c565b9050613925818860200151613937565b50809150508094505050505092915050565b60008082841161394c57600084819150613951565b828403835b915091509250929050565b600080828401905083811015613992577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613994565b805b91505092915050565b604051806080016040528060008152602001600081526020016000815260200160008152509056fea26469706673582212208dd315d3eefaf6a432871865941baa5fa54c8e0eaa7f48d8104ab992c364098b64736f6c63430006040033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000070f0c29b946e63803bd0be796e17e47138668a680000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000bbf11c2f66e1887681c902095cefb1018c854c0f00000000000000000000000000000000000000000000000040fe01d848bc7ad00000000000000000000000000000000000000000000000fde03734dc203fbc80

-----Decoded View---------------
Arg [0] : _token_address (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [1] : _secret_registry (address): 0x70f0c29b946E63803BD0Be796E17E47138668A68
Arg [2] : _chain_id (uint256): 1
Arg [3] : _settlement_timeout_min (uint256): 100
Arg [4] : _settlement_timeout_max (uint256): 500
Arg [5] : _deprecation_executor (address): 0xbBF11c2f66E1887681C902095CEfB1018C854c0f
Arg [6] : _channel_participant_deposit_limit (uint256): 4683182690956770000
Arg [7] : _token_network_deposit_limit (uint256): 4683182690956770000000

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [1] : 00000000000000000000000070f0c29b946e63803bd0be796e17e47138668a68
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [4] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [5] : 000000000000000000000000bbf11c2f66e1887681c902095cefb1018c854c0f
Arg [6] : 00000000000000000000000000000000000000000000000040fe01d848bc7ad0
Arg [7] : 0000000000000000000000000000000000000000000000fde03734dc203fbc80


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.