Update comments of all close functions

Update comments of all close functions

pragma solidity ^0.4.0;

import "./Token.sol";

library NettingChannelLibrary {
    struct Lock
    {
        uint64 expiration;
        uint amount;
        bytes32 hashlock;
    }

    struct Participant
    {
        address node_address;
        uint256 balance;
        uint256 netted;
        uint256 transferred_amount;
        uint256 amount;
        bytes merkle_proof;
        bytes32 hashlock;
        bytes32 secret;
        uint256 expiration;
        uint64 nonce;
        address asset;
        address recipient;
        bytes32 locksroot;
        Lock[] unlocked;
    }

    struct Data {
        uint settle_timeout;
        uint opened;
        uint closed;
        uint settled;
        address closing_address;
        Token token;
        Participant[2] participants;
        mapping(bytes32 => bool) locks;
    }

    modifier notSettledButClosed(Data storage self) {
        if (self.settled > 0 || self.closed == 0)
            throw;
        _;
    }

    modifier stillTimeout(Data storage self) {
        if (self.closed + self.settle_timeout < block.number)
            throw;
        _;
    }

    modifier timeoutOver(Data storage self) {
        if (self.closed + self.settle_timeout > block.number)
            throw;
        _;
    }

    modifier notClosingAddress(Data storage self, address caller) {
        if (caller == self.closing_address)
            throw;
        _;
    }

    /// @notice deposit(uint) to deposit amount to channel.
    /// @dev Deposit an amount to the channel. At least one of the participants
    /// must deposit before the channel is opened.
    /// @param caller_address (address) the address of the invoker of the function
    /// @param channel_address (address) the address of the channel
    /// @param amount (uint) the amount to be deposited to the address
    /// @return success (bool) if the transfer was successful
    /// @return balance (uint256) the new balance of the invoker
    function deposit(
        Data storage self,
        address caller_address,
        address channel_address,
        uint256 amount)
        returns (bool success, uint256 balance)
    {
        uint index;

        if (self.closed != 0) {
            throw;
        }

        if (self.token.balanceOf(caller_address) < amount) {
            throw;
        }

        Participant storage participant = self.participants[0];
        if (participant.node_address != caller_address) {
            participant = self.participants[1];
            if (participant.node_address != caller_address) {
                throw;
            }
        }

        success = self.token.transferFrom(
            caller_address,
            channel_address,
            amount
        );

        if (success == true) {
            balance = participant.balance;
            balance += amount;
            participant.balance = balance;

            if (self.opened == 0) {
                self.opened = block.number;
            }

            return (true, balance);
        }

        return (false, 0);
    }

    /// @notice partner() to get the partner or other participant of the channel
    /// @dev Get the other participating party of the channel
    /// @return (address) the partner of the calling party
    function partner(Data storage self, address one_address) constant returns (address) {
        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (one_address == node1.node_address) {
            return node2.node_address;
        }

        if (one_address == node2.node_address) {
            return node1.node_address;
        }

        return 0x0;
    }

    function addressAndBalance(Data storage self)
        constant
        returns(
        address participant1,
        uint balance1,
        address participant2,
        uint balance2)
    {
        Participant[2] participants = self.participants;
        Participant node1 = participants[0];
        Participant node2 = participants[1];

        // return by name
        participant1 = node1.node_address;
        balance1 = node1.balance;
        participant2 = node2.node_address;
        balance2 = node2.balance;
    }

    /// @notice Close a channel between two parties that was used only unidirectionally
    /// @param caller_address The address of the participant closing the channel
    /// @param signed_transfer The transfer to close the channel with.
    function closeSingleTransfer(Data storage self, address caller_address, bytes signed_transfer) {
        bytes memory transfer_raw;
        address transfer_address;

        if (self.settled > 0 || self.closed > 0) {
            throw;
        }

        if (signed_transfer.length <= 65) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (caller_address != node1.node_address && caller_address != node2.node_address) {
            throw;
        }

        (transfer_raw, transfer_address) = getTransferRawAddress(signed_transfer);

        if (node1.node_address == transfer_address) {
            Participant storage sender = node1;
        } else if (node2.node_address == transfer_address) {
            sender = node2;
        } else {
            throw;
        }

        decodeAndAssign(sender, transfer_raw);

        self.closing_address = caller_address;
        self.closed = block.number;
    }

    /// @notice Close a channel between two parties that had no transfer occur.
    ///         Cases where this may need to happen is when Alice opens a
    ///         channel with Bob and:
    ///         - Nobody put a deposit in. The channel is unused.
    ///         - Alice put a deposit and no transfers were made.
    ///         - Alice put a deposit, BoB also did but no transfers were made.
    ///         - Bob put a deposit and no transfers were made
    /// @param caller_address The address of the participant trying to close
    function closeWithoutTransfer(Data storage self, address caller_address) {

        if (self.settled > 0 || self.closed > 0) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (caller_address != node1.node_address && caller_address != node2.node_address) {
            throw;
        }

        self.closing_address = caller_address;
        self.closed = block.number;
    }

    /// @notice Close a channel between two parties that was used bidirectionally
    /// @param caller_address The address of the participant closing the channel
    /// @param first_encoded the last transfer of the first participant
    /// @param second_encoded the last transfer of the second participant
    function close(
        Data storage self,
        address caller_address,
        bytes first_encoded,
        bytes second_encoded)
    {
        bytes memory first_raw;
        bytes memory second_raw;
        address first_address;
        address second_address;
        bytes32 transfer_sender;

        if (self.settled > 0 || self.closed > 0) {
            throw;
        }

        if (first_encoded.length <= 65 || second_encoded.length <= 65) {
            throw;
        }

        (first_raw, first_address) = getTransferRawAddress(first_encoded);
        (second_raw, second_address) = getTransferRawAddress(second_encoded);

        if (first_address == second_address) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (caller_address != node1.node_address && caller_address != node2.node_address) {
            throw;
        }

        if (node1.node_address == first_address) {
            Participant storage first_sender = node1;
        } else if (node2.node_address == first_address) {
            first_sender = node2;
        } else {
            throw;
        }

        if (node1.node_address == second_address) {
            Participant storage second_sender = node1;
        } else if (node2.node_address == second_address) {
            second_sender = node2;
        } else {
            throw;
        }

        decodeAndAssign(first_sender, first_raw);
        decodeAndAssign(second_sender, second_raw);

        self.closing_address = caller_address;
        self.closed = block.number;
    }

    /// @notice updateTransfer Updates (disputes) the state after closing.
    /// @param caller_address The counterparty to the channel. The participant
    ///                       that did not close the channel.
    /// @param signed_transfer The transfer the counterparty believes is the
    ///                        valid state and wants to dispute with.
    function updateTransfer(Data storage self, address caller_address, bytes signed_transfer)
        notSettledButClosed(self)
        stillTimeout(self)
        notClosingAddress(self, caller_address)
    {
        uint64 nonce;
        bytes memory transfer_raw;
        address transfer_address;

        (transfer_raw, transfer_address) = getTransferRawAddress(signed_transfer);

        // transfer address must be from counter party
        if (self.closing_address != transfer_address) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (node1.node_address == transfer_address) {
            Participant storage sender = node1;
        } else if (node2.node_address == transfer_address) {
            sender = node2;
        } else {
            throw;
        }

        assembly {
            nonce := mload(add(transfer_raw, 12))  // skip cmdid and padding
        }

        if (nonce < sender.nonce || nonce == sender.nonce) {
            throw;
        }

        decodeAndAssign(sender, transfer_raw);

        // TODO check if tampered and penalize
        // TODO check if outdated and penalize
    }

    /// @notice unlock(bytes, bytes, bytes32) to unlock a locked transfer
    /// @dev Unlock a locked transfer
    /// @param locked_encoded (bytes) the lock
    /// @param merkle_proof (bytes) the merkle proof
    /// @param secret (bytes32) the secret
    function unlock(
        Data storage self,
        address caller_address,
        bytes locked_encoded,
        bytes merkle_proof,
        bytes32 secret)
        notSettledButClosed(self)
    {
        uint partner_id;
        uint64 expiration;
        uint amount;
        bytes32 hashlock;
        bytes32 h;
        bytes32 el;

        (expiration, amount, hashlock) = decodeLock(locked_encoded);

        if (self.locks[hashlock]) {
            throw;
        }

        if (expiration < block.number)
            throw;

        if (hashlock != sha3(secret))
            throw;

        Participant[2] storage participants = self.participants;
        Participant storage participant = participants[0];
        if (participant.node_address == caller_address) {
            participant = participants[1];
            if (participant.node_address != caller_address) {
                throw;
            }
        }

        if (participant.nonce == 0) {
            throw;
        }

        h = sha3(locked_encoded);
        for (uint i = 32; i <= merkle_proof.length; i += 32) {
            assembly {
                el := mload(add(merkle_proof, i))
            }

            if (h < el) {
                h = sha3(h, el);
            } else {
                h = sha3(el, h);
            }
        }

        if (participant.locksroot != h)
            throw;

        participant.unlocked.push(Lock(expiration, amount, hashlock));
        self.locks[hashlock] = true;
    }

    /// @notice settle() to settle the balance between the two parties
    /// @dev Settles the balances of the two parties fo the channel
    /// @return participants (Participant[2]) the participants with netted balances
    function settle(Data storage self, address caller_address)
        notSettledButClosed(self)
        timeoutOver(self)
    {
        uint total_netted;
        uint total_deposit;
        uint k;

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        node1.netted = node1.balance + node2.transferred_amount - node1.transferred_amount;
        node2.netted = node2.balance + node1.transferred_amount - node2.transferred_amount;

        for (k = 0; k < node1.unlocked.length; k++) {
            node1.netted += node1.unlocked[k].amount;
            node2.netted -= node1.unlocked[k].amount;
        }

        for (k = 0; k < node2.unlocked.length; k++) {
            node2.netted += node2.unlocked[k].amount;
            node1.netted -= node2.unlocked[k].amount;
        }

        self.settled = block.number;

        total_netted = node1.netted + node2.netted;
        total_deposit = node1.balance + node2.balance;

        if (total_netted != total_deposit) {
            throw;
        }

        if (!self.token.transfer(node1.node_address, node1.netted)) {
            throw;
        }
        if (!self.token.transfer(node2.node_address, node2.netted)) {
            throw;
        }
    }

    function getTransferRawAddress(bytes memory signed_transfer) private returns (bytes memory, address) {
        uint signature_start;
        uint length;
        bytes memory signature;
        bytes memory transfer_raw;
        bytes32 transfer_hash;
        address transfer_address;

        length = signed_transfer.length;
        signature_start = length - 65;
        signature = slice(signed_transfer, signature_start, length);
        transfer_raw = slice(signed_transfer, 0, signature_start);

        transfer_hash = sha3(transfer_raw);
        var (r, s, v) = signatureSplit(signature);
        transfer_address = ecrecover(transfer_hash, v, r, s);

        return (transfer_raw, transfer_address);
    }

    function decodeAndAssign(Participant storage sender, bytes transfer_raw) private {
        // all checks must be done by now
        uint cmdid;

        cmdid = uint(transfer_raw[0]);

        if (cmdid == 5) {
            assignDirectTransfer(sender, transfer_raw);
        } else if (cmdid == 7) {
            assignMediatedTransfer(sender, transfer_raw);
        } else if (cmdid == 8) {
            assignRefundTransfer(sender, transfer_raw);
        } else {
            throw;
        }
    }

    // NOTES about the length of variable types:
    // - variable length types start with a size-prefix of 32bytes (uint256)
    // - bytes is a variable length type
    // - a variable with a bytes type will contain the address of the first data element
    // - solidity starts indexing at 0 (so the 32th byte is at the offset 31)
    //  ref: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI

    // TODO: use sstore instead of these temporaries

    function assignDirectTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 156) {  // raw message size (without signature)
            throw;
        }

        uint64 nonce;
        address asset;
        address recipient;
        uint256 transferred_amount;
        bytes32 locksroot;
        bytes32 secret;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))              // nonce [4:12]
            // identifier [12:20]
            asset := mload(add(message, 40))              // asset [20:40]
            recipient := mload(add(message, 60))          // recipient [40:60]
            transferred_amount := mload(add(message, 92)) // transferred_amount [60:92]
            locksroot := mload(add(message, 124))         // optional_locksroot [92:124]
            secret := mload(add(message, 156))            // optional_secret [124:156]
        }

        participant.nonce = nonce;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.transferred_amount = transferred_amount;
        participant.locksroot = locksroot;
        participant.secret = secret;
    }

    function assignMediatedTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 268) {
            throw;
        }

        uint64 nonce;
        uint64 expiration;
        address asset;
        address recipient;
        bytes32 locksroot;
        bytes32 hashlock;
        uint256 transferred_amount;
        uint256 lock_amount;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))               // nonce [4:12]
            // identifier [12:20]
            expiration := mload(add(message, 28))          // expiration [20:28]
            asset := mload(add(message, 48))               // asset [28:48]
            recipient := mload(add(message, 68))           // recipient [48:68]
            // target [68:88]
            // initiator [88:108]
            locksroot := mload(add(message, 140))          // locksroot [108:140]
            hashlock := mload(add(message, 172))           // hashlock [140:172]
            transferred_amount := mload(add(message, 204)) // transferred_amount[172:204]
            lock_amount := mload(add(message, 236))        // amount [204:236]
            // fee := mload(add(message, 268))             // fee [236:268]
        }

        participant.nonce = nonce;
        participant.expiration = expiration;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.locksroot = locksroot;
        participant.hashlock = hashlock;
        participant.transferred_amount = transferred_amount;
        participant.amount = lock_amount;
    }

    function assignRefundTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 196) {
            throw;
        }

        uint64 nonce;
        uint64 expiration;
        address asset;
        address recipient;
        bytes32 locksroot;
        uint256 transferred_amount;
        uint256 lock_amount;
        bytes32 hashlock;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))                // nonce [4:12]
            // identifier [12:20]
            expiration := mload(add(message, 28))           // expiration [20:28]
            asset := mload(add(message, 48))                // asset [28:48]
            recipient := mload(add(message, 68))            // recipient [48:68]
            locksroot := mload(add(message, 100))           // locksroot [68:100]
            transferred_amount := mload(add(message, 132))  // transferred_amount [100:132]
            lock_amount := mload(add(message, 164))         // amount [132:164]
            hashlock := mload(add(message, 196))            // hashlock [164:196]
        }

        participant.nonce = nonce;
        participant.expiration = expiration;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.locksroot = locksroot;
        participant.transferred_amount = transferred_amount;
        participant.amount = lock_amount;
        participant.hashlock = hashlock;
    }

    function decodeLock(bytes lock) private returns (uint64 expiration, uint amount, bytes32 hashlock) {
        if (lock.length != 72) {
            throw;
        }

        assembly {
            expiration := mload(add(lock, 8))   // expiration [0:8]
            amount := mload(add(lock, 40))      // expiration [8:40]
            hashlock := mload(add(lock, 72))    // expiration [40:72]

        }
    }

    function signatureSplit(bytes signature) private returns (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
            // of 's'. There is no 'mload8' to do this.
            //
            // 'byte' is not working due to the Solidity parser, so lets
            // use the second best option, 'and'
            v := and(mload(add(signature, 65)), 1)
        }
        // old geth sends a `v` value of [0,1], while the new, in line with the YP sends [27,28]
        if(v < 27) v += 27;
    }

    function slice(bytes a, uint start, uint end) private returns (bytes n) {
        if (a.length < end) {
            throw;
        }
        if (start < 0) {
            throw;
        }

        n = new bytes(end-start);
        for (uint i = start; i < end; i ++) { //python style slice
            n[i-start] = a[i];
        }
    }
}

