Skip to content

Instantly share code, notes, and snippets.

@Doctordrayfocus
Last active December 18, 2021 23:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Doctordrayfocus/8177bd086097ace3c5c6429bba0182d5 to your computer and use it in GitHub Desktop.
Save Doctordrayfocus/8177bd086097ace3c5c6429bba0182d5 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;
contract Logistics {
// The address of the account that launched the smart contract
address initiator;
// state data for each member registered on the contract
struct memberState {
uint balance;
uint reputation;
}
// state data for each delivery transactions executed through the smart contract
struct deliveryState {
uint deliveryFee;
uint status;
uint hashedDeliveryDetails;
address owner;
address assistingMember;
uint index;
}
// An array to store current available deliveries
uint[] availableDeliveries;
// mapping are live arrays with key and value pairs
mapping (address => memberState) public membersData;
mapping (address => uint) members;
mapping (uint => deliveryState) public deliveryData;
// modifiers
modifier onlyMember{
require(members[msg.sender] == 1);
_;
}
// errors
error notAuthorized(string reason);
error insufficientFee(string reason, uint registrationFee);
constructor() payable {
initiator = msg.sender;
// here we will register the initiator of the contract as a member
members[msg.sender] = 1;
membersData[msg.sender].balance = msg.value;
membersData[msg.sender].reputation = 10;
}
// This is a public function to the current available deliveries
function getAvailableDeliveries() public view returns( uint[] memory) {
return availableDeliveries;
}
// A private function remove delivery from current available deliveries
function removeFromAvailableDeliveries(uint index) private {
if (index >= availableDeliveries.length) return;
for (uint i = index; i < availableDeliveries.length-1; i++){
availableDeliveries[i] = availableDeliveries[i+1];
}
delete availableDeliveries[availableDeliveries.length-1];
}
// A private function add delivery from current available deliveries
function addToAvailableDelivery(uint hashedDeliveryDetails) private {
deliveryData[hashedDeliveryDetails].index = availableDeliveries.length;
availableDeliveries.push(hashedDeliveryDetails);
}
function register() public payable {
uint registrationFee = msg.value;
address newMember = msg.sender;
if (registrationFee < 10)
revert insufficientFee({
reason: "Ether value is less that the required registration fee",
registrationFee: 10
});
members[newMember] = 1;
membersData[newMember].balance = msg.value;
membersData[newMember].reputation = 10;
}
function requestForDelivery(uint hashedDeliveryDetails) onlyMember public payable {
if(members[msg.sender] != 1)
revert notAuthorized({
reason: "Only members of this contract can request for delivery"
});
uint senderReputation = membersData[msg.sender].reputation;
if(senderReputation < 6)
revert notAuthorized({
reason: "You have a low reputation, complete more deliveries to increase your reputations"
});
deliveryData[hashedDeliveryDetails].deliveryFee = msg.value;
deliveryData[hashedDeliveryDetails].status = 0;
deliveryData[hashedDeliveryDetails].hashedDeliveryDetails = hashedDeliveryDetails;
deliveryData[hashedDeliveryDetails].owner = msg.sender;
addToAvailableDelivery(hashedDeliveryDetails);
membersData[msg.sender].balance = membersData[msg.sender].balance + msg.value;
}
function respondToDeliveryRequest(uint hashedDeliveryDetails) onlyMember public {
if(members[msg.sender] != 1)
revert notAuthorized({
reason: "Only members of this contract can respond to delivery request"
});
uint memberReputation = membersData[msg.sender].reputation;
if(memberReputation < 1)
revert notAuthorized({
reason: "You have exhausted your reputations"
});
uint deliveryStatus = deliveryData[hashedDeliveryDetails].status;
if(deliveryStatus != 0)
revert notAuthorized({
reason: "This delivery is no longer available"
});
deliveryData[hashedDeliveryDetails].status = 1;
deliveryData[hashedDeliveryDetails].assistingMember = msg.sender;
removeFromAvailableDeliveries(deliveryData[hashedDeliveryDetails].index);
}
function markDeliveryAsCompleted(uint hashedDeliveryDetails) onlyMember public {
if(members[msg.sender] != 1) {
revert notAuthorized({
reason: "Only members of this contract can update this delivery"
});
}
address assistingMember = deliveryData[hashedDeliveryDetails].assistingMember;
if(assistingMember != msg.sender) {
revert notAuthorized({
reason: "You don't have access to update this delivery"
});
}
deliveryData[hashedDeliveryDetails].status = 2;
}
function markDeliveryAsCancled(uint hashedDeliveryDetails) onlyMember public {
if(members[msg.sender] != 1) {
revert notAuthorized({
reason: "Only members of this contract can update this delivery"
});
}
address assistingMember = deliveryData[hashedDeliveryDetails].assistingMember;
if(assistingMember != msg.sender && msg.sender != initiator) {
revert notAuthorized({
reason: "You don't have access to update this delivery"
});
}
deliveryData[hashedDeliveryDetails].status = 0;
addToAvailableDelivery(hashedDeliveryDetails);
if (assistingMember == msg.sender) {
membersData[msg.sender].reputation = membersData[msg.sender].reputation - 5;
}
if (msg.sender == initiator) {
membersData[msg.sender].reputation = membersData[msg.sender].reputation - 6;
}
}
function markDeliveryAsConfirmed(uint hashedDeliveryDetails) onlyMember public {
if(members[msg.sender] != 1) {
revert notAuthorized({
reason: "Only members of this contract can update this delivery"
});
}
address deliveryOwner = deliveryData[hashedDeliveryDetails].owner;
if(deliveryOwner != msg.sender && msg.sender != initiator) {
revert notAuthorized({
reason: "You don't have access to confirm this delivery"
});
}
deliveryData[hashedDeliveryDetails].status = 3;
address assistingMember = deliveryData[hashedDeliveryDetails].assistingMember;
uint deliveryFee = deliveryData[hashedDeliveryDetails].deliveryFee;
membersData[deliveryOwner].balance = membersData[deliveryOwner].balance - deliveryFee;
membersData[assistingMember].reputation = membersData[assistingMember].reputation + 3;
membersData[assistingMember].balance = membersData[assistingMember].balance + deliveryFee;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment