<commit_before>pragma solidity ^0.4.25;
// solium-disable-next-line
pragma experimental ABIEncoderV2;

import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol";


contract TicketBroker {

    struct Sender {
        uint256 deposit;
        uint256 penaltyEscrow;
        uint256 withdrawBlock;
    }

    struct Ticket {
        address recipient;
        address sender;
        uint256 faceValue;
        uint256 winProb;
        uint256 senderNonce;
        bytes32 recipientRandHash;
        bytes auxData;
    }

    uint256 public minPenaltyEscrow;
    uint256 public unlockPeriod;

    mapping (address => Sender) public senders;
    mapping (bytes32 => bool) public usedTickets;

    event DepositFunded(address indexed sender, uint256 amount);
    event PenaltyEscrowFunded(address indexed sender, uint256 amount);
    event WinningTicketRedeemed(
        address indexed sender,
        address indexed recipient,
        uint256 faceValue,
        uint256 winProb,
        uint256 senderNonce,
        uint256 recipientRand,
        bytes auxData
    );
    event WinningTicketTransfer(address indexed sender, address indexed recipient, uint256 amount);
    event PenaltyEscrowSlashed(address indexed sender, address indexed recipient, uint256 amount);
    event Unlock(address indexed sender, uint256 startBlock, uint256 endBlock);
    event UnlockCancelled(address indexed sender);
    event Withdrawal(address indexed sender, uint256 deposit, uint256 penaltyEscrow);

    modifier processDeposit(address _sender, uint256 _amount) {
        Sender storage sender = senders[_sender];
        sender.deposit += _amount;
        if (_isUnlockInProgress(sender)) {
            _cancelUnlock(sender, _sender);
        }

        _;

        emit DepositFunded(_sender, _amount);
    }

    modifier processPenaltyEscrow(address _sender, uint256 _amount) {
        require(_amount >= minPenaltyEscrow, "penalty escrow amount must be >= minPenaltyEscrow");

        Sender storage sender = senders[_sender];
        sender.penaltyEscrow += _amount;
        if (_isUnlockInProgress(sender)) {
            _cancelUnlock(sender, _sender);
        }

        _;

        emit PenaltyEscrowFunded(_sender, _amount);
    }

    constructor(uint256 _minPenaltyEscrow, uint256 _unlockPeriod) internal {
        minPenaltyEscrow = _minPenaltyEscrow;
        unlockPeriod = _unlockPeriod;
    }

    function redeemWinningTicket(Ticket memory _ticket, bytes _sig, uint256 _recipientRand) public {
        bytes32 ticketHash = getTicketHash(_ticket);

        requireValidWinningTicket(_ticket, ticketHash, _sig, _recipientRand);

        Sender storage sender = senders[_ticket.sender];

        require(
            sender.deposit > 0 || sender.penaltyEscrow > 0,
            "sender deposit and penalty escrow are zero"
        );

        usedTickets[ticketHash] = true;

        uint256 amountToTransfer = 0;
        uint256 amountToSlash = 0;

        if (_ticket.faceValue > sender.deposit) {
            amountToTransfer = sender.deposit;
            amountToSlash = sender.penaltyEscrow;

            sender.deposit = 0;
            sender.penaltyEscrow = 0;
        } else {
            amountToTransfer = _ticket.faceValue;
            sender.deposit -= _ticket.faceValue;
        }

        if (amountToSlash > 0) {
            penaltyEscrowSlash(amountToSlash);

            emit PenaltyEscrowSlashed(_ticket.sender, _ticket.recipient, amountToSlash);
        }

        if (amountToTransfer > 0) {
            winningTicketTransfer(_ticket.recipient, amountToTransfer);

            emit WinningTicketTransfer(_ticket.sender, _ticket.recipient, amountToTransfer);
        }

        emit WinningTicketRedeemed(
            _ticket.sender,
            _ticket.recipient,
            _ticket.faceValue,
            _ticket.winProb,
            _ticket.senderNonce,
            _recipientRand,
            _ticket.auxData
        );
    }

    function unlock() public {
        Sender storage sender = senders[msg.sender];

        require(
            sender.deposit > 0 || sender.penaltyEscrow > 0,
            "sender deposit and penalty escrow are zero"
        );
        require(!_isUnlockInProgress(sender), "unlock already initiated");

        sender.withdrawBlock = block.number + unlockPeriod;

        emit Unlock(msg.sender, block.number, sender.withdrawBlock);
    }

    function cancelUnlock() public {
        Sender storage sender = senders[msg.sender];

        _cancelUnlock(sender, msg.sender);
    }

    function withdraw() public {
        Sender storage sender = senders[msg.sender];

        require(
            sender.deposit > 0 || sender.penaltyEscrow > 0,
            "sender deposit and penalty escrow are zero"
        );
        require(
            _isUnlockInProgress(sender), 
            "no unlock request in progress"
        );
        require(
            block.number >= sender.withdrawBlock, 
            "account is locked"
        );

        uint256 deposit = sender.deposit;
        uint256 penaltyEscrow = sender.penaltyEscrow;
        sender.deposit = 0;
        sender.penaltyEscrow = 0;

        withdrawTransfer(msg.sender, deposit + penaltyEscrow);

        emit Withdrawal(msg.sender, deposit, penaltyEscrow);
    }

    function isUnlockInProgress(address _sender) public view returns (bool) {
        Sender memory sender = senders[_sender];
        return _isUnlockInProgress(sender);
    }

    function _cancelUnlock(Sender storage _sender, address _senderAddress) internal {
        require(_isUnlockInProgress(_sender), "no unlock request in progress");

        _sender.withdrawBlock = 0;

        emit UnlockCancelled(_senderAddress);
    }

    function _isUnlockInProgress(Sender sender) internal pure returns (bool) {
        return sender.withdrawBlock > 0;
    }

    // Override
    function withdrawTransfer(address _sender, uint256 _amount) internal;

    // Override
    function winningTicketTransfer(address _recipient, uint256 _amount) internal;

    // Override
    function penaltyEscrowSlash(uint256 _amount) internal;

    // Override
    function requireValidTicketAuxData(bytes _auxData) internal view;

    function requireValidWinningTicket(
        Ticket memory _ticket,
        bytes32 _ticketHash,
        bytes _sig,
        uint256 _recipientRand
    ) 
        internal
        view
    {
        require(_ticket.recipient != address(0), "ticket recipient is null address");
        require(_ticket.sender != address(0), "ticket sender is null address");

        requireValidTicketAuxData(_ticket.auxData);
<commit_msg>PM: explicit memory data location<commit_after>pragma solidity ^0.4.25;
// solium-disable-next-line
pragma experimental ABIEncoderV2;

import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol";


contract TicketBroker {

    struct Sender {
        uint256 deposit;
        uint256 penaltyEscrow;
        uint256 withdrawBlock;
    }

    struct Ticket {
        address recipient;
        address sender;
        uint256 faceValue;
        uint256 winProb;
        uint256 senderNonce;
        bytes32 recipientRandHash;
        bytes auxData;
    }

    uint256 public minPenaltyEscrow;
    uint256 public unlockPeriod;

    mapping (address => Sender) public senders;
    mapping (bytes32 => bool) public usedTickets;

    event DepositFunded(address indexed sender, uint256 amount);
    event PenaltyEscrowFunded(address indexed sender, uint256 amount);
    event WinningTicketRedeemed(
        address indexed sender,
        address indexed recipient,
        uint256 faceValue,
        uint256 winProb,
        uint256 senderNonce,
        uint256 recipientRand,
        bytes auxData
    );
    event WinningTicketTransfer(address indexed sender, address indexed recipient, uint256 amount);
    event PenaltyEscrowSlashed(address indexed sender, address indexed recipient, uint256 amount);
    event Unlock(address indexed sender, uint256 startBlock, uint256 endBlock);
    event UnlockCancelled(address indexed sender);
    event Withdrawal(address indexed sender, uint256 deposit, uint256 penaltyEscrow);

    modifier processDeposit(address _sender, uint256 _amount) {
        Sender storage sender = senders[_sender];
        sender.deposit += _amount;
        if (_isUnlockInProgress(sender)) {
            _cancelUnlock(sender, _sender);
        }

        _;

        emit DepositFunded(_sender, _amount);
    }

    modifier processPenaltyEscrow(address _sender, uint256 _amount) {
        require(_amount >= minPenaltyEscrow, "penalty escrow amount must be >= minPenaltyEscrow");

        Sender storage sender = senders[_sender];
        sender.penaltyEscrow += _amount;
        if (_isUnlockInProgress(sender)) {
            _cancelUnlock(sender, _sender);
        }

        _;

        emit PenaltyEscrowFunded(_sender, _amount);
    }

    constructor(uint256 _minPenaltyEscrow, uint256 _unlockPeriod) internal {
        minPenaltyEscrow = _minPenaltyEscrow;
        unlockPeriod = _unlockPeriod;
    }

    function redeemWinningTicket(Ticket memory _ticket, bytes _sig, uint256 _recipientRand) public {
        bytes32 ticketHash = getTicketHash(_ticket);

        requireValidWinningTicket(_ticket, ticketHash, _sig, _recipientRand);

        Sender storage sender = senders[_ticket.sender];

        require(
            sender.deposit > 0 || sender.penaltyEscrow > 0,
            "sender deposit and penalty escrow are zero"
        );

        usedTickets[ticketHash] = true;

        uint256 amountToTransfer = 0;
        uint256 amountToSlash = 0;

        if (_ticket.faceValue > sender.deposit) {
            amountToTransfer = sender.deposit;
            amountToSlash = sender.penaltyEscrow;

            sender.deposit = 0;
            sender.penaltyEscrow = 0;
        } else {
            amountToTransfer = _ticket.faceValue;
            sender.deposit -= _ticket.faceValue;
        }

        if (amountToSlash > 0) {
            penaltyEscrowSlash(amountToSlash);

            emit PenaltyEscrowSlashed(_ticket.sender, _ticket.recipient, amountToSlash);
        }

        if (amountToTransfer > 0) {
            winningTicketTransfer(_ticket.recipient, amountToTransfer);

            emit WinningTicketTransfer(_ticket.sender, _ticket.recipient, amountToTransfer);
        }

        emit WinningTicketRedeemed(
            _ticket.sender,
            _ticket.recipient,
            _ticket.faceValue,
            _ticket.winProb,
            _ticket.senderNonce,
            _recipientRand,
            _ticket.auxData
        );
    }

    function unlock() public {
        Sender storage sender = senders[msg.sender];

        require(
            sender.deposit > 0 || sender.penaltyEscrow > 0,
            "sender deposit and penalty escrow are zero"
        );
        require(!_isUnlockInProgress(sender), "unlock already initiated");

        sender.withdrawBlock = block.number + unlockPeriod;

        emit Unlock(msg.sender, block.number, sender.withdrawBlock);
    }

    function cancelUnlock() public {
        Sender storage sender = senders[msg.sender];

        _cancelUnlock(sender, msg.sender);
    }

    function withdraw() public {
        Sender storage sender = senders[msg.sender];

        require(
            sender.deposit > 0 || sender.penaltyEscrow > 0,
            "sender deposit and penalty escrow are zero"
        );
        require(
            _isUnlockInProgress(sender), 
            "no unlock request in progress"
        );
        require(
            block.number >= sender.withdrawBlock, 
            "account is locked"
        );

        uint256 deposit = sender.deposit;
        uint256 penaltyEscrow = sender.penaltyEscrow;
        sender.deposit = 0;
        sender.penaltyEscrow = 0;

        withdrawTransfer(msg.sender, deposit + penaltyEscrow);

        emit Withdrawal(msg.sender, deposit, penaltyEscrow);
    }

    function isUnlockInProgress(address _sender) public view returns (bool) {
        Sender memory sender = senders[_sender];
        return _isUnlockInProgress(sender);
    }

    function _cancelUnlock(Sender storage _sender, address _senderAddress) internal {
        require(_isUnlockInProgress(_sender), "no unlock request in progress");

        _sender.withdrawBlock = 0;

        emit UnlockCancelled(_senderAddress);
    }

    function _isUnlockInProgress(Sender memory sender) internal pure returns (bool) {
        return sender.withdrawBlock > 0;
    }

    // Override
    function withdrawTransfer(address _sender, uint256 _amount) internal;

    // Override
    function winningTicketTransfer(address _recipient, uint256 _amount) internal;

    // Override
    function penaltyEscrowSlash(uint256 _amount) internal;

    // Override
    function requireValidTicketAuxData(bytes _auxData) internal view;

    function requireValidWinningTicket(
        Ticket memory _ticket,
        bytes32 _ticketHash,
        bytes _sig,
        uint256 _recipientRand
    ) 
        internal
        view
    {
        require(_ticket.recipient != address(0), "ticket recipient is null address");
        require(_ticket.sender != address(0), "ticket sender is null address");

        requireValidTicketAuxData(_ticket.auxData);

{'fraction_non_alphanumeric': 0.07462911363807516, 'fraction_numerical': 0.01957978763461104, 'mean_word_length': 2.52067868504772, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '899586', 'n_tokens_mistral': 4013, 'n_tokens_neox': 3474, 'n_words': 875}