pragma solidity ^0.4.0;

import "./Token.sol";

library NettingChannelLibrary {
    struct Lock
    {
        uint64 expiration;
        uint amount;
        bytes32 hashlock;
    }

    struct Participant
    {
        address node_address;
        uint256 balance;
        uint256 netted;
        uint256 transferred_amount;
        uint256 amount;
        bytes merkle_proof;
        bytes32 hashlock;
        bytes32 secret;
        uint256 expiration;
        uint64 nonce;
        address asset;
        address recipient;
        bytes32 locksroot;
        Lock[] unlocked;
    }

    struct Data {
        uint settle_timeout;
        uint opened;
        uint closed;
        uint settled;
        address closing_address;
        Token token;
        Participant[2] participants;
        mapping(bytes32 => bool) locks;
    }

    modifier notSettledButClosed(Data storage self) {
        if (self.settled > 0 || self.closed == 0)
            throw;
        _;
    }

    modifier stillTimeout(Data storage self) {
        if (self.closed + self.settle_timeout < block.number)
            throw;
        _;
    }

    modifier timeoutOver(Data storage self) {
        if (self.closed + self.settle_timeout > block.number)
            throw;
        _;
    }

    modifier notClosingAddress(Data storage self, address caller) {
        if (caller == self.closing_address)
            throw;
        _;
    }

    /// @notice deposit(uint) to deposit amount to channel.
    /// @dev Deposit an amount to the channel. At least one of the participants
    /// must deposit before the channel is opened.
    /// @param caller_address (address) the address of the invoker of the function
    /// @param channel_address (address) the address of the channel
    /// @param amount (uint) the amount to be deposited to the address
    /// @return success (bool) if the transfer was successful
    /// @return balance (uint256) the new balance of the invoker
    function deposit(
        Data storage self,
        address caller_address,
        address channel_address,
        uint256 amount)
        returns (bool success, uint256 balance)
    {
        uint index;

        if (self.closed != 0) {
            throw;
        }

        if (self.token.balanceOf(caller_address) < amount) {
            throw;
        }

        Participant storage participant = self.participants[0];
        if (participant.node_address != caller_address) {
            participant = self.participants[1];
            if (participant.node_address != caller_address) {
                throw;
            }
        }

        success = self.token.transferFrom(
            caller_address,
            channel_address,
            amount
        );

        if (success == true) {
            balance = participant.balance;
            balance += amount;
            participant.balance = balance;

            if (self.opened == 0) {
                self.opened = block.number;
            }

            return (true, balance);
        }

        return (false, 0);
    }

    /// @notice partner() to get the partner or other participant of the channel
    /// @dev Get the other participating party of the channel
    /// @return (address) the partner of the calling party
    function partner(Data storage self, address one_address) constant returns (address) {
        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (one_address == node1.node_address) {
            return node2.node_address;
        }

        if (one_address == node2.node_address) {
            return node1.node_address;
        }

        return 0x0;
    }

    function addressAndBalance(Data storage self)
        constant
        returns(
        address participant1,
        uint balance1,
        address participant2,
        uint balance2)
    {
        Participant[2] participants = self.participants;
        Participant node1 = participants[0];
        Participant node2 = participants[1];

        // return by name
        participant1 = node1.node_address;
        balance1 = node1.balance;
        participant2 = node2.node_address;
        balance2 = node2.balance;
    }

    function closeSingleTransfer(Data storage self, address caller_address, bytes signed_transfer) {
        bytes memory transfer_raw;
        address transfer_address;

        if (self.settled > 0 || self.closed > 0) {
            throw;
        }

        if (signed_transfer.length <= 65) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (caller_address != node1.node_address && caller_address != node2.node_address) {
            throw;
        }

        (transfer_raw, transfer_address) = getTransferRawAddress(signed_transfer);

        if (node1.node_address == transfer_address) {
            Participant storage sender = node1;
        } else if (node2.node_address == transfer_address) {
            sender = node2;
        } else {
            throw;
        }

        decodeAndAssign(sender, transfer_raw);

        self.closing_address = caller_address;
        self.closed = block.number;
    }

    /// @notice close a channel between two parties without a raiden transfer
    ///         Cases where this may need to happen is:
    ///         - Alice deposits but Bob doesn't, then Alice must be able to
    ///           close the channel and reclaim her deposit.
    ///         - Neither Alice or Bob have made any deposits
    ///         - Generally any case where you want to simply close the channel
    ///           without adding an extra transfer to it
    /// @param caller_address The address of the participant trying to close
    function closeWithoutTransfer(Data storage self, address caller_address) {

        if (self.settled > 0 || self.closed > 0) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (caller_address != node1.node_address && caller_address != node2.node_address) {
            throw;
        }

        self.closing_address = caller_address;
        self.closed = block.number;
    }

    /// @notice close(bytes, bytes) to close a channel between two parties
    /// @dev Close the channel between two parties
    /// @param first_encoded (bytes) the last sent transfer of the msg.sender
    /// @param second_encoded (bytes) the last sent transfer of the msg.sender
    function close(
        Data storage self,
        address caller_address,
        bytes first_encoded,
        bytes second_encoded)
    {
        bytes memory first_raw;
        bytes memory second_raw;
        address first_address;
        address second_address;
        bytes32 transfer_sender;

        if (self.settled > 0 || self.closed > 0) {
            throw;
        }

        if (first_encoded.length <= 65 || second_encoded.length <= 65) {
            throw;
        }

        (first_raw, first_address) = getTransferRawAddress(first_encoded);
        (second_raw, second_address) = getTransferRawAddress(second_encoded);

        if (first_address == second_address) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (caller_address != node1.node_address && caller_address != node2.node_address) {
            throw;
        }

        if (node1.node_address == first_address) {
            Participant storage first_sender = node1;
        } else if (node2.node_address == first_address) {
            first_sender = node2;
        } else {
            throw;
        }

        if (node1.node_address == second_address) {
            Participant storage second_sender = node1;
        } else if (node2.node_address == second_address) {
            second_sender = node2;
        } else {
            throw;
        }

        decodeAndAssign(first_sender, first_raw);
        decodeAndAssign(second_sender, second_raw);

        self.closing_address = caller_address;
        self.closed = block.number;
    }

    /// @notice updateTransfer(bytes) to update last known transfer
    /// @dev Allow the partner to update the last known transfer
    function updateTransfer(Data storage self, address caller_address, bytes signed_transfer)
        notSettledButClosed(self)
        stillTimeout(self)
        notClosingAddress(self, caller_address)
    {
        uint64 nonce;
        bytes memory transfer_raw;
        address transfer_address;

        (transfer_raw, transfer_address) = getTransferRawAddress(signed_transfer);

        // transfer address must be from counter party
        if (self.closing_address != transfer_address) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (node1.node_address == transfer_address) {
            Participant storage sender = node1;
        } else if (node2.node_address == transfer_address) {
            sender = node2;
        } else {
            throw;
        }

        assembly {
            nonce := mload(add(transfer_raw, 12))  // skip cmdid and padding
        }

        if (nonce < sender.nonce || nonce == sender.nonce) {
            throw;
        }

        decodeAndAssign(sender, transfer_raw);

        // TODO check if tampered and penalize
        // TODO check if outdated and penalize
    }

    /// @notice unlock(bytes, bytes, bytes32) to unlock a locked transfer
    /// @dev Unlock a locked transfer
    /// @param locked_encoded (bytes) the lock
    /// @param merkle_proof (bytes) the merkle proof
    /// @param secret (bytes32) the secret
    function unlock(
        Data storage self,
        address caller_address,
        bytes locked_encoded,
        bytes merkle_proof,
        bytes32 secret)
        notSettledButClosed(self)
    {
        uint partner_id;
        uint64 expiration;
        uint amount;
        bytes32 hashlock;
        bytes32 h;
        bytes32 el;

        (expiration, amount, hashlock) = decodeLock(locked_encoded);

        if (self.locks[hashlock]) {
            throw;
        }

        if (expiration < block.number)
            throw;

        if (hashlock != sha3(secret))
            throw;

        Participant[2] storage participants = self.participants;
        Participant storage participant = participants[0];
        if (participant.node_address == caller_address) {
            participant = participants[1];
            if (participant.node_address != caller_address) {
                throw;
            }
        }

        if (participant.nonce == 0) {
            throw;
        }

        h = sha3(locked_encoded);
        for (uint i = 32; i <= merkle_proof.length; i += 32) {
            assembly {
                el := mload(add(merkle_proof, i))
            }

            if (h < el) {
                h = sha3(h, el);
            } else {
                h = sha3(el, h);
            }
        }

        if (participant.locksroot != h)
            throw;

        participant.unlocked.push(Lock(expiration, amount, hashlock));
        self.locks[hashlock] = true;
    }

    /// @notice settle() to settle the balance between the two parties
    /// @dev Settles the balances of the two parties fo the channel
    /// @return participants (Participant[2]) the participants with netted balances
    function settle(Data storage self, address caller_address)
        notSettledButClosed(self)
        timeoutOver(self)
    {
        uint total_netted;
        uint total_deposit;
        uint k;

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        node1.netted = node1.balance + node2.transferred_amount - node1.transferred_amount;
        node2.netted = node2.balance + node1.transferred_amount - node2.transferred_amount;

        for (k = 0; k < node1.unlocked.length; k++) {
            node1.netted += node1.unlocked[k].amount;
            node2.netted -= node1.unlocked[k].amount;
        }

        for (k = 0; k < node2.unlocked.length; k++) {
            node2.netted += node2.unlocked[k].amount;
            node1.netted -= node2.unlocked[k].amount;
        }

        self.settled = block.number;

        total_netted = node1.netted + node2.netted;
        total_deposit = node1.balance + node2.balance;

        if (total_netted != total_deposit) {
            throw;
        }

        if (!self.token.transfer(node1.node_address, node1.netted)) {
            throw;
        }
        if (!self.token.transfer(node2.node_address, node2.netted)) {
            throw;
        }
    }

    function getTransferRawAddress(bytes memory signed_transfer) private returns (bytes memory, address) {
        uint signature_start;
        uint length;
        bytes memory signature;
        bytes memory transfer_raw;
        bytes32 transfer_hash;
        address transfer_address;

        length = signed_transfer.length;
        signature_start = length - 65;
        signature = slice(signed_transfer, signature_start, length);
        transfer_raw = slice(signed_transfer, 0, signature_start);

        transfer_hash = sha3(transfer_raw);
        var (r, s, v) = signatureSplit(signature);
        transfer_address = ecrecover(transfer_hash, v, r, s);

        return (transfer_raw, transfer_address);
    }

    function decodeAndAssign(Participant storage sender, bytes transfer_raw) private {
        // all checks must be done by now
        uint cmdid;

        cmdid = uint(transfer_raw[0]);

        if (cmdid == 5) {
            assignDirectTransfer(sender, transfer_raw);
        } else if (cmdid == 7) {
            assignMediatedTransfer(sender, transfer_raw);
        } else if (cmdid == 8) {
            assignRefundTransfer(sender, transfer_raw);
        } else {
            throw;
        }
    }

    // NOTES about the length of variable types:
    // - variable length types start with a size-prefix of 32bytes (uint256)
    // - bytes is a variable length type
    // - a variable with a bytes type will contain the address of the first data element
    // - solidity starts indexing at 0 (so the 32th byte is at the offset 31)
    //  ref: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI

    // TODO: use sstore instead of these temporaries

    function assignDirectTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 156) {  // raw message size (without signature)
            throw;
        }

        uint64 nonce;
        address asset;
        address recipient;
        uint256 transferred_amount;
        bytes32 locksroot;
        bytes32 secret;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))              // nonce [4:12]
            // identifier [12:20]
            asset := mload(add(message, 40))              // asset [20:40]
            recipient := mload(add(message, 60))          // recipient [40:60]
            transferred_amount := mload(add(message, 92)) // transferred_amount [60:92]
            locksroot := mload(add(message, 124))         // optional_locksroot [92:124]
            secret := mload(add(message, 156))            // optional_secret [124:156]
        }

        participant.nonce = nonce;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.transferred_amount = transferred_amount;
        participant.locksroot = locksroot;
        participant.secret = secret;
    }

    function assignMediatedTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 268) {
            throw;
        }

        uint64 nonce;
        uint64 expiration;
        address asset;
        address recipient;
        bytes32 locksroot;
        bytes32 hashlock;
        uint256 transferred_amount;
        uint256 lock_amount;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))               // nonce [4:12]
            // identifier [12:20]
            expiration := mload(add(message, 28))          // expiration [20:28]
            asset := mload(add(message, 48))               // asset [28:48]
            recipient := mload(add(message, 68))           // recipient [48:68]
            // target [68:88]
            // initiator [88:108]
            locksroot := mload(add(message, 140))          // locksroot [108:140]
            hashlock := mload(add(message, 172))           // hashlock [140:172]
            transferred_amount := mload(add(message, 204)) // transferred_amount[172:204]
            lock_amount := mload(add(message, 236))        // amount [204:236]
            // fee := mload(add(message, 268))             // fee [236:268]
        }

        participant.nonce = nonce;
        participant.expiration = expiration;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.locksroot = locksroot;
        participant.hashlock = hashlock;
        participant.transferred_amount = transferred_amount;
        participant.amount = lock_amount;
    }

    function assignRefundTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 196) {
            throw;
        }

        uint64 nonce;
        uint64 expiration;
        address asset;
        address recipient;
        bytes32 locksroot;
        uint256 transferred_amount;
        uint256 lock_amount;
        bytes32 hashlock;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))                // nonce [4:12]
            // identifier [12:20]
            expiration := mload(add(message, 28))           // expiration [20:28]
            asset := mload(add(message, 48))                // asset [28:48]
            recipient := mload(add(message, 68))            // recipient [48:68]
            locksroot := mload(add(message, 100))           // locksroot [68:100]
            transferred_amount := mload(add(message, 132))  // transferred_amount [100:132]
            lock_amount := mload(add(message, 164))         // amount [132:164]
            hashlock := mload(add(message, 196))            // hashlock [164:196]
        }

        participant.nonce = nonce;
        participant.expiration = expiration;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.locksroot = locksroot;
        participant.transferred_amount = transferred_amount;
        participant.amount = lock_amount;
        participant.hashlock = hashlock;
    }

    function decodeLock(bytes lock) private returns (uint64 expiration, uint amount, bytes32 hashlock) {
        if (lock.length != 72) {
            throw;
        }

        assembly {
            expiration := mload(add(lock, 8))   // expiration [0:8]
            amount := mload(add(lock, 40))      // expiration [8:40]
            hashlock := mload(add(lock, 72))    // expiration [40:72]

        }
    }

    function signatureSplit(bytes signature) private returns (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
            // of 's'. There is no 'mload8' to do this.
            //
            // 'byte' is not working due to the Solidity parser, so lets
            // use the second best option, 'and'
            v := and(mload(add(signature, 65)), 1)
        }
        // old geth sends a `v` value of [0,1], while the new, in line with the YP sends [27,28]
        if(v < 27) v += 27;
    }

    function slice(bytes a, uint start, uint end) private returns (bytes n) {
        if (a.length < end) {
            throw;
        }
        if (start < 0) {
            throw;
        }

        n = new bytes(end-start);
        for (uint i = start; i < end; i ++) { //python style slice
            n[i-start] = a[i];
        }
    }
}


