Improve comments and small refactor.

Improve comments and small refactor.

/**
 * @title BlobStore
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract BlobStore {

    struct BlobInfo {               // Single slot.
        bool updatable;             // True if the blob is updatable. Can only be disabled.
        bool enforceRevisions;      // True if the blob is enforcing revisions. Can only be enabled.
        bool retractable;           // True if the blob can be retracted. Can only be disabled.
        bool transferable;          // True if the blob be transfered to another user or disowned. Can only be disabled.
        uint32 revisionCount;       // Number of revisions including revision 0.
        uint32 blockNumber;         // Block number which contains revision 0.
        address owner;              // Who owns this blob.
    }

    mapping (bytes32 => BlobInfo) blobInfo;
    mapping (bytes32 => mapping (uint => bytes32)) packedBlockNumbers;
    mapping (bytes32 => mapping (address => bool)) enabledTransfers;

    /**
     * @dev A blob revision has been published.
     * @param id Id of the blob.
     * @param revisionId Id of the revision (the highest at the time of logging).
     * @param blob Contents of the blob.
     */
    event logBlob(bytes32 indexed id, uint indexed revisionId, bytes blob);

    /**
     * @dev A revision has been retracted.
     * @param revisionId Id of the revision.
     */
    event logRetractRevision(bytes32 indexed id, uint revisionId);

    /**
     * @dev An entire blob has been retracted. This cannot be undone.
     * @param id Id of the blob.
     */
    event logRetract(bytes32 indexed id);

    /**
     * @dev A blob has been transfered to a new address.
     * @param id Id of the blob.
     * @param recipient The address that now owns the blob.
     */
    event logTransfer(bytes32 indexed id, address recipient);

    /**
     * @dev A blob has been disowned. This cannot be undone.
     * @param id Id of the blob.
     */
    event logDisown(bytes32 indexed id);

    /**
     * @dev A blob has been set as not updatable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotUpdatable(bytes32 indexed id);

    /**
     * @dev A blob has been set as enforcing revisions. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetEnforceRevisions(bytes32 indexed id);

    /**
     * @dev A blob has been set as not retractable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotRetractable(bytes32 indexed id);

    /**
     * @dev A blob has been set as not transferable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotTransferable(bytes32 indexed id);

    // Create a 96-bit id for this contract. This is unique across all blockchains.
    // Wait a few minutes after deploying for this id to settle.
    bytes12 contractId = bytes12(sha3(this, block.blockhash(block.number - 1)));

    /**
     * @dev Throw if the current message is sending a payment.
     */
    modifier noValue() {
        if (msg.value > 0) {
            throw;      // Do not maintain a balance.
        }
        _
    }

    /**
     * @dev Throw if the blob has not been used before or it has been retracted.
     * @param id Id of the blob.
     */
    modifier exists(bytes32 id) {
        if (blobInfo[id].blockNumber == 0 || blobInfo[id].blockNumber == uint32(-1)) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the owner of the blob is not the message sender.
     * @param id Id of the blob.
     */
    modifier isOwner(bytes32 id) {
        if (blobInfo[id].owner != msg.sender) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not updatable.
     * @param id Id of the blob.
     */
    modifier isUpdatable(bytes32 id) {
        if (!blobInfo[id].updatable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not enforcing revisions.
     * @param id Id of the blob.
     */
    modifier isNotEnforceRevisions(bytes32 id) {
        if (blobInfo[id].enforceRevisions) {
            throw;
        }
        _
    }

    /**
     * @dev Throw is the blob is not retractable.
     * @param id Id of the blob.
     */
    modifier isRetractable(bytes32 id) {
        if (!blobInfo[id].retractable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not transferable.
     * @param id Id of the blob.
     */
    modifier isTransferable(bytes32 id) {
        if (!blobInfo[id].transferable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not transferable to a specific user.
     * @param id Id of the blob.
     * @param recipient Address of the user.
     */
    modifier isTransferEnabled(bytes32 id, address recipient) {
        if (!enabledTransfers[id][recipient]) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob only has one revision.
     * @param id Id of the blob.
     */
    modifier hasAdditionalRevisions(bytes32 id) {
        if (blobInfo[id].revisionCount < 2) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if a specific blob revision does not exist.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     */
    modifier revisionExists(bytes32 id, uint revisionId) {
        if (revisionId >= blobInfo[id].revisionCount) {
            throw;
        }
        _
    }

    /**
     * @dev Stores new blob in the transaction log. It is guaranteed that each user will get a different id from the same nonce.
     * @param blob Blob that should be stored.
     * @param nonce Any value that the user has not used previously to create a blob.
     * @param updatable True if the blob should be updatable.
     * @param enforceRevisions True if the blob should enforce revisions.
     * @param retractable True if the blob should be retractable.
     * @param transferable True if the blob should be transferable.
     * @param anon True if the blob should be anonymous.
     * @return id Id of the blob.
     */
    function create(bytes blob, bytes32 nonce, bool updatable, bool enforceRevisions, bool retractable, bool transferable, bool anon) noValue external returns (bytes32 id) {
        // Determine the id.
        id = contractId | (sha3(msg.sender, nonce) & (2 ** 160 - 1));
        // Make sure this id has not been used before.
        if (blobInfo[id].blockNumber != 0) {
            throw;
        }
        // Store blob info in state.
        blobInfo[id] = BlobInfo({
            updatable: updatable,
            enforceRevisions: enforceRevisions,
            retractable: retractable,
            transferable: transferable,
            revisionCount: 1,
            blockNumber: uint32(block.number),
            owner: anon ? 0 : msg.sender,
        });
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Store a blob revision block number in a packed slot.
     * @param id Id of the blob.
     * @param offset The offset of the block number should be retreived.
     */
    function _setPackedBlockNumber(bytes32 id, uint offset) internal {
        // Get the slot.
        bytes32 slot = packedBlockNumbers[id][offset / 8];
        // Wipe the previous block number.
        slot &= ~bytes32(uint32(-1) * 2 ** ((offset % 8) * 32));
        // Insert the current block number.
        slot |= bytes32(uint32(block.number) * 2 ** ((offset % 8) * 32));
        // Store the slot.
        packedBlockNumbers[id][offset / 8] = slot;
    }

    /**
     * @dev Create a new blob revision.
     * @param id Id of the blob.
     * @param blob Blob that should be stored as the new revision. Typically a VCDIFF of an earlier revision.
     * @return revisionId The new revisionId.
     */
    function createNewRevision(bytes32 id, bytes blob) noValue isOwner(id) isUpdatable(id) external returns (uint revisionId) {
        // Increment the number of revisions.
        revisionId = blobInfo[id].revisionCount++;
        // Store the block number.
        _setPackedBlockNumber(id, revisionId - 1);
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    /**
     * @dev Update a blob's latest revision.
     * @param id Id of the blob.
     * @param blob Blob that should replace the latest revision. Typically a VCDIFF if there is an earlier revision.
     */
    function updateLatestRevision(bytes32 id, bytes blob) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        uint revisionId = blobInfo[id].revisionCount - 1;
        // Update the block number.
        if (revisionId == 0) {
            blobInfo[id].blockNumber = uint32(block.number);
        }
        else {
            _setPackedBlockNumber(id, revisionId - 1);
        }
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    /**
     * @dev Retract a blob's latest revision. Revision 0 cannot be retracted.
     * @param id Id of the blob.
     */
    function retractLatestRevision(bytes32 id) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) hasAdditionalRevisions(id) external {
        uint revisionId = --blobInfo[id].revisionCount;
        // Delete the slot if it is no longer required.
        if (revisionId % 8 == 1) {
            delete packedBlockNumbers[id][revisionId / 8];
        }
        // Log the retraction.
        logRetractRevision(id, revisionId);
    }

    /**
     * @dev Delete all of a blob's packed revision block numbers.
     * @param id Id of the blob.
     */
    function _deleteAllPackedRevisionBlockNumbers(bytes32 id) internal {
        // Determine how many slots should be deleted.
        // Block number of the first revision is stored in the blob info, so the first slot only needs to be deleted of there are at least 2 revisions.
        uint slotCount = (blobInfo[id].revisionCount + 6) / 8;
        // Delete the slots.
        for (uint i = 0; i < slotCount; i++) {
            delete packedBlockNumbers[id][i];
        }
    }

    /**
     * @dev Delete all a blob's revisions and replace it with a new blob.
     * @param id Id of the blob.
     * @param blob Blob that should be stored.
     */
    function restart(bytes32 id, bytes blob) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        // Delete the packed revision block numbers.
        _deleteAllPackedRevisionBlockNumbers(id);
        // Update the blob state info.
        blobInfo[id].revisionCount = 1;
        blobInfo[id].blockNumber = uint32(block.number);
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Retract a blob.
     * @param id Id of the blob.
     */
    function retract(bytes32 id) noValue isOwner(id) isRetractable(id) external {
        // Delete the packed revision block numbers.
        _deleteAllPackedRevisionBlockNumbers(id);
        // Mark this blob as retracted.
        blobInfo[id] = BlobInfo({
            updatable: false,
            enforceRevisions: false,
            retractable: false,
            transferable: false,
            revisionCount: 0,
            blockNumber: uint32(-1),
            owner: 0,
        });
        // Log that the blob has been retracted.
        logRetract(id);
    }

    /**
     * @dev Enable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferEnable(bytes32 id) noValue isTransferable(id) external {
        // Record in state that the current user will accept this blob.
        enabledTransfers[id][msg.sender] = true;
    }

    /**
     * @dev Disable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferDisable(bytes32 id) noValue isTransferEnabled(id, msg.sender) external {
        // Record in state that the current user will not accept this blob.
        enabledTransfers[id][msg.sender] = false;
    }

    /**
     * @dev Transfer a blob to a new user.
     * @param id Id of the blob.
     * @param recipient Address of the user to transfer to blob to.
     */
    function transfer(bytes32 id, address recipient) noValue isOwner(id) isTransferable(id) isTransferEnabled(id, recipient) external {
        // Update ownership of the blob.
        blobInfo[id].owner = recipient;
        // Disable this transfer in future and free up the slot.
        enabledTransfers[id][recipient] = false;
        // Log the transfer.
        logTransfer(id, recipient);
    }

    /**
     * @dev Disown a blob.
     * @param id Id of the blob.
     */
    function disown(bytes32 id) noValue isOwner(id) isTransferable(id) external {
        // Remove the owner from the blob's state.
        delete blobInfo[id].owner;
        // Log as blob as disowned.
        logDisown(id);
    }

    /**
     * @dev Set a blob as not updatable.
     * @param id Id of the blob.
     */
    function setNotUpdatable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not updatable.
        blobInfo[id].updatable = false;
        // Log that the blob is not updatable.
        logSetNotUpdatable(id);
    }

    /**
     * @dev Set a blob to enforce revisions.
     * @param id Id of the blob.
     */
    function setEnforceRevisions(bytes32 id) noValue isOwner(id) external {
        // Record in state that all changes to this blob must be new revisions.
        blobInfo[id].enforceRevisions = true;
        // Log that the blob now forces new revisions.
        logSetEnforceRevisions(id);
    }

    /**
     * @dev Set a blob to not be retractable.
     * @param id Id of the blob.
     */
    function setNotRetractable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not retractable.
        blobInfo[id].retractable = false;
        // Log that the blob is not retractable.
        logSetNotRetractable(id);
    }

    /**
     * @dev Set a blob to not be transferable.
     * @param id Id of the blob.
     */
    function setNotTransferable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not transferable.
        blobInfo[id].transferable = false;
        // Log that the blob is not transferable.
        logSetNotTransferable(id);
    }

    /**
     * @dev Get the id for this BlobStore contract.
     * @return Id of the contract.
     */
    function getContractId() noValue constant external returns (bytes12) {
        return contractId;
    }

    /**
     * @dev Get the block number for a specific blob revision.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     * @return blockNumber Block number of the specified revision.
     */
    function _getRevisionBlockNumber(bytes32 id, uint revisionId) internal returns (uint blockNumber) {
        if (revisionId == 0) {
            blockNumber = blobInfo[id].blockNumber;
        }
        else {
            bytes32 slot = packedBlockNumbers[id][(revisionId - 1) / 8];
            blockNumber = uint32(uint256(slot) / 2 ** (((revisionId - 1) % 8) * 32));
        }
    }

    /**
     * @dev Get the block numbers for all a blob's revisions.
     * @param id Id of the blob.
     * @return blockNumbers Revision block numbers.
     */
    function _getRevisionBlockNumbers(bytes32 id) internal returns (uint[] blockNumbers) {
        uint revisionCount = blobInfo[id].revisionCount;
        blockNumbers = new uint[](revisionCount);
        for (uint revisionId = 0; revisionId < revisionCount; revisionId++) {
            blockNumbers[revisionId] = _getRevisionBlockNumber(id, revisionId);
        }
    }

    /**
     * @dev Get info about a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     * @return revisionCount How many revisions the blob has.
     * @return blockNumbers The block numbers of the revisions.
     * @return updatable Is the blob updatable?
     * @return enforceRevisions Does the blob enforce revisions?
     * @return retractable Is the blob retractable?
     * @return transferable Is the blob transferable?
     */
    function getInfo(bytes32 id) noValue exists(id) constant external returns (address owner, uint revisionCount, uint[] blockNumbers, bool updatable, bool enforceRevisions, bool retractable, bool transferable) {
        owner = blobInfo[id].owner;
        revisionCount = blobInfo[id].revisionCount;
        blockNumbers = _getRevisionBlockNumbers(id);
        updatable = blobInfo[id].updatable;
        enforceRevisions = blobInfo[id].enforceRevisions;
        retractable = blobInfo[id].retractable;
        transferable = blobInfo[id].transferable;
    }

    /**
     * @dev Get the owner of a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     */
    function getOwner(bytes32 id) noValue exists(id) constant external returns (address owner) {
        owner = blobInfo[id].owner;
    }

    /**
     * @dev Get the number of revisions a blob has.
     * @param id Id of the blob.
     * @return revisionCount How many revisions the blob has.
     */
    function getRevisionCount(bytes32 id) noValue exists(id) constant external returns (uint revisionCount) {
        revisionCount = blobInfo[id].revisionCount;
    }

    /**
     * @dev Get the block number for a specific blob revision.
     * @param id Id of the blob.
     * @return blockNumbers Block number of the specified revision.
     */
    function getRevisionBlockNumbers(bytes32 id) noValue exists(id) constant external returns (uint[] blockNumbers) {
        blockNumbers = _getRevisionBlockNumbers(id);
    }

    /**
     * @dev Determine if a blob is updatable.
     * @param id Id of the blob.
     * @return updatable True if the blob is updatable.
     */
    function getUpdatable(bytes32 id) noValue exists(id) constant external returns (bool updatable) {
        updatable = blobInfo[id].updatable;
    }

    /**
     * @dev Determine if a blob enforces revisions.
     * @param id Id of the blob.
     * @return enforceRevisions True if the blob enforces revisions.
     */
    function getEnforceRevisions(bytes32 id) noValue exists(id) constant external returns (bool enforceRevisions) {
        enforceRevisions = blobInfo[id].enforceRevisions;
    }

    /**
     * @dev Determine if a blob is retractable.
     * @param id Id of the blob.
     * @return retractable True if the blob is blob retractable.
     */
    function getRetractable(bytes32 id) noValue exists(id) constant external returns (bool retractable) {
        retractable = blobInfo[id].retractable;
    }

    /**
     * @dev Determine if a blob is transferable.
     * @param id Id of the blob.
     * @return transferable True if the blob is transferable.
     */
    function getTransferable(bytes32 id) noValue exists(id) constant external returns (bool transferable) {
        transferable = blobInfo[id].transferable;
    }

    /**
     * @dev Default function.
     */
    function() {
        throw;      // Do not maintain a balance.
    }

}

/**
 * @title BlobStore
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract BlobStore {

    struct BlobInfo {               // Single slot.
        bool updatable;             // True if the blob is updatable. Can only be disabled.
        bool enforceRevisions;      // True if the blob is enforcing revisions. Can only be enabled.
        bool retractable;           // True if the blob can be retracted. Can only be disabled.
        bool transferable;          // True if the blob be transfered to another user or disowned. Can only be disabled.
        uint32 revisionCount;       // Number of revisions including revision 0.
        uint32 blockNumber;         // Block number which contains revision 0.
        address owner;              // Who owns this blob.
    }

    mapping (bytes32 => BlobInfo) blobInfo;
    mapping (bytes32 => mapping (uint => bytes32)) packedBlockNumbers;
    mapping (bytes32 => mapping (address => bool)) enabledTransfers;

    /**
     * @dev A blob revision has been published.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     * @param blob Contents of the blob.
     */
    event logBlob(bytes32 indexed id, uint indexed revisionId, bytes blob);

    /**
     * @dev A revision has been retracted.
     * @param revisionId Id of the revision.
     */
    event logRetractRevision(bytes32 indexed id, uint revisionId);

    /**
     * @dev An entire blob has been retracted. This cannot be undone.
     * @param id Id of the blob.
     */
    event logRetract(bytes32 indexed id);

    /**
     * @dev A blob has been transfered to a new address.
     * @param id Id of the blob.
     * @param recipient The address that now owns the blob.
     */
    event logTransfer(bytes32 indexed id, address recipient);

    /**
     * @dev A blob has been disowned. This cannot be undone.
     * @param id Id of the blob.
     */
    event logDisown(bytes32 indexed id);

    /**
     * @dev A blob has been set as not updatable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotUpdatable(bytes32 indexed id);

    /**
     * @dev A blob has been set as enforcing revisions. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetEnforceRevisions(bytes32 indexed id);

    /**
     * @dev A blob has been set as not retractable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotRetractable(bytes32 indexed id);

    /**
     * @dev A blob has been set as not transferable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotTransferable(bytes32 indexed id);

    // Create a 96-bit id for this contract. This is unique across all blockchains.
    // Wait a few minutes after deploying for this id to settle.
    bytes12 contractId = bytes12(sha3(this, block.blockhash(block.number - 1)));

    /**
     * @dev Throw if the current message is sending a payment.
     */
    modifier noValue() {
        if (msg.value > 0) {
            throw;      // Do not maintain a balance.
        }
        _
    }

    /**
     * @dev Throw if the blob has not been used before or it has been retracted.
     * @param id Id of the blob.
     */
    modifier exists(bytes32 id) {
        if (blobInfo[id].blockNumber == 0 || blobInfo[id].blockNumber == uint32(-1)) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the owner of the blob is not the message sender.
     * @param id Id of the blob.
     */
    modifier isOwner(bytes32 id) {
        if (blobInfo[id].owner != msg.sender) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not updatable.
     * @param id Id of the blob.
     */
    modifier isUpdatable(bytes32 id) {
        if (!blobInfo[id].updatable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not enforcing revisions.
     * @param id Id of the blob.
     */
    modifier isNotEnforceRevisions(bytes32 id) {
        if (blobInfo[id].enforceRevisions) {
            throw;
        }
        _
    }

    /**
     * @dev Throw is the blob is not retractable.
     * @param id Id of the blob.
     */
    modifier isRetractable(bytes32 id) {
        if (!blobInfo[id].retractable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not transferable.
     * @param id Id of the blob.
     */
    modifier isTransferable(bytes32 id) {
        if (!blobInfo[id].transferable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not transferable to a specific user.
     * @param id Id of the blob.
     * @param recipient Address of the user.
     */
    modifier isTransferEnabled(bytes32 id, address recipient) {
        if (!enabledTransfers[id][recipient]) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob only has one revision.
     * @param id Id of the blob.
     */
    modifier hasAdditionalRevisions(bytes32 id) {
        if (blobInfo[id].revisionCount < 2) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if a specific blob revision does not exist.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     */
    modifier revisionExists(bytes32 id, uint revisionId) {
        if (revisionId >= blobInfo[id].revisionCount) {
            throw;
        }
        _
    }

    /**
     * @dev Stores new blob in the transaction log. It is guaranteed that each user will get a different id from the same nonce.
     * @param blob Blob that should be stored.
     * @param nonce Any value that the user has not used previously to create a blob.
     * @param updatable True if the blob should be updatable.
     * @param enforceRevisions True if the blob should enforce revisions.
     * @param retractable True if the blob should be retractable.
     * @param transferable True if the blob should be transferable.
     * @param anon True if the blob should be anonymous.
     * @return id Id of the blob.
     */
    function create(bytes blob, bytes32 nonce, bool updatable, bool enforceRevisions, bool retractable, bool transferable, bool anon) noValue external returns (bytes32 id) {
        // Determine the id.
        id = contractId | (sha3(msg.sender, nonce) & (2 ** 160 - 1));
        // Make sure this id has not been used before.
        if (blobInfo[id].blockNumber != 0) {
            throw;
        }
        // Store blob info in state.
        blobInfo[id] = BlobInfo({
            updatable: updatable,
            enforceRevisions: enforceRevisions,
            retractable: retractable,
            transferable: transferable,
            revisionCount: 1,
            blockNumber: uint32(block.number),
            owner: anon ? 0 : msg.sender,
        });
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Store a blob revision block number in a packed slot.
     * @param id Id of the blob.
     * @param offset The offset of the block number should be retreived.
     */
    function _setPackedBlockNumber(bytes32 id, uint offset) internal {
        // Get the slot.
        bytes32 slot = packedBlockNumbers[id][offset / 8];
        // Wipe the previous block number.
        slot &= ~bytes32(uint32(-1) * 2 ** ((offset % 8) * 32));
        // Insert the current block number.
        slot |= bytes32(uint32(block.number) * 2 ** ((offset % 8) * 32));
        // Store the slot.
        packedBlockNumbers[id][offset / 8] = slot;
    }

    /**
     * @dev Create a new blob revision.
     * @param id Id of the blob.
     * @param blob Blob that should be stored as the new revision.
     * @return revisionId The new revisionId.
     */
    function createNewRevision(bytes32 id, bytes blob) noValue isOwner(id) isUpdatable(id) external returns (uint revisionId) {
        // Increment the number of revisions.
        revisionId = blobInfo[id].revisionCount++;
        // Store the block number.
        _setPackedBlockNumber(id, revisionId - 1);
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    /**
     * @dev Update a blob's latest revision.
     * @param id Id of the blob.
     * @param blob Blob that should replace the latest revision.
     */
    function updateLatestRevision(bytes32 id, bytes blob) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        uint revisionId = blobInfo[id].revisionCount - 1;
        // Update the block number.
        if (revisionId == 0) {
            blobInfo[id].blockNumber = uint32(block.number);
        }
        else {
            _setPackedBlockNumber(id, revisionId - 1);
        }
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    /**
     * @dev Retract a blob's latest revision.
     * @param id Id of the blob.
     */
    function retractLatestRevision(bytes32 id) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) hasAdditionalRevisions(id) external {
        uint revisionId = --blobInfo[id].revisionCount;
        // Check if we are deleting the first block number in a slot.
        if (revisionId % 8 == 1) {
            delete packedBlockNumbers[id][revisionId / 8];
        }
        // Log the retraction.
        logRetractRevision(id, revisionId);
    }

    /**
     * @dev Delete all of a blob's packed revision block numbers.
     * @param id Id of the blob.
     */
    function _deleteAllPackedRevisionBlockNumbers(bytes32 id) internal {
        // Determine how many slots should be deleted.
        // Block number of the first revision is stored in the blob info, so the first slot only needs to be deleted of there are at least 2 revisions.
        uint slotCount = (blobInfo[id].revisionCount + 6) / 8;
        // Delete the slots.
        for (uint i = 0; i < slotCount; i++) {
            delete packedBlockNumbers[id][i];
        }
    }

    /**
     * @dev Delete all a blob's revisions and replace it with a new blob.
     * @param id Id of the blob.
     * @param blob Blob that should be stored.
     */
    function restart(bytes32 id, bytes blob) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        // Try to get some gas refunds.
        _deleteAllPackedRevisionBlockNumbers(id);
        // Update the blob state info.
        blobInfo[id].revisionCount = 1;
        blobInfo[id].blockNumber = uint32(block.number);
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Retract a blob.
     * @param id Id of the blob.
     */
    function retract(bytes32 id) noValue isOwner(id) isRetractable(id) external {
        // Delete the packed revision block numbers.
        _deleteAllPackedRevisionBlockNumbers(id);
        // Mark this blob as retracted.
        blobInfo[id] = BlobInfo({
            updatable: false,
            enforceRevisions: false,
            retractable: false,
            transferable: false,
            revisionCount: 0,
            blockNumber: uint32(-1),
            owner: 0,
        });
        // Log that the blob has been retracted.
        logRetract(id);
    }

    /**
     * @dev Enable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferEnable(bytes32 id) noValue isTransferable(id) external {
        // Record in state that the current user will accept this blob.
        enabledTransfers[id][msg.sender] = true;
    }

    /**
     * @dev Disable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferDisable(bytes32 id) noValue isTransferEnabled(id, msg.sender) external {
        // Record in state that the current user will not accept this blob.
        enabledTransfers[id][msg.sender] = false;
    }

    /**
     * @dev Transfer a blob to a new user.
     * @param id Id of the blob.
     * @param recipient Address of the user to transfer to blob to.
     */
    function transfer(bytes32 id, address recipient) noValue isOwner(id) isTransferable(id) isTransferEnabled(id, recipient) external {
        // Update ownership of the blob.
        blobInfo[id].owner = recipient;
        // Disable this transfer in future and free up the slot.
        enabledTransfers[id][recipient] = false;
        // Log the transfer.
        logTransfer(id, recipient);
    }

    /**
     * @dev Disown a blob.
     * @param id Id of the blob.
     */
    function disown(bytes32 id) noValue isOwner(id) isTransferable(id) external {
        // Remove the owner from the blob's state.
        delete blobInfo[id].owner;
        // Log as blob as disowned.
        logDisown(id);
    }

    /**
     * @dev Set a blob as not updatable.
     * @param id Id of the blob.
     */
    function setNotUpdatable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not updatable.
        blobInfo[id].updatable = false;
        // Log that the blob is not updatable.
        logSetNotUpdatable(id);
    }

    /**
     * @dev Set a blob to enforce revisions.
     * @param id Id of the blob.
     */
    function setEnforceRevisions(bytes32 id) noValue isOwner(id) external {
        // Record in state that all changes to this blob must be new revisions.
        blobInfo[id].enforceRevisions = true;
        // Log that the blob now forces new revisions.
        logSetEnforceRevisions(id);
    }

    /**
     * @dev Set a blob to not be retractable.
     * @param id Id of the blob.
     */
    function setNotRetractable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not retractable.
        blobInfo[id].retractable = false;
        // Log that the blob is not retractable.
        logSetNotRetractable(id);
    }

    /**
     * @dev Set a blob to not be transferable.
     * @param id Id of the blob.
     */
    function setNotTransferable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not transferable.
        blobInfo[id].transferable = false;
        // Log that the blob is not transferable.
        logSetNotTransferable(id);
    }

    /**
     * @dev Get the id for this BlobStore contract.
     * @return Id of the contract.
     */
    function getContractId() noValue constant external returns (bytes12) {
        return contractId;
    }

    /**
     * @dev Get the block number for a specific blob revision.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     * @return blockNumber Block number of the specified revision.
     */
    function _getRevisionBlockNumber(bytes32 id, uint revisionId) internal returns (uint blockNumber) {
        if (revisionId == 0) {
            blockNumber = blobInfo[id].blockNumber;
        }
        else {
            bytes32 slot = packedBlockNumbers[id][(revisionId - 1) / 8];
            blockNumber = uint32(uint256(slot) / 2 ** (((revisionId - 1) % 8) * 32));
        }
    }

    /**
     * @dev Get the block numbers for all a blob's revisions.
     * @param id Id of the blob.
     * @return blockNumbers Revision block numbers.
     */
    function _getRevisionBlockNumbers(bytes32 id) internal returns (uint[] blockNumbers) {
        blockNumbers = new uint[](blobInfo[id].revisionCount);
        for (uint revisionId = 0; revisionId < blobInfo[id].revisionCount; revisionId++) {
            blockNumbers[revisionId] = _getRevisionBlockNumber(id, revisionId);
        }
    }

    /**
     * @dev Get info about a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     * @return revisionCount How many revisions the blob has.
     * @return blockNumbers The block numbers of the revisions.
     * @return updatable Is the blob updatable?
     * @return enforceRevisions Does the blob enforce revisions?
     * @return retractable Is the blob retractable?
     * @return transferable Is the blob transferable?
     */
    function getInfo(bytes32 id) noValue exists(id) constant external returns (address owner, uint revisionCount, uint[] blockNumbers, bool updatable, bool enforceRevisions, bool retractable, bool transferable) {
        owner = blobInfo[id].owner;
        revisionCount = blobInfo[id].revisionCount;
        blockNumbers = _getRevisionBlockNumbers(id);
        updatable = blobInfo[id].updatable;
        enforceRevisions = blobInfo[id].enforceRevisions;
        retractable = blobInfo[id].retractable;
        transferable = blobInfo[id].transferable;
    }

    /**
     * @dev Get the owner of a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     */
    function getOwner(bytes32 id) noValue exists(id) constant external returns (address owner) {
        owner = blobInfo[id].owner;
    }

    /**
     * @dev Get the number of revisions a blob has.
     * @param id Id of the blob.
     * @return revisionCount How many revisions the blob has.
     */
    function getRevisionCount(bytes32 id) noValue exists(id) constant external returns (uint revisionCount) {
        revisionCount = blobInfo[id].revisionCount;
    }

    /**
     * @dev Get the block number for a specific blob revision.
     * @param id Id of the blob.
     * @return blockNumbers Block number of the specified revision.
     */
    function getRevisionBlockNumbers(bytes32 id) noValue exists(id) constant external returns (uint[] blockNumbers) {
        blockNumbers = _getRevisionBlockNumbers(id);
    }

    /**
     * @dev Determine if a blob is updatable.
     * @param id Id of the blob.
     * @return updatable True if the blob is updatable.
     */
    function getUpdatable(bytes32 id) noValue exists(id) constant external returns (bool updatable) {
        updatable = blobInfo[id].updatable;
    }

    /**
     * @dev Determine if a blob enforces revisions.
     * @param id Id of the blob.
     * @return enforceRevisions True if the blob enforces revisions.
     */
    function getEnforceRevisions(bytes32 id) noValue exists(id) constant external returns (bool enforceRevisions) {
        enforceRevisions = blobInfo[id].enforceRevisions;
    }

    /**
     * @dev Determine if a blob is retractable.
     * @param id Id of the blob.
     * @return retractable True if the blob is blob retractable.
     */
    function getRetractable(bytes32 id) noValue exists(id) constant external returns (bool retractable) {
        retractable = blobInfo[id].retractable;
    }

    /**
     * @dev Determine if a blob is transferable.
     * @param id Id of the blob.
     * @return transferable True if the blob is transferable.
     */
    function getTransferable(bytes32 id) noValue exists(id) constant external returns (bool transferable) {
        transferable = blobInfo[id].transferable;
    }

    /**
     * @dev Default function.
     */
    function() {
        throw;      // Do not maintain a balance.
    }

}


Fix checking invalid transfer

Fix checking invalid transfer

pragma solidity ^0.4.4;

import "./ConvertLib.sol";

contract UTCoin {
    uint256 public totalSupply = 10000; // トークンの総量

    // EVM上にstorage領域を定義。key => value になっていて address: uint 型で array balances を作る。
    mapping (address => uint) balances; // 各アドレスの残高

    /**
     * イベント通知
     * Transfer eventlog を定義
     * @param _from 受信アドレス
     * @param _to 送信アドレス
     * @param _value 送金額
     */
    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    /**
     * コンストラクタ
     */
    function UTCoin() {
        balances[tx.origin] = totalSupply;
    }

    /**
     * 送金
     * @param receiver 受信アドレス
     * @param amount 送金量
     * @return sufficient
     */
    function sendCoin(address receiver, uint amount) returns(bool sufficient) {
        // 不正送金チェック
        if (balances[msg.sender] < amount) throw;
        if (balances[receiver] + amount < balances[receiver]) throw;

        // 送信アドレスと受信アドレスの残高を更新
        balances[msg.sender] -= amount;
        balances[receiver] += amount;

        // イベント通知
        Transfer(msg.sender, receiver, amount);

        return true;
    }

    /**
     * ETH balance を返す
     * address の持っている UTCoin balance を2倍にして返す。この時 ConvertLib contract が呼ばれる。
     * @param addr アドレス
     * @return ETH balance
     */
    function getBalanceInEth(address addr) returns(uint){
        return ConvertLib.convert(getBalance(addr),2);
    }

    /**
     * UTCoin balance を返す
     * @param addr アドレス
     * @return UTCoin balance
     */
    function getBalance(address addr) returns(uint) {
        return balances[addr];
    }
}

pragma solidity ^0.4.4;

import "./ConvertLib.sol";

contract UTCoin {
    uint256 public totalSupply = 10000; // トークンの総量

    // EVM上にstorage領域を定義。key => value になっていて address: uint 型で array balances を作る。
    mapping (address => uint) balances; // 各アドレスの残高

    /**
     * Transfer eventlog を定義
     * @param _from 受信アドレス
     * @param _to 送信アドレス
     * @param _value 送金額
     */
    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    /**
     * コンストラクタ
     */
    function UTCoin() {
        balances[tx.origin] = totalSupply;
    }

    /**
     * 送金
     * @param receiver 受信アドレス
     * @param amount 送金量
     * @return sufficient
     */
    function sendCoin(address receiver, uint amount) returns(bool sufficient) {
        // 不正送金チェック
        if (balances[msg.sender] < amount) return false;
        if (balances[receiver] + amount < balances[receiver]) return false;

        // 送信アドレスと受信アドレスの残高を更新
        balances[msg.sender] -= amount;
        balances[receiver] += amount;

        // イベント通知
        Transfer(msg.sender, receiver, amount);

        return true;
    }

    /**
     * ETH balance を返す
     * address の持っている UTCoin balance を2倍にして返す。この時 ConvertLib contract が呼ばれる。
     * @param addr アドレス
     * @return ETH balance
     */
    function getBalanceInEth(address addr) returns(uint){
        return ConvertLib.convert(getBalance(addr),2);
    }

    /**
     * UTCoin balance を返す
     * @param addr アドレス
     * @return UTCoin balance
     */
    function getBalance(address addr) returns(uint) {
        return balances[addr];
    }
}


AssertBool.sol

AssertBool.sol

pragma solidity >= 0.4.15 < 0.6.0;

library AssertBool {

    /*
        Event: TestEvent

        Fired when an assertion is made.

        Params:
            result (bool) - Whether or not the assertion holds.
            message (string) - A message to display if the assertion does not hold.
    */
    event TestEvent(bool indexed result, string message);

    // ************************************** bool **************************************

    /*
        Function: isTrue

        Assert that a boolean is 'true'.

        : b == true

        Params:
            b (bool) - The boolean.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function isTrue(bool b, string memory message) public returns (bool result) {
        result = b;
        _report(result, message);
    }

    /*
        Function: isFalse

        Assert that a boolean is 'false'.

        : b == false

        Params:
            b (bool) - The boolean.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function isFalse(bool b, string memory message) public returns (bool result) {
        result = !b;
        _report(result, message);
    }

    /*
        Function: equal(bool)

        Assert that two booleans are equal.

        : A == B

        Params:
            A (bool) - The first boolean.
            B (bool) - The second boolean.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function equal(bool a, bool b, string memory message) public returns (bool result) {
        result = (a == b);
        if (result)
            _report(result, message);
        else
            _report(result, _appendTagged(_tag(a, "Tested"), _tag(b, "Against"), message));
    }

    /*
        Function: notEqual(bool)

        Assert that two booleans are not equal.

        : A != B

        Params:
            A (bool) - The first boolean.
            B (bool) - The second boolean.
            message (string) - A message that is sent if the assertion fails.

        Returns:
            result (bool) - The result.
    */
    function notEqual(bool a, bool b, string memory message) public returns (bool result) {
        result = (a != b);
        if (result)
            _report(result, message);
        else
            _report(result, _appendTagged(_tag(a, "Tested"), _tag(b, "Against"), message));
    }

    /******************************** internal ********************************/

        /*
            Function: _report

            Internal function for triggering <TestEvent>.

            Params:
                result (bool) - The test result (true or false).
                message (string) - The message that is sent if the assertion fails.
        */
    function _report(bool result, string memory message) internal {
        if(result)
            emit TestEvent(true, "");
        else
            emit TestEvent(false, message);
    }

    /*
        Function: _ltoa

        Convert an boolean to a string.

        Params:
            val (bool) - The boolean.

        Returns:
            result (string) - "true" if true, "false" if false.
    */
    function _ltoa(bool val) internal pure returns (string memory) {
        bytes memory b;
        if (val) {
            b = new bytes(4);
            b[0] = 't';
            b[1] = 'r';
            b[2] = 'u';
            b[3] = 'e';
            return string(b);
        }
        else {
            b = new bytes(5);
            b[0] = 'f';
            b[1] = 'a';
            b[2] = 'l';
            b[3] = 's';
            b[4] = 'e';
            return string(b);
        }
    }

    /*
    function htoa(address addr) constant returns (string) {
        bytes memory bts = new bytes(40);
        bytes20 addrBts = bytes20(addr);
        for (uint i = 0; i < 20; i++) {
            bts[2*i] = addrBts[i] % 16;
            bts[2*i + 1] = (addrBts[i] / 16) % 16;
        }
        return string(bts);
    }
    */

    /*
        Function: _tag(string)

        Add a tag to a string. The 'value' and 'tag' strings are returned on the form "tag: value".

        Params:
            value (string) - The value.
            tag (string) - The tag.

        Returns:
            result (string) - "tag: value"
    */
    function _tag(string memory value, string memory tag) internal pure returns (string memory) {

        bytes memory valueB = bytes(value);
        bytes memory tagB = bytes(tag);

        uint vl = valueB.length;
        uint tl = tagB.length;

        bytes memory newB = new bytes(vl + tl + 2);

        uint i;
        uint j;

        for (i = 0; i < tl; i++)
            newB[j++] = tagB[i];
        newB[j++] = ':';
        newB[j++] = ' ';
        for (i = 0; i < vl; i++)
            newB[j++] = valueB[i];

        return string(newB);
    }

    /*
        Function: _tag(bool)

        Add a tag to a boolean.

        Params:
            value (bool) - The value.
            tag (string) - The tag.

        Returns:
            result (string) - "tag: _ltoa(value)"
    */
    function _tag(bool value, string memory tag) internal pure returns (string memory) {
        string memory nstr = _ltoa(value);
        return _tag(nstr, tag);
    }

    /*
        Function: _appendTagged(string, string)

        Append two tagged values to a string.

        Params:
            tagged0 (string) - The first tagged value.
            tagged1 (string) - The second tagged value.
            str (string) - The string.

        Returns:
            result (string) - "str (tagged0, tagged1)"
    */
    function _appendTagged(string memory tagged0, string memory tagged1, string memory str) internal pure returns (string memory) {

        bytes memory tagged0B = bytes(tagged0);
        bytes memory tagged1B = bytes(tagged1);
        bytes memory strB = bytes(str);

        uint sl = strB.length;
        uint t0l = tagged0B.length;
        uint t1l = tagged1B.length;

        bytes memory newB = new bytes(sl + t0l + t1l + 5);

        uint i;
        uint j;

        for (i = 0; i < sl; i++)
            newB[j++] = strB[i];
        newB[j++] = ' ';
        newB[j++] = '(';
        for (i = 0; i < t0l; i++)
            newB[j++] = tagged0B[i];
        newB[j++] = ',';
        newB[j++] = ' ';
        for (i = 0; i < t1l; i++)
            newB[j++] = tagged1B[i];
        newB[j++] = ')';

        return string(newB);
    }

}

error: pathspec 'packages/truffle-core/lib/testing/AssertBool.sol' did not match any file(s) known to git


Changed event contract

Changed event contract

contract Event {  // can be killed, so the owner gets sent the money in the end

	address public organizer;
	mapping (address => bool) public attendeesPaid;
	uint public numAttendees;
	uint public quota;

	event PurchaseTicket(address _from, uint _amount); // so you can log the event
	event RefundTicket(address _to, uint _amount); // so you can log the event
	event HowMuchMoneyWasSent(uint _amount);

	function Event() {
		organizer = msg.sender;
		quota = 100;
		numAttendees = 0;
	}

	function buyTicket() public {
		if (numAttendees > quota) {
			throw; // throw ensures funds will be returned
		}

		if (msg.value != price) { //
			HowMuchMoneyWasSent(msg.value);
			throw;
		}

		attendeesPaid[msg.sender] = true;
		if (!organizer.send(msg.value)) throw; //send ether but catch error
		numAttendees++;
		PurchaseTicket(msg.sender, msg.value);
	}

	function getNumAttendees() returns (uint numAttendees){
		return numAttendees;
	}

	// function refundTicket(address recipient, uint amount) public {
	// 	if (msg.sender != organizer) { return; }
	// 	if (attendeesPaid[recipient] == amount) {
	// 		address myAddress = this;
	// 		if (myAddress.balance >= amount) {
	// 			if (!recipient.send(amount)) throw;
	// 			RefundTicket(recipient, amount);
	// 			attendeesPaid[recipient] = 0;
	// 			numAttendees--;
	// 		}
	// 	}
	// 	return;
	// }

	function destroy() {
		if (msg.sender == organizer) { // without this funds could be locked in the contract forever!
			suicide(organizer);
		}
	}
}

contract Event {  // can be killed, so the owner gets sent the money in the end

	address public organizer;
	mapping (address => uint) public attendeesPaid;
	uint public numAttendees;
	uint public quota;

	event PurchaseTicket(address _from, uint _amount); // so you can log the event
	event RefundTicket(address _to, uint _amount); // so you can log the event

	function Event() {
		organizer = msg.sender;
		quota = 100;
		numAttendees = 0;
	}

	function buyTicket() public {
		if (numAttendees >= quota) {
			throw; // throw ensures funds will be returned
		}
		attendeesPaid[msg.sender] = msg.value;
		if (!organizer.send(msg.value/2)) throw;
		/*transfer(msg.value/2);*/
		numAttendees++;
		PurchaseTicket(msg.sender, msg.value);
	}

	function getNumAttendees() returns (uint numAttendees){
		return numAttendees;
	}

	function changeQuota(uint newquota) public {
		if (msg.sender != organizer) { return; }
		quota = newquota;
	}

	function refundTicket(address recipient, uint amount) public {
		if (msg.sender != organizer) { return; }
		if (attendeesPaid[recipient] == amount) {
			address myAddress = this;
			if (myAddress.balance >= amount) {
				if (!recipient.send(amount)) throw;
				RefundTicket(recipient, amount);
				attendeesPaid[recipient] = 0;
				numAttendees--;
			}
		}
		return;
	}

	function destroy() {
		if (msg.sender == organizer) { // without this funds could be locked in the contract forever!
			suicide(organizer);
		}
	}
}


updated events in Access.sol

updated events in Access.sol

/// @author hugooconnor
/// @title A shared account to demo some features of solidity, with standard tokens
/// see how to document solidity code; https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format

contract Access {

	/**
	 * Data structures
	 * members -- an array of addresses, useful for looping over
	 * member -- a mapping of addresses to Member objects
	 * Member -- a struct containing member details
   * tokenSupply -- how many tokens on issue
   * tokens -- mapping of addresses to tokens
	 */
  address[] public members;
  mapping(address => Member) public member;

  struct Member {
        uint joinDate;
        bool exists;
        bool isSpecial;
  }

  uint tokenSupply;
  mapping(address => uint) public tokens;

  	/**
	 * Events: a cheaper option than storing all data on chain - append Log to events for clarity
	 * NewMember -- will call when new member joins
	 * Spend -- will call when contract funds spent
   * Transfer -- will call when token is transfered
	 */
  event NewMemberLog(address admin, address newMember, uint joinDate, bool exists, bool isSpecial);
  event SpendLog(uint date, address recipient, uint amount);
  event TransferLog(uint date, address sender, address recipient, uint amount);

	/**
	 * Constructor -- adds msg.sender to membership, sets them as special
	 */
  function Access(){
        member[msg.sender] = Member(now, true, true);
        members.push(msg.sender);
        NewMemberLog(msg.sender, msg.sender, member[msg.sender].joinDate, member[msg.sender].exists, member[msg.sender].isSpecial);
        tokens[msg.sender] += 1000;
        tokenSupply += 1000;
  }

  	/**
	 * Function modifier -- only special members can execute _ block
	 */
  modifier onlySpecial {
      if (member[msg.sender].isSpecial) {
        _
      }
  }

	/// @notice Adds new members or sets existing members to special, onlySpecial can call
	/// @param _nominee the person we are adding as a member
	///	@param _isSpecial if they are special or not
	/// @return success if state changes
  function addMember(address _nominee, bool _isSpecial) onlySpecial returns (bool success){
  		if(!member[_nominee].exists){
            member[_nominee] = Member(now, true, _isSpecial);
            members.push(_nominee);
            tokens[_nominee] += 1000;
            tokenSupply += 1000;
            NewMemberLog(msg.sender, _nominee, member[_nominee].joinDate, member[_nominee].exists, member[_nominee].isSpecial);
            return true;
  		} else if (member[_nominee].exists && _isSpecial){
            member[_nominee].isSpecial = _isSpecial;
            return true;
  		}
        return false;
  }

	/// @notice Spends contract funds, onlySpecial can call
	/// @param _recipient who is recieving the funds
	/// @param _amount how much they are getting
	/// @return success if funds are sent
  function spend(address _recipient, uint _amount) onlySpecial returns (bool success){
  		if(this.balance >= _amount){
            _recipient.send(_amount);
            SpendLog(now, _recipient, _amount);
            return true;
  		} else {
            return false;
  		}
  }

  /// @notice Gets total supply of issued tokens
  /// @return supply how many tokens are on issue
  function totalSupply() constant returns (uint256 supply){
    return tokenSupply;
  }

  /// @notice Gets the token balance of an address
  /// @param _owner whose address are we looking up
  /// @return balance how many tokens they have
  function balanceOf(address _owner) constant returns (uint256 balance){
    return tokens[_owner];
  }

  /// @notice transfers tokens between users
  /// @param _to who is the transfer to
  /// @param _value how many tokens are they transferring
  /// @return success if the transfer is successful or not
  function transfer(address _to, uint256 _value) returns (bool success){
    if(tokens[msg.sender] >= _value){
      tokens[msg.sender] -= _value;
      tokens[_to] += _value;
      TransferLog(now, msg.sender, _to, _value);
      return true;
    }
    return false;
  }
}

/// @author hugooconnor
/// @title A shared account to demo some features of solidity, with standard tokens
/// see how to document solidity code; https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format

contract Access {

	/**
	 * Data structures
	 * members -- an array of addresses, useful for looping over
	 * member -- a mapping of addresses to Member objects
	 * Member -- a struct containing member details
   * tokenSupply -- how many tokens on issue
   * tokens -- mapping of addresses to tokens
	 */
  address[] public members;
  mapping(address => Member) public member;

  struct Member {
        uint joinDate;
        bool exists;
        bool isSpecial;
  }

  uint tokenSupply;
  mapping(address => uint) public tokens;

  	/**
	 * Events: a cheaper option than storing all data on chain
	 * NewMember -- will call when new member joins
	 * Spend -- will call when contract funds spent
   * Transfer -- will call when token is transfered
	 */
  event NewMember(address admin, address newMember, uint joinDate, bool exists, bool isSpecial);
  event Spend(uint date, address recipient, uint amount);
  event Transfer(uint date, address sender, address recipient, uint amount);

	/**
	 * Constructor -- adds msg.sender to membership, sets them as special
	 */
  function Access(){
        member[msg.sender] = Member(now, true, true);
        members.push(msg.sender);
        NewMember(msg.sender, msg.sender, member[msg.sender].joinDate, member[msg.sender].exists, member[msg.sender].isSpecial);
        tokens[msg.sender] += 1000;
        tokenSupply += 1000;
  }

  	/**
	 * Function modifier -- only special members can execute _ block
	 */
  modifier onlySpecial {
      if (member[msg.sender].isSpecial) {
        _
      }
  }

	/// @notice Adds new members or sets existing members to special, onlySpecial can call
	/// @param _nominee the person we are adding as a member
	///	@param _isSpecial if they are special or not
	/// @return success if state changes
  function addMember(address _nominee, bool _isSpecial) onlySpecial returns (bool success){
  		if(!member[_nominee].exists){
            member[_nominee] = Member(now, true, _isSpecial);
            members.push(_nominee);
            tokens[_nominee] += 1000;
            tokenSupply += 1000;
            NewMember(msg.sender, _nominee, member[_nominee].joinDate, member[_nominee].exists, member[_nominee].isSpecial);
            return true;
  		} else if (member[_nominee].exists && _isSpecial){
            member[_nominee].isSpecial = _isSpecial;
            return true;
  		}
        return false;
  }

	/// @notice Spends contract funds, onlySpecial can call
	/// @param _recipient who is recieving the funds
	/// @param _amount how much they are getting
	/// @return success if funds are sent
  function spend(address _recipient, uint _amount) onlySpecial returns (bool success){
  		if(this.balance >= _amount){
            _recipient.send(_amount);
            Spend(now, _recipient, _amount);
            return true;
  		} else {
            return false;
  		}
  }

  /// @notice Gets total supply of issued tokens
  /// @return supply how many tokens are on issue
  function totalSupply() constant returns (uint256 supply){
    return tokenSupply;
  }

  /// @notice Gets the token balance of an address
  /// @param _owner whose address are we looking up
  /// @return balance how many tokens they have
  function balanceOf(address _owner) constant returns (uint256 balance){
    return tokens[_owner];
  }

  /// @notice transfers tokens between users
  /// @param _to who is the transfer to
  /// @param _value how many tokens are they transferring
  /// @return success if the transfer is successful or not
  function transfer(address _to, uint256 _value) returns (bool success){
    if(tokens[msg.sender] >= _value){
      tokens[msg.sender] -= _value;
      tokens[_to] += _value;
      Transfer(now, msg.sender, _to, _value);
      return true;
    }
    return false;
  }
}


adds tests to ensure our parsing works as expected.

/*
    Copyright 2017-2018 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity ^0.4.24;

import "truffle/Assert.sol";
import "../../contracts/libraries/StringLib.sol";

contract TestStringLib {
    using StringLib for *;

    function testToSlice() public {
        StringLib.slice memory sliceTest = "HelloWorld".toSlice();
        Assert.equal(sliceTest._len, 10,  "Length should match supplied string length");
        Assert.equal(sliceTest._ptr, 224,  "PTR should match supplied string");
    }

    function testDelimAndSplit() public {
        string memory oracleQueryPath = 'result.XETHZUSD.c.0';
        StringLib.slice memory pathSlice = oracleQueryPath.toSlice();
        StringLib.slice memory delim = ".".toSlice();
        uint length = pathSlice.count(delim) + 1;
        string[4] memory expectedResults = ['result', 'XETHZUSD', 'c', '0'];
        for (uint i = 0; i < length; i++) {
            Assert.equal(expectedResults[i], pathSlice.split(delim).toString(), "String not split properly!");
        }
    }

}

/*
    Copyright 2017-2018 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity ^0.4.24;

import "truffle/Assert.sol";
import "../../contracts/libraries/OrderLib.sol";

contract TestOrderLib {

}


Add comment

Add comment

pragma solidity ^0.4.0;

contract IdClaveChain
{
    struct Request
    {
        address requester;
        bytes4 callback;
        bool isDone;
        bytes32 user;
        // eight part of RSA encrypted password
        bytes32 encPassword_0;
        bytes32 encPassword_1;
        bytes32 encPassword_2;
        bytes32 encPassword_3;
        bytes32 encPassword_4;
        bytes32 encPassword_5;
        bytes32 encPassword_6;
        bytes32 encPassword_7;
    }

    address clave;
    uint64 public currentId;
    mapping (uint64 => Request) public requests;
    uint256 constant REQUEST_ETH = 0x10000000000000;

    function IdClaveChain(address _clave) public {
        clave = _clave;
    }

    function Register(bytes4 callback, bytes32 user, bytes32[8] encPassword) payable public
    {
        if(msg.value < REQUEST_ETH)
        {
            throw;
        }
        uint64 id = currentId;
        currentId++;
        requests[id].requester = msg.sender;
        requests[id].callback = callback;
        requests[id].isDone = false;
        requests[id].user = user;
        requests[id].encPassword_0 = encPassword[0];
        requests[id].encPassword_1 = encPassword[1];
        requests[id].encPassword_2 = encPassword[2];
        requests[id].encPassword_3 = encPassword[3];
        requests[id].encPassword_4 = encPassword[4];
        requests[id].encPassword_5 = encPassword[5];
        requests[id].encPassword_6 = encPassword[6];
        requests[id].encPassword_7 = encPassword[7];
        clave.transfer(REQUEST_ETH);
    }

    function SendResult(uint64 id, bytes32 user, bytes32 hashSaltPassword) public
    {
        if(requests[id].isDone) {
            throw;
        }
        if(msg.sender != clave){
            throw;
        }

        address requester = requests[id].requester;
        bytes4 callback = requests[id].callback;
        requester.call(callback, user, hashSaltPassword);
        requests[id].isDone = true;
    }
}

pragma solidity ^0.4.0;

contract IdClaveChain
{
    struct Request
    {
        address requester;
        bytes4 callback;
        bool isDone;
        bytes32 user;
        bytes32 encPassword_0;
        bytes32 encPassword_1;
        bytes32 encPassword_2;
        bytes32 encPassword_3;
        bytes32 encPassword_4;
        bytes32 encPassword_5;
        bytes32 encPassword_6;
        bytes32 encPassword_7;
    }

    address clave;
    uint64 public currentId;
    mapping (uint64 => Request) public requests;
    uint256 constant REQUEST_ETH = 0x10000000000000;

    function IdClaveChain(address _clave) public {
        clave = _clave;
    }

    function Register(bytes4 callback, bytes32 user, bytes32[8] encPassword) payable public
    {
        if(msg.value < REQUEST_ETH)
        {
            throw;
        }
        uint64 id = currentId;
        currentId++;
        requests[id].requester = msg.sender;
        requests[id].callback = callback;
        requests[id].isDone = false;
        requests[id].user = user;
        requests[id].encPassword_0 = encPassword[0];
        requests[id].encPassword_1 = encPassword[1];
        requests[id].encPassword_2 = encPassword[2];
        requests[id].encPassword_3 = encPassword[3];
        requests[id].encPassword_4 = encPassword[4];
        requests[id].encPassword_5 = encPassword[5];
        requests[id].encPassword_6 = encPassword[6];
        requests[id].encPassword_7 = encPassword[7];
        clave.transfer(REQUEST_ETH);
    }

    function SendResult(uint64 id, bytes32 user, bytes32 hashSaltPassword) public
    {
        if(requests[id].isDone) {
            throw;
        }
        if(msg.sender != clave){
            throw;
        }

        address requester = requests[id].requester;
        bytes4 callback = requests[id].callback;
        requester.call(callback, user, hashSaltPassword);
        requests[id].isDone = true;
    }
}


Added getters for arrays

Added getters for arrays

pragma solidity ^0.4.2;

contract GitBountyCreator {
    struct Bounty {
        address addr;
        uint256 totalVotes;
        uint256 totalVoters;
        uint256 payoutAmount;
    }
    mapping (string => Bounty) private bounties;
    address[] bountiesAddressesArray;
    modifier isChild(string key) {
        require(bounties[key].addr == msg.sender);
        _;
    }
    function createBounty(string issueUrl, address[] voters,uint256  expiresIn ) public payable returns(address) {
        GitBounty b = new GitBounty(issueUrl, voters, expiresIn, this);
        bounties[issueUrl] = Bounty({
            addr: b,
            totalVotes: 0,
            totalVoters: voters.length,
            payoutAmount: 0
        });
        b.addToBounty.value(msg.value)();
        bountiesAddressesArray.push(b);
        return b;
    }
    function getBounty(string key) public constant returns (address, uint256, uint256, uint256) {
        return (bounties[key].addr, bounties[key].totalVotes, bounties[key].totalVoters, bounties[key].payoutAmount);
    }
    function updateBountyAmount(string key, uint256 newAmount) public isChild(key) {
        Bounty storage b = bounties[key];
        b.payoutAmount = newAmount;
        bounties[key] = b;
    }
    function updateVoteProgress(string key, uint256 newTotalVotes) public isChild(key) {
      Bounty storage b = bounties[key];
      b.totalVotes = newTotalVotes;
      bounties[key] = b;
    }
    function getAllBounties() public constant returns (address[]) {
      return bountiesAddressesArray;
    }
}

contract GitBounty {
    GitBountyCreator public parent;
    string public key;
    address public owner;
    uint256 public totalBounty;
    uint256 public expiresAt;
    address[] public voterAddresses;
    uint256 public totalVotes;
    mapping (address => uint256) public contributions;
    mapping (address => bool) public eligibleVotersAddresses;
    mapping (address => uint256) public votes;
    address[] public PRS;
    uint256 public totalPRS;
    uint256 public requiredNumberOfVotes;
    bool public isBountyOpen;
    mapping (bytes32 => bool) private hasVotedToAddress;

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    modifier isEligibleVoter {
        require(eligibleVotersAddresses[msg.sender]);
        _;
    }
    modifier bountyOpen {
        require(isBountyOpen);
        _;
    }
    modifier votedOnce(address voter, address hunter) {
        require(!hasVoted(voter, hunter));
        _;
    }
    function GitBounty(string issueUrl, address[] voters,uint256  expiresIn, GitBountyCreator parentAddress ) public payable {
        parent = parentAddress;
        key = issueUrl;
        isBountyOpen = true;
        expiresAt += expiresIn + now;
        totalBounty += msg.value;
        owner = msg.sender;
        voterAddresses = voters;
        requiredNumberOfVotes = (voterAddresses.length / 2 )  + 1;
        for (uint256 i=0; i < voterAddresses.length; i++ ){
            eligibleVotersAddresses[voterAddresses[i]] = true;
        }
        contributions[msg.sender] += msg.value;
    }
    function addToBounty() public payable bountyOpen {
        contributions[msg.sender] += msg.value;
        totalBounty += msg.value;
        parent.updateBountyAmount(key, totalBounty);
    }
    function vote(address addr) public isEligibleVoter bountyOpen votedOnce(msg.sender, addr){
        votes[addr] += 1;
        if (votes[addr] == 1 ) {
          // New PR vote
          PRS.push(addr);
          totalPRS++;
        }
        addVotePair(msg.sender, addr);
        doCount(addr);
    }
    function doCount(address addr) private {
        if (votes[addr] >= requiredNumberOfVotes) {
            addr.transfer(totalBounty);
            isBountyOpen = false;
        }
    }
    function addVotePair(address voter, address hunter) private {
        hasVotedToAddress[keccak256(voter, hunter)] = true;
    }
    function hasVoted(address voter, address hunter) private constant returns (bool) {
        return hasVotedToAddress[keccak256(voter, hunter)];
    }
    function getAllPRS() public constant returns (address[]) {
      return PRS;
    }

}

pragma solidity ^0.4.2;

contract GitBountyCreator {
    struct Bounty {
        address addr;
        uint256 totalVotes;
        uint256 totalVoters;
        uint256 payoutAmount;
    }
    mapping (string => Bounty) private bounties;
    modifier isChild(string key) {
        require(bounties[key].addr == msg.sender);
        _;
    }
    function createBounty(string issueUrl, address[] voters,uint256  expiresIn ) public payable returns(address) {
        GitBounty b = new GitBounty(issueUrl, voters, expiresIn, this);
        bounties[issueUrl] = Bounty({
            addr: b,
            totalVotes: 0,
            totalVoters: voters.length,
            payoutAmount: 0
        });
        b.addToBounty.value(msg.value)();
        return b;
    }
    function getBounty(string key) public constant returns (address, uint256, uint256, uint256) {
        return (bounties[key].addr, bounties[key].totalVotes, bounties[key].totalVoters, bounties[key].payoutAmount);
    }
    function updateBountyAmount(string key, uint256 newAmount) public isChild(key) {
        Bounty storage b = bounties[key];
        b.payoutAmount = newAmount;
        bounties[key] = b;
    }
    function updateVoteProgress(string key, uint256 newTotalVotes) public isChild(key) {
      Bounty storage b = bounties[key];
      b.totalVotes = newTotalVotes;
      bounties[key] = b;
    }
}

contract GitBounty {
    GitBountyCreator public parent;
    string public key;
    address public owner;
    uint256 public totalBounty;
    uint256 public expiresAt;
    address[] public voterAddresses;
    uint256 public totalVotes;
    mapping (address => uint256) public contributions;
    mapping (address => bool) public eligibleVotersAddresses;
    mapping (address => uint256) public votes;
    address[] public PRS;
    uint256 public totalPRS;
    uint256 public requiredNumberOfVotes;
    bool public isBountyOpen;
    mapping (bytes32 => bool) private hasVotedToAddress;

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    modifier isEligibleVoter {
        require(eligibleVotersAddresses[msg.sender]);
        _;
    }
    modifier bountyOpen {
        require(isBountyOpen);
        _;
    }
    modifier votedOnce(address voter, address hunter) {
        require(!hasVoted(voter, hunter));
        _;
    }
    function GitBounty(string issueUrl, address[] voters,uint256  expiresIn, GitBountyCreator parentAddress ) public payable {
        parent = parentAddress;
        key = issueUrl;
        isBountyOpen = true;
        expiresAt += expiresIn + now;
        totalBounty += msg.value;
        owner = msg.sender;
        voterAddresses = voters;
        requiredNumberOfVotes = (voterAddresses.length / 2 )  + 1;
        for (uint256 i=0; i < voterAddresses.length; i++ ){
            eligibleVotersAddresses[voterAddresses[i]] = true;
        }
        contributions[msg.sender] += msg.value;
    }
    function addToBounty() public payable bountyOpen {
        contributions[msg.sender] += msg.value;
        totalBounty += msg.value;
        parent.updateBountyAmount(key, totalBounty);
    }
    function vote(address addr) public isEligibleVoter bountyOpen votedOnce(msg.sender, addr){
        votes[addr] += 1;
        if (votes[addr] == 1 ) {
          // New PR vote
          PRS.push(addr);
          totalPRS++;
        }
        addVotePair(msg.sender, addr);
        doCount(addr);
    }
    function doCount(address addr) private {
        if (votes[addr] >= requiredNumberOfVotes) {
            addr.transfer(totalBounty);
            isBountyOpen = false;
        }
    }
    function addVotePair(address voter, address hunter) private {
        hasVotedToAddress[keccak256(voter, hunter)] = true;
    }
    function hasVoted(address voter, address hunter) private constant returns (bool) {
        return hasVotedToAddress[keccak256(voter, hunter)];
    }

}


solidity:)

solidity:)

contract Forum {

  address public owner;
  string public name;

  struct Topic {
    string title;
    string content;

    address author;
  }

  mapping ( uint => Topic ) topics;
  uint public numTopics;

  function Forum( string _name ) {
    name = _name;
    owner = msg.sender;

    numTopics = 0;
  }

  function addTopic( string title, string content ) public returns ( uint topicId ) {

    // topics.push( Topic( title, content, msg.sender  ) );
    topicId = numTopics++;
  }

}

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