pragma solidity ^0.4.19; /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a * b; assert(a == 0 || c / a == b); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } } /** * @title Ownable contract */ contract Ownable { address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ function Ownable() public { owner = msg.sender; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(msg.sender == owner); _; } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { require(newOwner != address(0)); OwnershipTransferred(owner, newOwner); owner = newOwner; } } /** * @title SupplyBusiness contract */ contract SupplyBusiness is Ownable { using SafeMath for uint256; /** * Business struct */ struct Business { uint _index; string _name; address _address; } /** * Business router mapping */ mapping(bytes32 => Business) private business; /** * Business name array */ bytes32[] private businessIndice; event AddBusiness(string _name, address indexed _address); event GetBusiness(string _name, address indexed _address); /** * check if business exists in db */ function isExist(string name) public constant returns (bool) { if(businessIndice.length == 0) return false; bytes32 _name = stringToBytes32(name); return (businessIndice[business[_name]._index] == _name); } /** * add new business to db */ function addBusiness(string name, address contractAddress) onlyOwner public returns (bool) { require(isExist(name) == false); bytes32 _name = stringToBytes32(name); businessIndice.push(_name); business[_name]._index = businessIndice.length - 1; business[_name]._name = name; business[_name]._address = contractAddress; AddBusiness(name, contractAddress); return true; } /** * remove existing business from db */ function removeBusiness(string name) onlyOwner public returns (bool) { require(isExist(name) == true); bytes32 _name = stringToBytes32(name); uint rowToDelete = business[_name]._index; bytes32 keyToMove = businessIndice[businessIndice.length-1]; businessIndice[rowToDelete] = keyToMove; business[keyToMove]._index = rowToDelete; businessIndice.length = businessIndice.length.sub(1); return true; } /** * get existing business from db */ function getBusiness(string name) onlyOwner public constant returns (address contractAddress) { require(isExist(name) == true); bytes32 _name = stringToBytes32(name); GetBusiness(name, business[_name]._address); return business[_name]._address; } /** * edit existing business in db */ function editBusiness(string name, address contractAddress) onlyOwner public returns (bool) { require(isExist(name) == true); bytes32 _name = stringToBytes32(name); business[_name]._address = contractAddress; return true; } /** * get all count of businesses from db */ function getBusinessCount() public constant returns (uint count) { return businessIndice.length; } /** * upload product normally indexed by product labelNo */ function uploadProduct(string bizName, string labelNo, string id, string name, string shipmentId, string countryOrigin, string expireDate, string sealTagLogDate) public returns (bool) { require(isExist(bizName)); address bizAddr = getBusiness(bizName); ProductTrack product = ProductTrack(bizAddr); product.addProduct(labelNo, id, name, shipmentId, countryOrigin, expireDate, sealTagLogDate); } /** * get product info by product labelNo */ function getProductDetails(string bizName, string labelNo) public constant returns (string id, string name, string shipmentId, string countryOrigin, string expireDate, string sealTagLogDate) { require(isExist(bizName)); address bizAddr = getBusiness(bizName); ProductTrack product = ProductTrack(bizAddr); (labelNo , id, name, shipmentId, countryOrigin, expireDate, sealTagLogDate) = product.getProduct(labelNo); } /** * get product tracking info by product labelNo */ function getProductTracking(string bizName, string labelNo) public constant returns (bytes32 txHash1, uint256 txTimestamp1, bytes32 txHash2, uint256 txTimestamp2, bytes32 txHash3, uint256 txTimestamp3) { require(isExist(bizName)); address bizAddr = getBusiness(bizName); ProductTrack product = ProductTrack(bizAddr); (txHash1, txTimestamp1, txHash2, txTimestamp2, txHash3, txTimestamp3) = product.getProductTracking(labelNo); } /** * get product count with business name */ function getProductCount(string bizName) public constant returns (uint count) { require(isExist(bizName)); address bizAddr = getBusiness(bizName); ProductTrack product = ProductTrack(bizAddr); return product.getProductCount(); } /** * check if product is exist with labelNo in business name */ function isExistProduct(string bizName, string labelNo) public constant returns (bool) { require(isExist(bizName)); address bizAddr = getBusiness(bizName); ProductTrack product = ProductTrack(bizAddr); return product.isExist(labelNo); } /** * convert string to bytes32 */ function stringToBytes32(string memory source) private returns (bytes32 result) { if (isEmptyString(source)) return 0x0; assembly { result := mload(add(source, 32)) } } /** * check if string is empty */ function isEmptyString(string str) private constant returns (bool) { bytes memory tempEmptyStringTest = bytes(str); if (tempEmptyStringTest.length == 0) { return true; } return false; } } /** * @title ProductTrack contract */ contract ProductTrack is Ownable { using SafeMath for uint256; /** * Product Tracking struct */ struct Product { uint _index; string _labelNo; string _id; string _name; string _shipmentId; string _countryOrigin; string _expireDate; string _sealTagLogDate; bytes32 _txHash1; uint256 _txTimestamp1; bytes32 _txHash2; uint256 _txTimestamp2; bytes32 _txHash3; uint256 _txTimestamp3; } /** * Business name */ string public BUSINESSNAME; /** * Product DB indexed by labelNo normally */ mapping (bytes32 => Product) private productDB; /** * Product label key array */ bytes32[] private labels; /** * */ function ProductTrack(string bizName) public { BUSINESSNAME = bizName; } /** * check if product exists in db */ function isExist(string labelNo) public constant returns (bool) { if(labels.length == 0) return false; bytes32 _labelNo = stringToBytes32(labelNo); return (labels[productDB[_labelNo]._index] == _labelNo); } /** * add new product in db */ function addProduct(string labelNo, string id, string name, string shipmentId, string countryOrigin, string expireDate, string sealTagLogDate) public returns (bool) { require(isExist(labelNo) == false); bytes32 _labelNo = stringToBytes32(labelNo); labels.push(_labelNo); productDB[_labelNo]._index = labels.length - 1; productDB[_labelNo]._labelNo = labelNo; productDB[_labelNo]._id = id; productDB[_labelNo]._name = name; productDB[_labelNo]._shipmentId = shipmentId; productDB[_labelNo]._countryOrigin = countryOrigin; productDB[_labelNo]._expireDate = expireDate; productDB[_labelNo]._sealTagLogDate = sealTagLogDate; productDB[_labelNo]._txTimestamp1 = block.timestamp; return true; } /** * remove existing product by labelNo from db */ function removeProduct(string labelNo) onlyOwner public returns (bool) { require(isExist(labelNo) == true); bytes32 _labelNo = stringToBytes32(labelNo); uint rowToDelete = productDB[_labelNo]._index; bytes32 keyToMove = labels[labels.length-1]; labels[rowToDelete] = keyToMove; productDB[keyToMove]._index = rowToDelete; labels.length = labels.length.sub(1); return true; } /** * get existing product details by labelNo from db except tx info */ function getProduct(string labelNo) public constant returns (string _labelNo, string _id, string _name, string _shipmentId, string _countryOrigin, string _expireDate, string _sealTagLogDate) { require(isExist(labelNo) == true); bytes32 __labelNo = stringToBytes32(labelNo); Product memory pt = productDB[__labelNo]; return(pt._labelNo, pt._id, pt._name, pt._shipmentId, pt._countryOrigin, pt._expireDate, pt._sealTagLogDate); } /** * get existing product tx info by labelNo from db */ function getProductTracking(string labelNo) public constant returns (bytes32 _txHash1, uint256 _txTimestamp1, bytes32 _txHash2, uint256 _txTimestamp2, bytes32 _txHash3, uint256 _txTimestamp3) { require(isExist(labelNo) == true); bytes32 __labelNo = stringToBytes32(labelNo); Product memory pt = productDB[__labelNo]; return(pt._txHash1, pt._txTimestamp1, pt._txHash2, pt._txTimestamp2, pt._txHash3, pt._txTimestamp3); } /** * edit existing product with expireDate as Point 2 */ function updateExpireDate(string labelNo, string value) public returns (bool) { require(isExist(labelNo) == true); bytes32 _labelNo = stringToBytes32(labelNo); productDB[_labelNo]._expireDate = value; productDB[_labelNo]._txTimestamp2 = block.timestamp; return true; } /** * edit existing product with sealTagLogDate as Point 3 */ function updateSealTagLogDate(string labelNo, string value) public returns (bool) { require(isExist(labelNo) == true); bytes32 _labelNo = stringToBytes32(labelNo); productDB[_labelNo]._sealTagLogDate = value; productDB[_labelNo]._txTimestamp3 = block.timestamp; return true; } /** * update transaction hash with specific txHash for Point 1, 2, 3 */ function updateTxHash(string labelNo, string point, bytes32 txHash) public returns (bool) { require(isExist(labelNo) == true); bytes32 _labelNo = stringToBytes32(labelNo); if(keccak256(point) == keccak256("point1")) { productDB[_labelNo]._txHash1 = txHash; } else if(keccak256(point) == keccak256("point2")) { productDB[_labelNo]._txHash2 = txHash; } else if(keccak256(point) == keccak256("point3")) { productDB[_labelNo]._txHash3 = txHash; } return true; } /** * edit existing product with specific data in db */ function editProduct(string labelNo, string key, string value) public returns (bool) { require(isExist(labelNo) == true); bytes32 _labelNo = stringToBytes32(labelNo); if(keccak256(key) == keccak256("id")) productDB[_labelNo]._id = value; else if(keccak256(key) == keccak256("name")) productDB[_labelNo]._name = value; else if(keccak256(key) == keccak256("shipmentId")) productDB[_labelNo]._shipmentId = value; else if(keccak256(key) == keccak256("countryOrigin")) productDB[_labelNo]._countryOrigin = value; return true; } /** * get all count of businesses from db */ function getProductCount() public constant returns (uint count) { return labels.length; } /** * constructor with business name of contract */ function setBusinessName(string bizName) onlyOwner public constant { require(isEmptyString(bizName) == false); BUSINESSNAME = bizName; } /** * convert string to bytes32 */ function stringToBytes32(string memory source) private returns (bytes32 result) { if (isEmptyString(source)) { return 0x0; } assembly { result := mload(add(source, 32)) } } /** * check if string is empty */ function isEmptyString(string str) private constant returns (bool) { bytes memory tempEmptyStringTest = bytes(str); if (tempEmptyStringTest.length == 0) { return true; } return false; } }
0.4.24