Fix typo (#3058)

Fix typo (#3058)

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/Proxy.sol)

pragma solidity ^0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overriden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/Proxy.sol)

pragma solidity ^0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overriden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}


Sample Crowdsale

Sample Crowdsale

pragma solidity ^0.4.11;

contract SafeMath {
    function safeAdd(uint256 x, uint256 y) internal returns(uint256) {
      uint256 z = x + y;
      assert((z >= x) && (z >= y));
      return z;
    }

    function safeSubtract(uint256 x, uint256 y) internal returns(uint256) {
      assert(x >= y);
      uint256 z = x - y;
      return z;
    }

    function safeMult(uint256 x, uint256 y) internal returns(uint256) {
      uint256 z = x * y;
      assert((x == 0)||(z/x == y));
      return z;
    }
}

contract AnemoiPresale is SafeMath{
    // Fund deposit address
    address public ethFundDeposit = "#placeholder#";
    address public owner;                                       // Owner of the pre sale contract
    mapping (address => uint256) public whiteList;

    // presale parameters
    bool public isFinalized;                                    // switched to true in operational state
    uint256 public constant maxLimit =  5000 ether;            // Maximum limit for taking in the money
    uint256 public constant minRequired = 10 ether;            // Minimum contribution per person
    uint256 public totalSupply;
    mapping (address => uint256) public balances;

    // events
    event Contribution(address indexed _to, uint256 _value);

    modifier onlyOwner() {
      require (msg.sender == owner);
      _;
    }

    // @dev constructor
    function Anemoi() {
      isFinalized = false;                                      //controls pre through crowdsale state
      owner = msg.sender;
      totalSupply = 0;
    }

    // @dev this function accepts Ether and increases the balances of the contributors
    function() payable {
      uint256 checkedSupply = safeAdd(totalSupply, msg.value);
      require (msg.value >= minRequired);                        // The contribution needs to be above 10 Ether
      require (!isFinalized);                                    // Cannot accept Ether after finalizing the contract
      require (checkedSupply <= maxLimit);
      require (whiteList[msg.sender] == 1);
      balances[msg.sender] = safeAdd(balances[msg.sender], msg.value);

      totalSupply = safeAdd(totalSupply, msg.value);
      Contribution(msg.sender, msg.value);
      ethFundDeposit.transfer(this.balance);                     // send the eth to Anemoi multi-sig
    }

    // @dev adds an Ethereum address to whitelist
    function setWhiteList(address _whitelisted) onlyOwner {
      whiteList[_whitelisted] = 1;
    }

    // @dev removed an Ethereum address from whitelist
    function removeWhiteList(address _whitelisted) onlyOwner {
      whiteList[_whitelisted] = 0;
    }

    /// @dev Ends the funding period and sends the ETH home
    function finalize() external onlyOwner {
      require (!isFinalized);
      // move to operational
      isFinalized = true;
      ethFundDeposit.transfer(this.balance);                     // send the eth to Anemoi multi-sig
    }
}

