pragma solidity ^0.6.4; library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; return c; } function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } contract Ecommerce { using SafeMath for uint256; enum UserType{noUser,buyer,seller} address[] admins; uint256 MIN_TIME = 3 minutes; uint256 MAX_TIME = 6 minutes; // uint256 MIN_TIME = 30 days; // uint256 MAX_TIME = 60 days; struct UserStruct{ string name; string location; string email; uint256 mobile; UserType userType; } struct DisputeStruct{ uint256 productId; uint256 accept; uint256 reject; uint256 count; mapping (uint256 => mapping (uint256 => address payable )) votedAdmin; bool isDisputeCleared; } struct ProductStruct{ string name; string description; uint256 price; uint256 amount; uint256 disputePrice; uint256 orderTime; address payable buyer; address payable seller; bool isOrdered; bool isShipped; bool confirmDelivery; } mapping (address => UserStruct) public user; mapping (uint256 => ProductStruct) public product; mapping (uint256 => DisputeStruct) public dispute; mapping (address => uint256[]) productList; mapping (address => mapping (uint256 => bool)) isVoted; uint256 public P_ID; uint256 public D_ID; constructor (address[] memory _admins) public { require(_admins.length.mod(2) != 0, "Number of admins should be Odd"); admins = _admins; } function UserRegistraion( string calldata _name, string calldata _location, string calldata _email, uint256 _mobile,UserType _userType ) external { require(uint(user[msg.sender].userType) == 0,'Already Registered'); user[msg.sender]= UserStruct(_name,_location,_email,_mobile,_userType); } function SellProduct( string calldata _name, string calldata _description, uint256 _price) external payable { require(uint(user[msg.sender].userType) == 2,'Invalid User'); require(msg.value == _price.div(100),'Insuffent Dispute value'); P_ID++; product[P_ID].name= _name; product[P_ID].description= _description; product[P_ID].disputePrice= msg.value; product[P_ID].price= _price; product[P_ID].seller= msg.sender; productList[msg.sender].push(P_ID); } function BuyProduct(uint256 _P_ID) external payable { require(uint(user[msg.sender].userType) == 1,'Invalid User'); require(_P_ID > 0,'Invalid Product Id'); require(product[_P_ID].isOrdered == false,'Product Already Ordered'); require(msg.value == product[_P_ID].disputePrice.add(product[_P_ID].price),'Insuffient Ethereum'); product[_P_ID].buyer = msg.sender; product[_P_ID].amount = msg.value.sub(product[_P_ID].disputePrice); product[_P_ID].disputePrice += msg.value.sub(product[_P_ID].amount); product[_P_ID].orderTime = now; product[_P_ID].isOrdered = true; } function ProductShipping(uint256 _P_ID) external { require(uint(user[msg.sender].userType) == 2,'Invalid User'); require(product[_P_ID].seller == msg.sender,'Must be a Seller'); require(product[_P_ID].isOrdered == true,'Product is not Ordered'); require(product[_P_ID].isShipped == false,'Product is already Shipped'); product[_P_ID].isShipped = true; } function ConfirmDelivery(uint256 _P_ID) external { require(uint(user[msg.sender].userType) == 1,'Invalid User'); require(product[_P_ID].buyer == msg.sender,'Must be a Buyer'); require(product[_P_ID].isShipped == true,'Product is Not Shipped'); product[_P_ID].seller.transfer(product[_P_ID].amount); product[_P_ID].buyer.transfer(product[_P_ID].disputePrice.div(2)); product[_P_ID].seller.transfer(product[_P_ID].disputePrice.div(2)); product[_P_ID].amount =0; product[_P_ID].disputePrice = 0; product[_P_ID].confirmDelivery = true; } function ClaimAmount(uint256 _P_ID) external { require(uint(user[msg.sender].userType) == 1,'Invalid User'); require(now > MAX_TIME + product[_P_ID].orderTime ,'after 60 days only'); require(product[_P_ID].buyer == msg.sender,'Must be a Buyer'); product[_P_ID].buyer.transfer(product[_P_ID].amount); product[_P_ID].buyer.transfer(product[_P_ID].disputePrice.div(2)); product[_P_ID].amount = 0; product[_P_ID].orderTime = 0; product[_P_ID].disputePrice = product[_P_ID].disputePrice.div(2); product[_P_ID].buyer = address(0); product[_P_ID].isOrdered = false; product[_P_ID].isShipped = false; } function DisputeCreation(uint256 _P_ID) external { require( now > MIN_TIME + product[_P_ID].orderTime && ( now < MAX_TIME + product[_P_ID].orderTime ) ,'inbetween 30 to 60 days only'); require(uint(user[msg.sender].userType) == 2,'Invalid User'); require(product[_P_ID].seller == msg.sender,'Must be a Seller'); require(product[_P_ID].isShipped == true && product[_P_ID].confirmDelivery == false,'Product is either not Shipped or already Confirmed'); D_ID++; dispute[D_ID].productId = _P_ID; } function DisputeVoting(uint256 _D_ID,uint256 _vote) external { require(indexOf(admins,msg.sender) != uint256(-1),'Not An Admin'); require(isVoted[msg.sender][_D_ID] == false,'Admin has already Voted'); require(dispute[_D_ID].isDisputeCleared == false,'Dispute Already Cleared'); require(dispute[_D_ID].count <= admins.length,'Maximum Vote Reached'); if (_vote == 2) { dispute[_D_ID].accept++; } if(_vote == 1){ dispute[_D_ID].reject++; } dispute[_D_ID].count++; dispute[_D_ID].votedAdmin[dispute[_D_ID].count][_vote] = msg.sender; isVoted[msg.sender][_D_ID] = true; if (dispute[D_ID].count == admins.length) { if (dispute[_D_ID].accept > dispute[_D_ID].reject) { // buyer wins product[dispute[_D_ID].productId].buyer.transfer(product[dispute[_D_ID].productId].amount); product[dispute[_D_ID].productId].buyer.transfer(product[dispute[_D_ID].productId].disputePrice.div(2)); product[dispute[_D_ID].productId].disputePrice = product[dispute[_D_ID].productId].disputePrice.div(2); product[dispute[_D_ID].productId].buyer = address(0); product[dispute[_D_ID].productId].isOrdered = false; product[dispute[_D_ID].productId].isShipped = false; PayAdmin(_D_ID,2); } else { // seller wins product[dispute[_D_ID].productId].seller.transfer(product[dispute[_D_ID].productId].amount); product[dispute[_D_ID].productId].seller.transfer(product[dispute[_D_ID].productId].disputePrice.div(2)); product[dispute[_D_ID].productId].disputePrice = product[dispute[_D_ID].productId].disputePrice.div(2); product[dispute[_D_ID].productId].confirmDelivery = true; PayAdmin(_D_ID,1); } product[dispute[_D_ID].productId].amount = 0; product[dispute[_D_ID].productId].disputePrice = 0; dispute[_D_ID].isDisputeCleared = true; } } function PayAdmin(uint256 _D_ID,uint256 _vote) internal { uint256 count; if (_vote == 2) { count = dispute[_D_ID].accept; } if (_vote == 1) { count = dispute[_D_ID].reject; } for(uint256 i = 1;i<=admins.length;i++){ if (dispute[_D_ID].votedAdmin[i][_vote] != address(0)) { dispute[_D_ID].votedAdmin[i][_vote].transfer(product[dispute[_D_ID].productId].disputePrice.div(count)); } } } function indexOf(address[] memory self, address value) internal pure returns (uint256) { for (uint256 i = 0; i < self.length; i++) if (self[i] == value) return i; return uint256(-1); } //Read function ProductList() external view returns(uint256[] memory List){ return(productList[msg.sender]); } }
0.6.4