pragma solidity ^0.4.11;

contract SafeMath {
    function safeAdd(uint256 x, uint256 y) internal returns(uint256) {
      uint256 z = x + y;
      assert((z >= x) && (z >= y));
      return z;
    }

    function safeSubtract(uint256 x, uint256 y) internal returns(uint256) {
      assert(x >= y);
      uint256 z = x - y;
      return z;
    }

    function safeMult(uint256 x, uint256 y) internal returns(uint256) {
      uint256 z = x * y;
      assert((x == 0)||(z/x == y));
      return z;
    }
}

contract AnemoiPresale is SafeMath{
    // Fund deposit address
    address public ethFundDeposit = "#placeholder#";
    address public owner;                                       // Owner of the pre sale contract
    mapping (address => uint256) public whiteList;

    // presale parameters
    bool public isFinalized;                                    // switched to true in operational state
    uint256 public constant maxLimit =  5000 ether;            // Maximum limit for taking in the money
    uint256 public constant minRequired = 10 ether;            // Minimum contribution per person
    uint256 public totalSupply;
    mapping (address => uint256) public balances;

    // events
    event Contribution(address indexed _to, uint256 _value);

    modifier onlyOwner() {
      require (msg.sender == owner);
      _;
    }

    // @dev constructor
    function IndorsePreSale() {
      isFinalized = false;                                      //controls pre through crowdsale state
      owner = msg.sender;
      totalSupply = 0;
    }

    // @dev this function accepts Ether and increases the balances of the contributors
    function() payable {
      uint256 checkedSupply = safeAdd(totalSupply, msg.value);
      require (msg.value >= minRequired);                        // The contribution needs to be above 10 Ether
      require (!isFinalized);                                    // Cannot accept Ether after finalizing the contract
      require (checkedSupply <= maxLimit);
      require (whiteList[msg.sender] == 1);
      balances[msg.sender] = safeAdd(balances[msg.sender], msg.value);

      totalSupply = safeAdd(totalSupply, msg.value);
      Contribution(msg.sender, msg.value);
      ethFundDeposit.transfer(this.balance);                     // send the eth to Anemoi multi-sig
    }

    // @dev adds an Ethereum address to whitelist
    function setWhiteList(address _whitelisted) onlyOwner {
      whiteList[_whitelisted] = 1;
    }

    // @dev removed an Ethereum address from whitelist
    function removeWhiteList(address _whitelisted) onlyOwner {
      whiteList[_whitelisted] = 0;
    }

    /// @dev Ends the funding period and sends the ETH home
    function finalize() external onlyOwner {
      require (!isFinalized);
      // move to operational
      isFinalized = true;
      ethFundDeposit.transfer(this.balance);                     // send the eth to Anemoi multi-sig
    }
}


added third example

added third example

pragma solidity ^0.4.10;

//the very third example
contract Example3 {

}

error: pathspec 'example3.sol' did not match any file(s) known to git


catalogo: incluir exemplo com map

catalogo: incluir exemplo com map

pragma solidity ^0.4.4;

// Proof of Existence contract, version 3
contract ProofOfExistence3 {

    mapping (bytes32 => bool) private proofs;

    // store a proof of existence in the contract state
    function storeProof(bytes32 proof) {
        proofs[proof] = true;
    }

    // calculate and store the proof for a document
    function notarize(string document) {
        var proof = calculateProof(document);
        storeProof(proof);
    }

    // helper function to get a document's sha256
    function calculateProof(string document) constant returns (bytes32) {
        return sha256(document);
    }

    // check if a document has been notarized
    function checkDocument(string document) constant returns (bool) {
        var proof = calculateProof(document);
        return hasProof(proof);
    }

    // returns true if proof is stored
    function hasProof(bytes32 proof) constant returns (bool) {
        return proofs[proof];
    }

}

error: pathspec 'catalogo-project/contracts/ProofOfExistence3.sol' did not match any file(s) known to git


make setters in GovernorSettings virtual

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.3.2 (governance/extensions/GovernorSettings.sol)

pragma solidity ^0.8.0;

import "../Governor.sol";

/**
 * @dev Extension of {Governor} for settings updatable through governance.
 *
 * _Available since v4.4._
 */
abstract contract GovernorSettings is Governor {
    uint256 private _votingDelay;
    uint256 private _votingPeriod;
    uint256 private _proposalThreshold;

    event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);
    event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);
    event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold);

    /**
     * @dev Initialize the governance parameters.
     */
    constructor(
        uint256 initialVotingDelay,
        uint256 initialVotingPeriod,
        uint256 initialProposalThreshold
    ) {
        _setVotingDelay(initialVotingDelay);
        _setVotingPeriod(initialVotingPeriod);
        _setProposalThreshold(initialProposalThreshold);
    }

    /**
     * @dev See {IGovernor-votingDelay}.
     */
    function votingDelay() public view virtual override returns (uint256) {
        return _votingDelay;
    }

    /**
     * @dev See {IGovernor-votingPeriod}.
     */
    function votingPeriod() public view virtual override returns (uint256) {
        return _votingPeriod;
    }

    /**
     * @dev See {Governor-proposalThreshold}.
     */
    function proposalThreshold() public view virtual override returns (uint256) {
        return _proposalThreshold;
    }

    /**
     * @dev Update the voting delay. This operation can only be performed through a governance proposal.
     *
     * Emits a {VotingDelaySet} event.
     */
    function setVotingDelay(uint256 newVotingDelay) public virtual onlyGovernance {
        _setVotingDelay(newVotingDelay);
    }

    /**
     * @dev Update the voting period. This operation can only be performed through a governance proposal.
     *
     * Emits a {VotingPeriodSet} event.
     */
    function setVotingPeriod(uint256 newVotingPeriod) public virtual onlyGovernance {
        _setVotingPeriod(newVotingPeriod);
    }

    /**
     * @dev Update the proposal threshold. This operation can only be performed through a governance proposal.
     *
     * Emits a {ProposalThresholdSet} event.
     */
    function setProposalThreshold(uint256 newProposalThreshold) public virtual onlyGovernance {
        _setProposalThreshold(newProposalThreshold);
    }

    /**
     * @dev Internal setter for the voting delay.
     *
     * Emits a {VotingDelaySet} event.
     */
    function _setVotingDelay(uint256 newVotingDelay) internal virtual {
        emit VotingDelaySet(_votingDelay, newVotingDelay);
        _votingDelay = newVotingDelay;
    }

    /**
     * @dev Internal setter for the voting period.
     *
     * Emits a {VotingPeriodSet} event.
     */
    function _setVotingPeriod(uint256 newVotingPeriod) internal virtual {
        // voting period must be at least one block long
        require(newVotingPeriod > 0, "GovernorSettings: voting period too low");
        emit VotingPeriodSet(_votingPeriod, newVotingPeriod);
        _votingPeriod = newVotingPeriod;
    }

    /**
     * @dev Internal setter for the proposal threshold.
     *
     * Emits a {ProposalThresholdSet} event.
     */
    function _setProposalThreshold(uint256 newProposalThreshold) internal virtual {
        emit ProposalThresholdSet(_proposalThreshold, newProposalThreshold);
        _proposalThreshold = newProposalThreshold;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.3.2 (governance/extensions/GovernorSettings.sol)

pragma solidity ^0.8.0;

import "../Governor.sol";

/**
 * @dev Extension of {Governor} for settings updatable through governance.
 *
 * _Available since v4.4._
 */
abstract contract GovernorSettings is Governor {
    uint256 private _votingDelay;
    uint256 private _votingPeriod;
    uint256 private _proposalThreshold;

    event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);
    event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);
    event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold);

    /**
     * @dev Initialize the governance parameters.
     */
    constructor(
        uint256 initialVotingDelay,
        uint256 initialVotingPeriod,
        uint256 initialProposalThreshold
    ) {
        _setVotingDelay(initialVotingDelay);
        _setVotingPeriod(initialVotingPeriod);
        _setProposalThreshold(initialProposalThreshold);
    }

    /**
     * @dev See {IGovernor-votingDelay}.
     */
    function votingDelay() public view virtual override returns (uint256) {
        return _votingDelay;
    }

    /**
     * @dev See {IGovernor-votingPeriod}.
     */
    function votingPeriod() public view virtual override returns (uint256) {
        return _votingPeriod;
    }

    /**
     * @dev See {Governor-proposalThreshold}.
     */
    function proposalThreshold() public view virtual override returns (uint256) {
        return _proposalThreshold;
    }

    /**
     * @dev Update the voting delay. This operation can only be performed through a governance proposal.
     *
     * Emits a {VotingDelaySet} event.
     */
    function setVotingDelay(uint256 newVotingDelay) public onlyGovernance {
        _setVotingDelay(newVotingDelay);
    }

    /**
     * @dev Update the voting period. This operation can only be performed through a governance proposal.
     *
     * Emits a {VotingPeriodSet} event.
     */
    function setVotingPeriod(uint256 newVotingPeriod) public onlyGovernance {
        _setVotingPeriod(newVotingPeriod);
    }

    /**
     * @dev Update the proposal threshold. This operation can only be performed through a governance proposal.
     *
     * Emits a {ProposalThresholdSet} event.
     */
    function setProposalThreshold(uint256 newProposalThreshold) public onlyGovernance {
        _setProposalThreshold(newProposalThreshold);
    }

    /**
     * @dev Internal setter for the voting delay.
     *
     * Emits a {VotingDelaySet} event.
     */
    function _setVotingDelay(uint256 newVotingDelay) internal virtual {
        emit VotingDelaySet(_votingDelay, newVotingDelay);
        _votingDelay = newVotingDelay;
    }

    /**
     * @dev Internal setter for the voting period.
     *
     * Emits a {VotingPeriodSet} event.
     */
    function _setVotingPeriod(uint256 newVotingPeriod) internal virtual {
        // voting period must be at least one block long
        require(newVotingPeriod > 0, "GovernorSettings: voting period too low");
        emit VotingPeriodSet(_votingPeriod, newVotingPeriod);
        _votingPeriod = newVotingPeriod;
    }

    /**
     * @dev Internal setter for the proposal threshold.
     *
     * Emits a {ProposalThresholdSet} event.
     */
    function _setProposalThreshold(uint256 newProposalThreshold) internal virtual {
        emit ProposalThresholdSet(_proposalThreshold, newProposalThreshold);
        _proposalThreshold = newProposalThreshold;
    }
}


Require explicit signing of T&Cs

Require explicit signing of T&Cs

pragma solidity ^0.4.11;

import './token.sol';

/// @title Dutch auction contract - distribution of tokens using an auction.
/// @author [..] credits to Stefan George - <stefan.george@consensys.net>
contract DutchAuction {
    /*
    Auction for the TKN Token.
    Usage of the contract implies agreement of the Terms & Conditions
        Link: http://xyz.eth/tc.pdf
        MD5: e18de70182a134687249aebe6656049c

    Only addresses which signed the contract are allowed to call `bid`
    Users needs to called below, to explicitly sign agreement with the terms:
    `DutchAuction.sign('e18de70182a134687249aebe6656049c')`
    */

    /*
     *  Storage
     */

    // Keep track of signing the Terms and Conditions
    mapping (address => bool) public terms_signed;
    bytes32 terms_hash = 'e18de70182a134687249aebe6656049c';

    ReserveToken public token;
    address public owner;

    // Price function parameters
    uint public price_factor;
    uint public price_const;

    // For calculating elapsed time for price
    uint public start_time;
    uint public end_time;
    uint public start_block;

    // Keep track of funds claimed after auction has ended
    uint public funds_claimed;

    // Total number of tokens that will be auctioned
    uint public tokens_auctioned;

    // Wei per TKN (Tei * multiplier)
    uint public final_price;

    mapping (address => uint) public bids;

    Stages public stage;

    // Terminology:
    // 1 token unit = Tei
    // 1 token = TKN = Tei * multiplier
    // multiplier set from token's number of decimals (i.e. 10**decimals)
    uint multiplier;

    // TODO - remove after testing
    uint rounding_error_tokens;

    /*
     *  Enums
     */
    enum Stages {
        AuctionDeployed,
        AuctionSetUp,
        AuctionStarted,
        AuctionEnded,
        TokensDistributed,
        TradingStarted
    }

    /*
     *  Modifiers
     */
    modifier atStage(Stages _stage) {
        require(stage == _stage);
        _;
    }

    modifier isOwner() {
        require(msg.sender == owner);
        _;
    }

    modifier signedTerms() {
        require(terms_signed[msg.sender]);
        _;
    }

    modifier isValidPayload() {
        require(msg.data.length == 4 || msg.data.length == 36);
        _;
    }

    /*
     *  Events
     */

    event Deployed(address indexed auction, uint indexed price_factor, uint indexed price_const);
    event Setup();
    event SettingsChanged(uint indexed price_factor, uint indexed price_const);
    event AuctionStarted(uint indexed start_time, uint indexed block_number);
    event TermsSigned(address indexed sender, bytes32 indexed _terms_hash);
    event BidSubmission(address indexed sender, uint amount, uint returned_amount, uint indexed missing_reserve);
    event ClaimedTokens(address indexed recipient, uint sent_amount, uint num);
    event AuctionEnded(uint indexed final_price);
    event TokensDistributed();
    event TradingStarted();

    /*
     *  Public functions
     */

    /// @dev Contract constructor function sets owner.
    /// @param _price_factor Auction price factor.
    /// @param _price_const Auction price divisor constant.
    function DutchAuction(
        uint _price_factor,
        uint _price_const)
        public
    {
        owner = msg.sender;
        stage = Stages.AuctionDeployed;
        Deployed(this, price_factor, price_const);
        changeSettings(_price_factor, _price_const);
    }

    /// @dev Setup function sets external contracts' addresses.
    /// @param _token Token address.
    function setup(address _token)
        public
        isOwner
        atStage(Stages.AuctionDeployed)
    {
        require(_token != 0x0);
        token = ReserveToken(_token);
        require(token.owner() == owner);

        // Get number of tokens to be auctioned from token auction balance
        tokens_auctioned = token.balanceOf(this);

        // Set number of tokens multiplier from token decimals
        multiplier = 10**uint(token.decimals());

        stage = Stages.AuctionSetUp;
        Setup();

        // Tei auctioned
        assert(tokens_auctioned > multiplier);
    }

    /// @dev Changes auction start price factor before auction is started.
    /// @param _price_factor Updated price factor.
    /// @param _price_const Updated price divisor constant.
    function changeSettings(
        uint _price_factor,
        uint _price_const)
        public
        isOwner
    {
        require(stage == Stages.AuctionDeployed || stage == Stages.AuctionSetUp);
        require(_price_factor > 0);
        require(_price_const > 0);

        price_factor = _price_factor;
        price_const = _price_const;
        SettingsChanged(price_factor, price_const);
    }

    /// @dev Starts auction and sets start_time.
    function startAuction()
        public
        isOwner
        atStage(Stages.AuctionSetUp)
    {
        stage = Stages.AuctionStarted;
        start_time = now;
        start_block = block.number;
        AuctionStarted(start_time, start_block);
    }

    /// --------------------------------- Auction Functions -------------------------------------------

    /// @dev Allows to sing the terms.
    function sign(bytes32 _terms_hash)
        public
        atStage(Stages.AuctionStarted)
    {
        require(_terms_hash == terms_hash); // check if the correct terms are signed
        terms_signed[msg.sender]; // register digital signature
        TermsSigned(msg.sender, _terms_hash);
    }

    /// @dev Allows to send a bid to the auction.
    function bid()
        public
        payable
        atStage(Stages.AuctionStarted)
    {
        bid(msg.sender);
    }

    /// @dev Allows to send a bid to the auction.
    /// @param receiver Bidder account address.
    function bid(address receiver)
        public
        payable
        isValidPayload
        signedTerms
        atStage(Stages.AuctionStarted)
    {
        require(receiver != 0x0);
        require(msg.value > 0);

        uint amount = msg.value;
        uint pre_receiver_funds = bids[receiver];

        // Missing reserve without the current bid amount
        uint maxWei = missingReserveToEndAuction(this.balance - amount);

        // Only invest maximum possible amount.
        if (amount > maxWei) {
            amount = maxWei;
            // Send change back to receiver address.
            // TODO add test for this
            receiver.transfer(msg.value - amount);
        }
        bids[receiver] += amount;
        BidSubmission(receiver, amount, msg.value - amount, maxWei);

        if (maxWei == amount) {
            // When maxWei is equal to the big amount the auction is ended and finalizeAuction is triggered.
            finalizeAuction();
        }

        assert(bids[receiver] == pre_receiver_funds + amount);
    }

    /// @dev Claims tokens for bidder after auction. To be used if tokens can be claimed by bidders, individually.
    function claimTokens()
        public
        atStage(Stages.AuctionEnded)
    {
        claimTokens(msg.sender);
    }

    /// @dev Claims tokens for bidder after auction.
    /// @param receiver Tokens will be assigned to this address if set.
    function claimTokens(address receiver)
        public
        isValidPayload
        atStage(Stages.AuctionEnded)
    {
        require(receiver != 0x0);
        require(bids[receiver] > 0);

        // Number of Tei = bidded_wei / wei_per_TKN * multiplier
        uint num = multiplier * bids[receiver] / final_price;

        // Update funds claimed with full bidded amount
        // rounding errors are included to not block the contract
        funds_claimed += bids[receiver];

        // Set receiver bid to 0 before assigning tokens
        bids[receiver] = 0;

        token.transfer(receiver, num);
        ClaimedTokens(receiver, num, token.balanceOf(receiver));

        // Test for a correct claimed tokens calculation
        /* TODO remove this after testing */
        uint auction_unclaimed_tokens = token.balanceOf(this);

        uint unclaimed_tokens = (this.balance - funds_claimed) * multiplier / final_price;
        unclaimed_tokens += rounding_error_tokens;

        if(auction_unclaimed_tokens != unclaimed_tokens) {
            rounding_error_tokens += 1;
            unclaimed_tokens += 1;
        }
        assert(auction_unclaimed_tokens == unclaimed_tokens);
        /* End of removable test */

        if (funds_claimed == this.balance) {
            stage = Stages.TokensDistributed;
            TokensDistributed();
            transferReserveToToken();
        }

        assert(num == token.balanceOf(receiver));
        assert(bids[receiver] == 0);
    }

    /*
     *  Private functions
     */

    /// @dev Finalize auction and set the final token price.
    function finalizeAuction()
        private
        atStage(Stages.AuctionStarted)
    {
        final_price = calcTokenPrice();
        end_time = now;
        stage = Stages.AuctionEnded;
        AuctionEnded(final_price);

        assert(final_price > 0);
    }

    /// @dev Transfer auction balance to the token.
    function transferReserveToToken()
        private
        atStage(Stages.TokensDistributed)
    {
        uint pre_balance = this.balance;

        token.receiveReserve.value(this.balance)();
        stage = Stages.TradingStarted;
        TradingStarted();

        assert(this.balance == 0);
        assert(token.balance == pre_balance);
    }

    /// @dev Calculates the token price at the current timestamp during the auction; elapsed time = 0 before auction starts.
    /// @dev At AuctionDeployed the price is 1, because multiplier is 0
    /// @return Returns the token price - Wei per TKN.
    function calcTokenPrice()
        constant
        private
        returns (uint)
    {
        uint elapsed;
        if(stage == Stages.AuctionStarted) {
            elapsed = now - start_time;
        }
        return multiplier * price_factor / (elapsed + price_const) + 1;
    }

    /// --------------------------------- Price Functions -------------------------------------------

    /// @dev Calculates current token price.
    /// @return Returns num Wei per TKN (multiplier * Tei).
    function price()
        public
        constant
        returns (uint)
    {
        if (stage == Stages.AuctionEnded ||
            stage == Stages.TokensDistributed ||
            stage == Stages.TradingStarted)
        {
            return 0;
        }
        return calcTokenPrice();
    }

    /// @dev The missing reserve amount necessary to end the auction at the current price.
    /// @return Returns the missing reserve amount.
    function missingReserveToEndAuction()
        constant
        public
        returns (uint)
    {
        return missingReserveToEndAuction(this.balance);
    }

    /// @dev The missing reserve amount necessary to end the auction at the current price, for a provided reserve/balance.
    /// @param reserve Reserve amount - might be current balance or current balance without current bid value for bid().
    /// @return Returns the missing reserve amount.
    function missingReserveToEndAuction(uint reserve)
        constant
        public
        returns (uint)
    {
        uint reserve_at_price = tokens_auctioned * price() / multiplier;
        if(reserve_at_price < reserve) {
            return 0;
        }
        return reserve_at_price - reserve;
    }
}

pragma solidity ^0.4.11;

import './token.sol';

/// @title Dutch auction contract - distribution of tokens using an auction.
/// @author [..] credits to Stefan George - <stefan.george@consensys.net>
contract DutchAuction {
    /*
     *  Storage
     */
    ReserveToken public token;
    address public owner;

    // Price function parameters
    uint public price_factor;
    uint public price_const;

    // For calculating elapsed time for price
    uint public start_time;
    uint public end_time;
    uint public start_block;

    // Keep track of funds claimed after auction has ended
    uint public funds_claimed;

    // Total number of tokens that will be auctioned
    uint public tokens_auctioned;

    // Wei per TKN (Tei * multiplier)
    uint public final_price;

    mapping (address => uint) public bids;
    Stages public stage;

    // Terminology:
    // 1 token unit = Tei
    // 1 token = TKN = Tei * multiplier
    // multiplier set from token's number of decimals (i.e. 10**decimals)
    uint multiplier;

    // TODO - remove after testing
    uint rounding_error_tokens;

    /*
     *  Enums
     */
    enum Stages {
        AuctionDeployed,
        AuctionSetUp,
        AuctionStarted,
        AuctionEnded,
        TokensDistributed,
        TradingStarted
    }

    /*
     *  Modifiers
     */
    modifier atStage(Stages _stage) {
        require(stage == _stage);
        _;
    }

    modifier isOwner() {
        require(msg.sender == owner);
        _;
    }

    modifier isValidPayload() {
        require(msg.data.length == 4 || msg.data.length == 36);
        _;
    }

    /*
     *  Events
     */

    event Deployed(address indexed auction, uint indexed price_factor, uint indexed price_const);
    event Setup();
    event SettingsChanged(uint indexed price_factor, uint indexed price_const);
    event AuctionStarted(uint indexed start_time, uint indexed block_number);
    event BidSubmission(address indexed sender, uint amount, uint returned_amount, uint indexed missing_reserve);
    event ClaimedTokens(address indexed recipient, uint sent_amount, uint num);
    event AuctionEnded(uint indexed final_price);
    event TokensDistributed();
    event TradingStarted();

    /*
     *  Public functions
     */

    /// @dev Contract constructor function sets owner.
    /// @param _price_factor Auction price factor.
    /// @param _price_const Auction price divisor constant.
    function DutchAuction(
        uint _price_factor,
        uint _price_const)
        public
    {
        owner = msg.sender;
        stage = Stages.AuctionDeployed;
        Deployed(this, price_factor, price_const);
        changeSettings(_price_factor, _price_const);
    }

    /// @dev Setup function sets external contracts' addresses.
    /// @param _token Token address.
    function setup(address _token)
        public
        isOwner
        atStage(Stages.AuctionDeployed)
    {
        require(_token != 0x0);
        token = ReserveToken(_token);
        require(token.owner() == owner);

        // Get number of tokens to be auctioned from token auction balance
        tokens_auctioned = token.balanceOf(this);

        // Set number of tokens multiplier from token decimals
        multiplier = 10**uint(token.decimals());

        stage = Stages.AuctionSetUp;
        Setup();

        // Tei auctioned
        assert(tokens_auctioned > multiplier);
    }

    /// @dev Changes auction start price factor before auction is started.
    /// @param _price_factor Updated price factor.
    /// @param _price_const Updated price divisor constant.
    function changeSettings(
        uint _price_factor,
        uint _price_const)
        public
        isOwner
    {
        require(stage == Stages.AuctionDeployed || stage == Stages.AuctionSetUp);
        require(_price_factor > 0);
        require(_price_const > 0);

        price_factor = _price_factor;
        price_const = _price_const;
        SettingsChanged(price_factor, price_const);
    }

    /// @dev Starts auction and sets start_time.
    function startAuction()
        public
        isOwner
        atStage(Stages.AuctionSetUp)
    {
        stage = Stages.AuctionStarted;
        start_time = now;
        start_block = block.number;
        AuctionStarted(start_time, start_block);
    }

    /// --------------------------------- Auction Functions -------------------------------------------

    /// @dev Allows to send a bid to the auction.
    function bid()
        public
        payable
        atStage(Stages.AuctionStarted)
    {
        bid(msg.sender);
    }

    /// @dev Allows to send a bid to the auction.
    /// @param receiver Bidder account address.
    function bid(address receiver)
        public
        payable
        isValidPayload
        atStage(Stages.AuctionStarted)
    {
        require(receiver != 0x0);
        require(msg.value > 0);

        uint amount = msg.value;
        uint pre_receiver_funds = bids[receiver];

        // Missing reserve without the current bid amount
        uint maxWei = missingReserveToEndAuction(this.balance - amount);

        // Only invest maximum possible amount.
        if (amount > maxWei) {
            amount = maxWei;
            // Send change back to receiver address.
            // TODO add test for this
            receiver.transfer(msg.value - amount);
        }
        bids[receiver] += amount;
        BidSubmission(receiver, amount, msg.value - amount, maxWei);

        if (maxWei == amount) {
            // When maxWei is equal to the big amount the auction is ended and finalizeAuction is triggered.
            finalizeAuction();
        }

        assert(bids[receiver] == pre_receiver_funds + amount);
    }

    /// @dev Claims tokens for bidder after auction. To be used if tokens can be claimed by bidders, individually.
    function claimTokens()
        public
        atStage(Stages.AuctionEnded)
    {
        claimTokens(msg.sender);
    }

    /// @dev Claims tokens for bidder after auction.
    /// @param receiver Tokens will be assigned to this address if set.
    function claimTokens(address receiver)
        public
        isValidPayload
        atStage(Stages.AuctionEnded)
    {
        require(receiver != 0x0);
        require(bids[receiver] > 0);

        // Number of Tei = bidded_wei / wei_per_TKN * multiplier
        uint num = multiplier * bids[receiver] / final_price;

        // Update funds claimed with full bidded amount
        // rounding errors are included to not block the contract
        funds_claimed += bids[receiver];

        // Set receiver bid to 0 before assigning tokens
        bids[receiver] = 0;

        token.transfer(receiver, num);
        ClaimedTokens(receiver, num, token.balanceOf(receiver));

        // Test for a correct claimed tokens calculation
        /* TODO remove this after testing */
        uint auction_unclaimed_tokens = token.balanceOf(this);

        uint unclaimed_tokens = (this.balance - funds_claimed) * multiplier / final_price;
        unclaimed_tokens += rounding_error_tokens;

        if(auction_unclaimed_tokens != unclaimed_tokens) {
            rounding_error_tokens += 1;
            unclaimed_tokens += 1;
        }
        assert(auction_unclaimed_tokens == unclaimed_tokens);
        /* End of removable test */

        if (funds_claimed == this.balance) {
            stage = Stages.TokensDistributed;
            TokensDistributed();
            transferReserveToToken();
        }

        assert(num == token.balanceOf(receiver));
        assert(bids[receiver] == 0);
    }

    /*
     *  Private functions
     */

    /// @dev Finalize auction and set the final token price.
    function finalizeAuction()
        private
        atStage(Stages.AuctionStarted)
    {
        final_price = calcTokenPrice();
        end_time = now;
        stage = Stages.AuctionEnded;
        AuctionEnded(final_price);

        assert(final_price > 0);
    }

    /// @dev Transfer auction balance to the token.
    function transferReserveToToken()
        private
        atStage(Stages.TokensDistributed)
    {
        uint pre_balance = this.balance;

        token.receiveReserve.value(this.balance)();
        stage = Stages.TradingStarted;
        TradingStarted();

        assert(this.balance == 0);
        assert(token.balance == pre_balance);
    }

    /// @dev Calculates the token price at the current timestamp during the auction; elapsed time = 0 before auction starts.
    /// @dev At AuctionDeployed the price is 1, because multiplier is 0
    /// @return Returns the token price - Wei per TKN.
    function calcTokenPrice()
        constant
        private
        returns (uint)
    {
        uint elapsed;
        if(stage == Stages.AuctionStarted) {
            elapsed = now - start_time;
        }
        return multiplier * price_factor / (elapsed + price_const) + 1;
    }

    /// --------------------------------- Price Functions -------------------------------------------

    /// @dev Calculates current token price.
    /// @return Returns num Wei per TKN (multiplier * Tei).
    function price()
        public
        constant
        returns (uint)
    {
        if (stage == Stages.AuctionEnded ||
            stage == Stages.TokensDistributed ||
            stage == Stages.TradingStarted)
        {
            return 0;
        }
        return calcTokenPrice();
    }

    /// @dev The missing reserve amount necessary to end the auction at the current price.
    /// @return Returns the missing reserve amount.
    function missingReserveToEndAuction()
        constant
        public
        returns (uint)
    {
        return missingReserveToEndAuction(this.balance);
    }

    /// @dev The missing reserve amount necessary to end the auction at the current price, for a provided reserve/balance.
    /// @param reserve Reserve amount - might be current balance or current balance without current bid value for bid().
    /// @return Returns the missing reserve amount.
    function missingReserveToEndAuction(uint reserve)
        constant
        public
        returns (uint)
    {
        uint reserve_at_price = tokens_auctioned * price() / multiplier;
        if(reserve_at_price < reserve) {
            return 0;
        }
        return reserve_at_price - reserve;
    }
}


Remove transcodedDataHash from oraclize_query params because not longer needed

pragma solidity ^0.4.11;

import "./Verifier.sol";
import "./Verifiable.sol";

import "../../installed_contracts/oraclize/contracts/usingOraclize.sol";

/*
 * @title Verifier contract that uses Oraclize for off-chain computation
 */
contract OraclizeVerifier is Verifier, usingOraclize {

    // Stores parameters for an Oraclize query
    struct OraclizeQuery {
        uint256 jobId;
        uint256 segmentSequenceNumber;
        string transcodedDataHash;
        address callbackContract;
    }

    // Stores active Oraclize queries
    mapping (bytes32 => OraclizeQuery) oraclizeQueries;

    // Check if sender is Oraclize
    modifier onlyOraclize() {
        if (msg.sender != oraclize_cbAddress()) throw;
        _;
    }

    // Check if sufficient funds for Oraclize computation
    modifier sufficientOraclizeFunds() {
        if (oraclize_getPrice("computation") > msg.value) throw;
        _;
    }

    function OraclizeVerifier() {
        // OAR used for testing purposes
        OAR = OraclizeAddrResolverI(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475);
        // Set Oraclize proof
        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
    }

    event OraclizeCallback(uint256 indexed jobId, uint256 indexed segmentSequenceNumber, bytes proof, bool result);

    /*
     * @dev Verify implementation that creates an Oraclize computation query
     * @param _jobId Job identifier
     * @param _segmentSequenceNumber Segment being verified for job
     * @param _code Content-addressed storage hash of binary to execute off-chain
     * @param _dataHash Content-addressed storage hash of input data of segment
     * @param _transcodedDataHash Content-addressed storage hash of transcoded input data of segment
     * @param _callbackContract Address of Verifiable contract to call back
     */
    function verify(uint256 _jobId, uint256 _segmentSequenceNumber, string _code, string _dataHash, string _transcodedDataHash, address _callbackContract) payable sufficientOraclizeFunds external returns (bool) {
        // Create Oraclize query
        bytes32 queryId = oraclize_query("computation", [_code, _dataHash], 3000000);

        // Store Oraclize query parameters
        oraclizeQueries[queryId].jobId = _jobId;
        oraclizeQueries[queryId].segmentSequenceNumber = _segmentSequenceNumber;
        oraclizeQueries[queryId].transcodedDataHash = _transcodedDataHash;
        oraclizeQueries[queryId].callbackContract = _callbackContract;

        return true;
    }

    /*
     * @dev Callback function invoked by Oraclize to return result of off-chain computation
     * @param _queryId Oraclize query identifier
     * @param _result Result of Oraclize computation
     */
    function __callback(bytes32 _queryId, string _result, bytes _proof) onlyOraclize {
        OraclizeQuery memory oc = oraclizeQueries[_queryId];

        // Check if transcoded data hash returned by Oraclize matches originally submitted transcoded data hash
        if (strCompare(oc.transcodedDataHash, _result) == 0) {
            // Notify callback contract of successful verification
            if (!Verifiable(oc.callbackContract).receiveVerification(oc.jobId, oc.segmentSequenceNumber, true)) throw;
            OraclizeCallback(oc.jobId, oc.segmentSequenceNumber, _proof, true);
        } else {
            // Notify callback contract of failed verification
            if (!Verifiable(oc.callbackContract).receiveVerification(oc.jobId, oc.segmentSequenceNumber, false)) throw;
            OraclizeCallback(oc.jobId, oc.segmentSequenceNumber, _proof, false);
        }

        // Remove Oraclize query
        delete oraclizeQueries[_queryId];
    }
}

pragma solidity ^0.4.11;

import "./Verifier.sol";
import "./Verifiable.sol";

import "../../installed_contracts/oraclize/contracts/usingOraclize.sol";

/*
 * @title Verifier contract that uses Oraclize for off-chain computation
 */
contract OraclizeVerifier is Verifier, usingOraclize {

    // Stores parameters for an Oraclize query
    struct OraclizeQuery {
        uint256 jobId;
        uint256 segmentSequenceNumber;
        string transcodedDataHash;
        address callbackContract;
    }

    // Stores active Oraclize queries
    mapping (bytes32 => OraclizeQuery) oraclizeQueries;

    // Check if sender is Oraclize
    modifier onlyOraclize() {
        if (msg.sender != oraclize_cbAddress()) throw;
        _;
    }

    // Check if sufficient funds for Oraclize computation
    modifier sufficientOraclizeFunds() {
        if (oraclize_getPrice("computation") > msg.value) throw;
        _;
    }

    function OraclizeVerifier() {
        // OAR used for testing purposes
        OAR = OraclizeAddrResolverI(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475);
        // Set Oraclize proof
        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
    }

    event OraclizeCallback(uint256 indexed jobId, uint256 indexed segmentSequenceNumber, bytes proof, bool result);

    /*
     * @dev Verify implementation that creates an Oraclize computation query
     * @param _jobId Job identifier
     * @param _segmentSequenceNumber Segment being verified for job
     * @param _code Content-addressed storage hash of binary to execute off-chain
     * @param _dataHash Content-addressed storage hash of input data of segment
     * @param _transcodedDataHash Content-addressed storage hash of transcoded input data of segment
     * @param _callbackContract Address of Verifiable contract to call back
     */
    function verify(uint256 _jobId, uint256 _segmentSequenceNumber, string _code, string _dataHash, string _transcodedDataHash, address _callbackContract) payable sufficientOraclizeFunds external returns (bool) {
        // Create Oraclize query
        bytes32 queryId = oraclize_query("computation", [_code, _dataHash, _transcodedDataHash], 3000000);

        // Store Oraclize query parameters
        oraclizeQueries[queryId].jobId = _jobId;
        oraclizeQueries[queryId].segmentSequenceNumber = _segmentSequenceNumber;
        oraclizeQueries[queryId].transcodedDataHash = _transcodedDataHash;
        oraclizeQueries[queryId].callbackContract = _callbackContract;

        return true;
    }

    /*
     * @dev Callback function invoked by Oraclize to return result of off-chain computation
     * @param _queryId Oraclize query identifier
     * @param _result Result of Oraclize computation
     */
    function __callback(bytes32 _queryId, string _result, bytes _proof) onlyOraclize {
        OraclizeQuery memory oc = oraclizeQueries[_queryId];

        // Check if transcoded data hash returned by Oraclize matches originally submitted transcoded data hash
        if (strCompare(oc.transcodedDataHash, _result) == 0) {
            // Notify callback contract of successful verification
            if (!Verifiable(oc.callbackContract).receiveVerification(oc.jobId, oc.segmentSequenceNumber, true)) throw;
            OraclizeCallback(oc.jobId, oc.segmentSequenceNumber, _proof, true);
        } else {
            // Notify callback contract of failed verification
            if (!Verifiable(oc.callbackContract).receiveVerification(oc.jobId, oc.segmentSequenceNumber, false)) throw;
            OraclizeCallback(oc.jobId, oc.segmentSequenceNumber, _proof, false);
        }

        // Remove Oraclize query
        delete oraclizeQueries[_queryId];
    }
}