Pastebin
API
tools
faq
paste
Login
Sign up
Please fix the following errors:
New Paste
Syntax Highlighting
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; // Notes: // - Use integer values of type uint where the number is alway +ve, like ids. // - Use integer values of type int for any value from microcontrollers since -1 is being used as an alternative to null, which is not supported in Solidity. contract order_fulfillment { // This is the address of the smart contract owner, the buyer in this case. address public owner; // This modifier is applied on all functions so only owner or allowed participants can call the contract modifier restrictedUsers() { // require(Participants[msg.sender].contract_access == true, "Unauthorized user."); require(msg.sender == owner || Participants[msg.sender].contract_access == true, "Unauthorized"); _; } // This modifier is applied on functions like adding/removing participants modifier onlyOwner() { require(msg.sender == owner, "Not owner"); _; } // The data structures in the Smart Contract will be similar but not exactly the same as the database. // In the Smart Contract only require data that is used for penalty calculations. struct Participant { uint8 id; string name; string role; address account_address; bool contract_access; } // Mapping (collection) of participants with the account_address as the key. // Making it public automatically provides a getter. mapping(address => Participant) public Participants; // Mapping (collection) of participant's private keys with their account address as the key mapping(address => string) PrivateKeys; // Mapping the roles to participant addresses, a redundant mapping to validate that // two participants are not mapped to the same role. mapping(string => address) public RoleParticipant; // Order related structs that hold expected values and penalties for order attributes. // Note that fixed point numbers are not well supported so stay with integers. // Adjust all number values accordingly. // Order items. struct item_struct { string description; int order_quantity; string uom; int penalty_amount; // amount is in wei } // Assigned vehicle. struct vehicle_struct { string assigned_vehicle_regn_num; int penalty_amount; // amount is in wei } // Departure and Arrival times. struct schedule_struct { int expected_departure_timestamp; int expected_arrival_timestamp; int penalty_amount; // amount is in wei } // Transport condition parameter values. // Keep all values +ve. struct transport_condition_parameter_struct { string name; //temperature, humidity, etc int min_value; int max_value; int penalty_amount; // amount is in wei } // The main order stuct which will be created/updated from the web app. // This structure will be updated by the buyer, seller & transporter in 3 steps // using the following functions: // - createOrder() // - updateSellerOrder() // - updateTransporterOrder() struct order_struct { uint8 order_id; address[] participant_addresses; int buyer_to_seller_amount; int seller_to_transporter_amount; item_struct item; schedule_struct schedule; transport_condition_parameter_struct[] transport_condition_parameters; vehicle_struct vehicle; string status; } // Mapping (collection) of orders with the order_id as the key. mapping(uint8 => order_struct) orders; // This nested struct approach is to support sensors recording multiple parameters. // For example: Temperature and Humidity, Latitude and Longitude. // The value will be -1 if not received, hence datatype is kept as int. struct sensor_parameter_struct { string name; int value; // This is assuming all sensor data will be integers. } struct sensor_data_struct { uint8 sensor_id; sensor_parameter_struct[] sensor_parameters; } // This struct will support multiple sensors. struct microcontroller_data_struct { //Data coming from the microcontroller uint8 microcontroller_id; uint timestamp; sensor_data_struct[] sensor_data; } // For simplicity, all single value data will be stored individually. // Multi-valued data (only transport conditions in this case) will be // stored in the microcontroller_data array. // This structure will be updated by the data coming from microcontrollers // using the functions below // - receiveANPRData // - receiveScheduleData // - receiveQuantityData // - receiveTransportConditionsData struct incoming_data_struct { string loading_vehicle_regn_num; string unloading_vehicle_regn_num; int departure_timestamp; int arrival_timestamp; int loaded_quantity; // This is to calculate any difference in unloaded quantity. int unloaded_quantity; microcontroller_data_struct[] microcontroller_data; } // Mapping of incoming_data_struct with order_id in the contract scope. mapping(uint8 => incoming_data_struct) incoming_data; // Structure for penalties. // Whenever any microcontroller data is received penalties (if any) // are immediately calculated for the received data and // stored in the below struct struct penalty_struct { address participant_address; int penalty_amount; // amount is in wei string penalty_parameter_name; // temperature, humidity, etc } // Mapping of penalty_struct with order_id in the contract scope. // Every time penalty for a parameter is calculated // It is appended in this mapping // Maps Order ID to an Array of penalties mapping(uint8 => penalty_struct[]) penalties; // Constructor is automatically called when the contract is being deployed constructor() { // Account deploying the contract is stored as the owner // msg.sender is a way to reference the account doing a transaction owner = msg.sender; } /* Functions to receive and save data coming in from the microcontrollers. */ // The data will be received as a microcontroller_data_struct. // Multi-value data will be pushed into the microcontroller_data array. // Single value data will be updated in the variables. // ANPR data from Loading and Unloading vehicle locations. // Here the data is coming as a single variable and not in any particular structure function receiveANPRData( uint8 order_id, string memory vehicle_regn_num, string memory vehicle_location // 'Loading' or 'Unloading' ) external restrictedUsers { // There is no direct string comparison in Solidity. // Convert to a hash and compare as below. if (sha256(bytes(vehicle_location)) == sha256(bytes("Loading"))){ // store vehicle regn number in loading location variable (seller location) incoming_data[order_id].loading_vehicle_regn_num = vehicle_regn_num; } else if (sha256(bytes(vehicle_location)) == sha256(bytes("Unloading"))){ // store vehicle regn number in unloading location variable (buyer location) incoming_data[order_id].unloading_vehicle_regn_num = vehicle_regn_num; } // Call the calculate penalties function only if the received vehicle_regn_num is not null (-1) // If null value is received then don't calculate penalties if (sha256(bytes(vehicle_regn_num)) != "-1"){ // Calculate penalties for incorrect vehicle used calculateVehiclePenalties(order_id, vehicle_location); } } // Arrival and Departure time data. // Incoming data is coming in the form of microcontroller data structure declared above function receiveScheduleData( uint8 order_id, string calldata schedule_type, // 'Departure' or 'Arrival' microcontroller_data_struct calldata microcontroller_data ) external restrictedUsers { if (sha256(bytes(schedule_type)) == sha256(bytes("Departure"))){ // timestamp is coming from seller location incoming_data[order_id].departure_timestamp = microcontroller_data.sensor_data[0].sensor_parameters[0].value; orders[order_id].status = "Departed"; // update order status } else if (sha256(bytes(schedule_type)) == sha256(bytes("Arrival"))){ // timestamp is coming from buyer location incoming_data[order_id].arrival_timestamp = microcontroller_data.sensor_data[0].sensor_parameters[0].value; orders[order_id].status = "Arrived"; // update order status } // Call the calculate penalties function only if the received timestamp is valid // If null value (-1) is received then don't calculate penalties if (microcontroller_data.sensor_data[0].sensor_parameters[0].value != -1){ // Calculate penalties for variation in departure or arrival time calculateSchedulePenalties(order_id, schedule_type); } } // Loaded and Unloaded quantity data. // Incoming data is coming in the form of microcontroller data structure declared above function receiveQuantityData( uint8 order_id, string calldata quantity_stage, // 'Loaded' or 'Unloaded' microcontroller_data_struct calldata microcontroller_data ) external restrictedUsers { if (sha256(bytes(quantity_stage)) == sha256(bytes("Loaded"))){ // quantity reading is coming from the microcontroller inside the delivery vehicle incoming_data[order_id].loaded_quantity = microcontroller_data.sensor_data[0].sensor_parameters[0].value; orders[order_id].status = "Loaded"; // Call the calculate penalties function only if the received quantity is valid // If null value (-1) is received then don't calculate penalties if (incoming_data[order_id].loaded_quantity != -1){ // Calculating quantity penalties calculateQuantityPenalties(order_id, quantity_stage); } } else if (sha256(bytes(quantity_stage)) == sha256(bytes("Unloaded"))){ // quantity reading is coming from the buyer location orders[order_id].status = "Unloaded"; incoming_data[order_id].unloaded_quantity = microcontroller_data.sensor_data[0].sensor_parameters[0].value; // Call the calculate penalties function only if the received quantity is valid // If null value (-1) is received then don't calculate penalties if (incoming_data[order_id].unloaded_quantity != -1){ // Calculating quantity penalties calculateQuantityPenalties(order_id, quantity_stage); } // The unloaded quantity data will be the last data received so trigger the final transport condition penalties calculation method. calculateTransportConditionPenalties(order_id); } } // Ongoing transport conditions, data for parameters specified in the order. // Incoming data is coming in the form of microcontroller data structure declared above function receiveTransportConditionsData( uint8 order_id, microcontroller_data_struct calldata microcontroller_data ) external restrictedUsers { incoming_data[order_id].microcontroller_data.push(microcontroller_data); } /* Functions for penalties calculation that will be called internally by smart contract functions. */ // Transporter sends a different vehicle than the one assigned when creating the order. // or if Transporter changes the vehicle during transit. // Penalize Transporter 100%. function calculateVehiclePenalties( uint8 order_id, string memory vehicle_location ) private restrictedUsers { address transporter_address = RoleParticipant["Transporter"]; // Get Transporter address since vehicle penalties can only apply to the transporter. // for(uint8 i = 0; i < orders[order_id].participant_addresses.length; i++){ // if (sha256(bytes(Participants[orders[order_id].participant_addresses[i]].role)) == sha256(bytes("Transporter"))){ // transporter_address = orders[order_id].participant_addresses[i]; // break; // } // } // Calculate penalty for unassigned vehicle at loading. if (sha256(bytes(vehicle_location)) == sha256(bytes("Loading"))) { if (sha256(bytes(orders[order_id].vehicle.assigned_vehicle_regn_num)) != sha256(bytes(incoming_data[order_id].loading_vehicle_regn_num))){ penalties[order_id].push( penalty_struct(transporter_address, orders[order_id].vehicle.penalty_amount, "Unassigned vehicle at loading.") ); } // Calculate penalty for unassigned vehicle at unloading. } else if(sha256(bytes(vehicle_location)) == sha256(bytes("Unloading"))) { if (sha256(bytes(incoming_data[order_id].loading_vehicle_regn_num)) != sha256(bytes(incoming_data[order_id].unloading_vehicle_regn_num))){ penalties[order_id].push( penalty_struct(transporter_address, orders[order_id].vehicle.penalty_amount, "Unassigned vehicle at unloading." ) ); } } } // Penalties for delays in departure and arrival. function calculateSchedulePenalties( uint8 order_id, string calldata schedule_type // 'Departure' or 'Arrival' ) private restrictedUsers { address seller_address = RoleParticipant["Seller"]; address transporter_address = RoleParticipant["Transporter"]; // Get Seller and Transporter address since departure delay penalties are divided equally. // Arrival delay penalties are on Transporter only. // for(uint8 i = 0; i < orders[order_id].participant_addresses.length; i++){ // if (sha256(bytes(Participants[orders[order_id].participant_addresses[i]].role)) == sha256(bytes("Seller"))){ // seller_address = orders[order_id].participant_addresses[i]; // } // else if (sha256(bytes(Participants[orders[order_id].participant_addresses[i]].role)) == sha256(bytes("Transporter"))){ // transporter_address = orders[order_id].participant_addresses[i]; // } // } // Calculate penalty after receiving departure time if (sha256(bytes(schedule_type)) == sha256(bytes("Departure"))) { if (incoming_data[order_id].departure_timestamp > orders[order_id].schedule.expected_departure_timestamp) { // Calculate penalties // Deviation is calculated on a per-hour basis by dividing difference between the actual and expected timestamp by 3600 // In Solidity a normal division is equivalent to floor division as decimal values are rounded down by default // This is because decimal values don't exist in Solidity int departure_time_variation = (incoming_data[order_id].departure_timestamp - orders[order_id].schedule.expected_departure_timestamp)/3600; // Dividing penalty amount by 2 as both seller and transporter will be penalised 50% int departure_time_penalty_amount = (departure_time_variation * orders[order_id].schedule.penalty_amount) / 2; // Retrieving the amount due to seller int amount_due_to_seller = orders[order_id].buyer_to_seller_amount - orders[order_id].seller_to_transporter_amount; // Checking if penalty amount is below or equal to the maximum capped amount (20% of amount due to seller) if (departure_time_penalty_amount <= (20*amount_due_to_seller)/100 ){ // Assign calculated penalty to Seller. penalties[order_id].push( penalty_struct(seller_address, departure_time_penalty_amount, "Delay in departure time." ) ); } // If penalty exceeds the 20% cap, then update the penalty amount to the capped amount else { // Assign capped penalty to Seller. penalties[order_id].push( penalty_struct(seller_address, (20*amount_due_to_seller)/100, "Delay in departure time." ) ); } // Checking if penalty amount is below or equal to the maximum capped amount (10% of amount due to transporter) if (departure_time_penalty_amount <= (10*orders[order_id].seller_to_transporter_amount)/100 ){ // Assign calculated penalty to Transporter. penalties[order_id].push( penalty_struct(transporter_address, departure_time_penalty_amount, "Delay in departure time." ) ); } // If penalty exceeds the 10% cap, then update the penalty amount to the capped amount else { // Assign capped penalty to Transporter. penalties[order_id].push( penalty_struct(transporter_address, (10*orders[order_id].seller_to_transporter_amount)/100, "Delay in departure time." ) ); } } } // Calculate penalty after receiving arrival time else if (sha256(bytes(schedule_type)) == sha256(bytes("Arrival"))) { if (incoming_data[order_id].arrival_timestamp > orders[order_id].schedule.expected_arrival_timestamp) { // Calculate penalties // Deviation is calculated on a per-hour basis by dividing difference between the actual and expected timestamp by 3600 // In Solidity a normal division is equivalent to floor division as decimal values are rounded down by default // This is because decimal values don't exist in Solidity int arrival_time_variation = (incoming_data[order_id].arrival_timestamp - orders[order_id].schedule.expected_arrival_timestamp)/3600; int arrival_time_penalty_amount = (arrival_time_variation * orders[order_id].schedule.penalty_amount); // Checking if penalty amount is below or equal to the maximum capped amount (10% of amount due to transporter) if (arrival_time_penalty_amount <= ((10*orders[order_id].seller_to_transporter_amount)/100) ){ // Assign calculated penalty to Transporter only. penalties[order_id].push( penalty_struct(transporter_address, arrival_time_penalty_amount, "Delay in arrival time." ) ); } // If penalty exceeds the 10% cap, then update the penalty amount to the capped amount else { // Assign capped penalty to Transporter. penalties[order_id].push( penalty_struct(transporter_address, ((10*orders[order_id].seller_to_transporter_amount)/100), "Delay in arrival time." ) ); } } } } // Penalties for incorrect quantities. // If the quantity loaded is less than the order quantity the Seller is penalized. // If the unloaded quantity is less than the loaded quantity the Seller is penalized. // The loaded quantity will have to be stored for this. function calculateQuantityPenalties( uint8 order_id, string calldata quantity_stage // 'Loaded' or 'Unloaded' ) private restrictedUsers { address seller_address = RoleParticipant["Seller"]; address transporter_address = RoleParticipant["Transporter"]; // Get Seller and Transporter address since quantity penalties may apply to either or both. // for(uint8 i = 0; i < orders[order_id].participant_addresses.length; i++){ // if (sha256(bytes(Participants[orders[order_id].participant_addresses[i]].role)) == sha256(bytes("Seller"))){ // seller_address = orders[order_id].participant_addresses[i]; // } // else if (sha256(bytes(Participants[orders[order_id].participant_addresses[i]].role)) == sha256(bytes("Transporter"))){ // transporter_address = orders[order_id].participant_addresses[i]; // } // } // Calculate penalties after receiving loaded quantity if (sha256(bytes(quantity_stage)) == sha256(bytes("Loaded"))) { if (incoming_data[order_id].loaded_quantity < orders[order_id].item.order_quantity) { // Calculate penalties int loaded_quantity_variation = orders[order_id].item.order_quantity - incoming_data[order_id].loaded_quantity; // Dividing penalty amount by 2 as both seller and transporter will be penalised 50% int loaded_quantity_penalty_amount = (loaded_quantity_variation * orders[order_id].item.penalty_amount); // Retrieving the amount due to seller int amount_due_to_seller = orders[order_id].buyer_to_seller_amount - orders[order_id].seller_to_transporter_amount; // Checking if penalty amount is below or equal to the maximum capped amount (100% of amount due to seller) if (loaded_quantity_penalty_amount <= amount_due_to_seller){ // Assign calculated penalty to Seller. penalties[order_id].push( penalty_struct(seller_address, loaded_quantity_penalty_amount, "Shortfall in loaded quantity." ) ); } // If penalty exceeds the 100% cap, then update the penalty amount to the capped amount else { // Assign capped penalty to Seller. penalties[order_id].push( penalty_struct(seller_address, amount_due_to_seller, "Shortfall in loaded quantity." ) ); } } // Calculate penalties after receiving unloaded quantity } else if (sha256(bytes(quantity_stage)) == sha256(bytes("Unloaded"))) { // Now compare with loaded quantity, not expected quantity. if (incoming_data[order_id].unloaded_quantity < incoming_data[order_id].loaded_quantity) { // Calculate penalties int unloaded_quantity_variation = incoming_data[order_id].loaded_quantity - incoming_data[order_id].unloaded_quantity; int unloaded_quantity_penalty_amount = (unloaded_quantity_variation * orders[order_id].item.penalty_amount); // Checking if penalty amount is below or equal to the maximum capped amount (100% of amount due to transporter) if (unloaded_quantity_penalty_amount <= orders[order_id].seller_to_transporter_amount){ // Assign calculated penalty to Transporter. penalties[order_id].push( penalty_struct(transporter_address, unloaded_quantity_penalty_amount, "Shortfall in unloaded quantity." ) ); } // If penalty exceeds the 100% cap, then update the penalty amount to the capped amount else { // Assign capped penalty to Transporter. penalties[order_id].push( penalty_struct(transporter_address, orders[order_id].seller_to_transporter_amount, "Shortfall in unloaded quantity." ) ); } } } } // This will be the final function and the order status can be updated to completed. // If transport condition parameters have deviations. // Penalize Transporter 100%. // For this the sensor data that is received at predefined frequency is used. // Stored in incoming_data['order_id'].microcontroller_data[] as sensor_data structs. function calculateTransportConditionPenalties(uint8 order_id) private restrictedUsers{ address transporter_address = RoleParticipant["Transporter"]; // Get Transporter address since vehicle penalties can only apply to it. // for(uint8 i = 0; i < orders[order_id].participant_addresses.length; i++){ // if (sha256(bytes(Participants[orders[order_id].participant_addresses[i]].role)) == sha256(bytes("Transporter"))){ // transporter_address = orders[order_id].participant_addresses[i]; // break; // } // } // Checking if the sensor reading stays in the expected range, otherwise transporter is penalised // Go through each expected parameter for (uint8 l = 0; l < orders[order_id].transport_condition_parameters.length; l++) { // Get the min and max values for this parameter. int expected_min = orders[order_id].transport_condition_parameters[l].min_value; int expected_max = orders[order_id].transport_condition_parameters[l].max_value; int penalty_amount = 0; int absolute_total_deviation = 0; // Penalty struct for each parameter. penalty_struct memory parameter_penalty = penalty_struct( transporter_address, penalty_amount, orders[order_id].transport_condition_parameters[l].name ); // For each expected parameter go through the list of microcontroller data received. // Find the parameter with the name that matches and check its value. // For each deviant reading update the holding penalty struct which will finally be pushed to the main penalties mapping for the order. // Go through all the microcontroller data received for the order. for (uint8 i = 0; i < incoming_data[order_id].microcontroller_data.length; i++) { // Go through all the sensor data for each microcontroller data item. for (uint8 j = 0; j < incoming_data[order_id].microcontroller_data[i].sensor_data.length; j++) { // For cleaner code copying the sensor data into a local variable sensor_data_struct memory temp_sensor_data = incoming_data[order_id].microcontroller_data[i].sensor_data[j]; // Go through all the parameters for each sensor data item. for (uint8 k = 0;k < temp_sensor_data.sensor_parameters.length;k++) { // string memory parameter_name = temp_sensor_data.sensor_parameters[k].name; if (sha256(bytes(orders[order_id].transport_condition_parameters[l].name)) == sha256(bytes(temp_sensor_data.sensor_parameters[k].name))) { // If sensor reading is null(-1) then apply penalty for a single unit of deviation if (temp_sensor_data.sensor_parameters[k].value == -1){ absolute_total_deviation += 1; } // If sensor reading is greater than the expected maximum value else if ((temp_sensor_data.sensor_parameters[k].value) > expected_max) { absolute_total_deviation += (temp_sensor_data.sensor_parameters[k].value) - expected_max; } // If sensor reading is less than the expected minimum value else if ((temp_sensor_data.sensor_parameters[k].value) < expected_min) { absolute_total_deviation += expected_min - (temp_sensor_data.sensor_parameters[k].value); } } } } } // Dividing the absolute total deviation by the length of microcontroller data array attribute int averaged_absolute_total_deviation = absolute_total_deviation/(int(incoming_data[order_id].microcontroller_data.length)); // Calculating the penalty amount using the averaged absolute total deviation for the transport condition int transport_condition_parameter_penalty_amount = averaged_absolute_total_deviation * orders[order_id].transport_condition_parameters[l].penalty_amount; // If the averaged_absolute_total_deviation is not greater than 5% of the amount to transporter if (transport_condition_parameter_penalty_amount <= ((5*orders[order_id].seller_to_transporter_amount)/100)){ // Assign calculated penalty parameter_penalty.penalty_amount = transport_condition_parameter_penalty_amount; } // If the averaged_absolute_total_deviation is greater than 5% of the amount to transporter else{ // Assign capped penalty parameter_penalty.penalty_amount = (5*orders[order_id].seller_to_transporter_amount)/100; } // Pushing the updated local parameter penalty struct to penalties mapping if (parameter_penalty.penalty_amount > 0) { penalties[order_id].push(parameter_penalty); } } // Carry out the payments paymentPostPenalties(order_id); } // Ether amount transferred to participants will be stored in this mapping // Contract to .... is said as the amount here are after application of penalties // and transferred from the contract to the respective participant // struct contract_to_participant_amount{ // uint contract_to_buyer; // Refund to buyer // uint contract_to_seller; // uint contract_to_transporter; // } // mapping(uint8 => contract_to_participant_amount) public amount_to_participants; uint[] public amount_to_participants; function paymentPostPenalties(uint8 order_id) private{ address payable buyer_address = payable(RoleParticipant["Buyer"]); address payable seller_address = payable(RoleParticipant["Seller"]); address payable transporter_address = payable(RoleParticipant["Transporter"]); // Total penalties applied to a participant will be stored in these int seller_penalty; int transporter_penalty; // Get buyer, seller and transporter address since transactions may be done to all three by the contract // for(uint8 i = 0; i < orders[order_id].participant_addresses.length; i++){ // if (sha256(bytes(Participants[orders[order_id].participant_addresses[i]].role)) == sha256(bytes("Buyer"))){ // buyer_address = payable(orders[order_id].participant_addresses[i]); // } // else if (sha256(bytes(Participants[orders[order_id].participant_addresses[i]].role)) == sha256(bytes("Seller"))){ // seller_address = payable(orders[order_id].participant_addresses[i]); // } // else if (sha256(bytes(Participants[orders[order_id].participant_addresses[i]].role)) == sha256(bytes("Transporter"))){ // transporter_address = payable(orders[order_id].participant_addresses[i]); // } // } // Calculate total penalty amount applied to a participant using the penalties stored under an order id // Iterating through all the penalties calculated and stored in the penalties mapping for an order id for(uint i=0; i<penalties[order_id].length; i++){ if (penalties[order_id][i].participant_address == seller_address){ seller_penalty += (penalties[order_id][i].penalty_amount); } else if (penalties[order_id][i].participant_address == transporter_address){ transporter_penalty += (penalties[order_id][i].penalty_amount); } } // Declaring the variables to store the final ether amounts to be transferred uint seller_to_transporter_post_penalties; uint buyer_to_seller_post_penalties; // Calculate final ether amount to be transferred after applying penalties // If the calculated transporter penalty does not exceed the amount due to transporter if (transporter_penalty <= (orders[order_id].seller_to_transporter_amount)){ // Update seller to transporter amount post penalties seller_to_transporter_post_penalties = uint(orders[order_id].seller_to_transporter_amount - transporter_penalty); } // If the calculated seller penalty does not exceed the amount due to seller if (seller_penalty <= (orders[order_id].buyer_to_seller_amount - orders[order_id].seller_to_transporter_amount)){ // Update buyer to seller amount post penalties buyer_to_seller_post_penalties = uint(orders[order_id].buyer_to_seller_amount - orders[order_id].seller_to_transporter_amount - seller_penalty); } // Calculate the amount to be refunded to buyer uint contract_to_buyer_post_penalties = uint(orders[order_id].buyer_to_seller_amount - int(buyer_to_seller_post_penalties + seller_to_transporter_post_penalties)); // amount_to_participants.push(contract_to_buyer_post_penalties); // amount_to_participants.push(buyer_to_seller_post_penalties); // amount_to_participants.push(seller_to_transporter_post_penalties); // amount_to_participants[order_id].contract_to_buyer = contract_to_buyer_post_penalties; // amount_to_participants[order_id].contract_to_seller = buyer_to_seller_post_penalties; // amount_to_participants[order_id].contract_to_transporter = seller_to_transporter_post_penalties; // Transfer payments require(transporter_address.send(seller_to_transporter_post_penalties), "Ether to transporter failed"); require(seller_address.send(buyer_to_seller_post_penalties), "Ether to seller failed"); require(buyer_address.send(contract_to_buyer_post_penalties), "Ether to buyer failed"); // Mark order as completed orders[order_id].status = "Completed"; } /* Functions for client access via web3.js (or equivalent) */ // Function to add participants in the system, can only be called by the owner error ParticipantExists(address account_address, string role); function addParticipant( string memory role, string memory name, address account_address ) external onlyOwner { // There is no way to check for the existence of a value for a key in a mapping // since any key will return the default values (0, false, ''). // So check for one or more attributes being non-default. require(Participants[account_address].account_address == address(0) && RoleParticipant[role] == address(0), "Participant exists."); // Granting access to call smart contract functions Participants[account_address].contract_access = true; // Storing the participant's details Participants[account_address].role = role; Participants[account_address].name = name; Participants[account_address].account_address = account_address; // Update the role-participant mapping for validation. RoleParticipant[role] = account_address; } // Function to add orders in the system // Order will be created through the web app function createOrder( uint8 order_id, // The calling participant address is used for updating buyer_address. address seller_address, address transporter_address, int buyer_to_seller_amount, item_struct memory item, int schedule_expected_arrival_timestamp, int schedule_penalty_amount ) external payable restrictedUsers { // Update order_id orders[order_id].order_id = order_id; // Update all three participant addresses. orders[order_id].participant_addresses.push(msg.sender); orders[order_id].participant_addresses.push(seller_address); orders[order_id].participant_addresses.push(transporter_address); // Update buyer to seller amount. orders[order_id].buyer_to_seller_amount = buyer_to_seller_amount; // Update entire item struct, also receive the penalty amount value from the web app orders[order_id].item = item; // Manually update the penalty amount attribute orders[order_id].item.penalty_amount = orders[order_id].buyer_to_seller_amount * item.order_quantity; // Update expected arrival time and penalty in schedule struct. orders[order_id].schedule.expected_arrival_timestamp = schedule_expected_arrival_timestamp; orders[order_id].schedule.penalty_amount = schedule_penalty_amount; // Update order status. orders[order_id].status = "Open"; } // Returns order details to display on the web app function getOrderData(uint8 order_id) external view restrictedUsers returns (order_struct memory) { return orders[order_id]; } // Delete a specific order function deleteOrder(uint8 order_id) external restrictedUsers { delete orders[order_id]; } // Seller adds the transport conditions and assigns a transporter function updateSellerOrder( uint8 order_id, int seller_to_transporter_amount, int schedule_expected_departure_timestamp, int vehicle_penalty_amount, transport_condition_parameter_struct[] calldata transport_condition_parameters // calldata is used since data structure has variable size ) external restrictedUsers { // Update seller to transporter amount. orders[order_id].seller_to_transporter_amount = seller_to_transporter_amount; // Update expected departure timestamp. orders[order_id].schedule.expected_departure_timestamp = schedule_expected_departure_timestamp; // Update unassigned vehicle penalty amount. if (vehicle_penalty_amount <= (seller_to_transporter_amount/10)) { // equivalent to 10% of seller_to_transporter_amount orders[order_id].vehicle.penalty_amount = vehicle_penalty_amount; } // If penalty amount exceeds the 10% cap then store the capped value as the penalty amount else { orders[order_id].vehicle.penalty_amount = seller_to_transporter_amount/10; } // Iterating through expected_parameters as they have a dynamic size for (uint8 i = 0; i < transport_condition_parameters.length; i++) { orders[order_id].transport_condition_parameters.push( transport_condition_parameters[i] ); } } // Transporter allots a vehicle to the order function updateTransporterOrder(uint8 order_id, string memory assigned_vehicle_regn_num) external restrictedUsers { orders[order_id].vehicle.assigned_vehicle_regn_num = assigned_vehicle_regn_num; } // To display penalties on the web app function getPenaltyAmount(uint8 order_id) external view restrictedUsers returns (penalty_struct[] memory){ return penalties[order_id]; } // This function is for testing purposes function getIncomingData(uint8 order_id) external view restrictedUsers returns (string[2] memory, int[4] memory, microcontroller_data_struct[] memory) { return ( [ incoming_data[order_id].loading_vehicle_regn_num, incoming_data[order_id].unloading_vehicle_regn_num ], [ incoming_data[order_id].departure_timestamp, incoming_data[order_id].arrival_timestamp, incoming_data[order_id].loaded_quantity, incoming_data[order_id].unloaded_quantity ], incoming_data[order_id].microcontroller_data ); } // This function will be used by participants to add their private keys mapped to their address function addPrivateKey(address public_key, string memory private_key) restrictedUsers external { require(public_key == msg.sender, "Unauthorized"); PrivateKeys[public_key] = private_key; } // // This function will be used by the web app to retrieve participant's private keys to sign transactions function getPrivateKey(address public_key) restrictedUsers external view returns(string memory){ require(public_key == msg.sender, "Unauthorized"); return PrivateKeys[public_key]; } // receive() function to enable payments to the smart contract receive() external payable {} }
Optional Paste Settings
Category:
None
Cryptocurrency
Cybersecurity
Fixit
Food
Gaming
Haiku
Help
History
Housing
Jokes
Legal
Money
Movies
Music
Pets
Photo
Science
Software
Source Code
Spirit
Sports
Travel
TV
Writing
Tags:
Syntax Highlighting:
None
Bash
C
C#
C++
CSS
HTML
JSON
Java
JavaScript
Lua
Markdown (PRO members only)
Objective C
PHP
Perl
Python
Ruby
Swift
4CS
6502 ACME Cross Assembler
6502 Kick Assembler
6502 TASM/64TASS
ABAP
AIMMS
ALGOL 68
APT Sources
ARM
ASM (NASM)
ASP
ActionScript
ActionScript 3
Ada
Apache Log
AppleScript
Arduino
Asymptote
AutoIt
Autohotkey
Avisynth
Awk
BASCOM AVR
BNF
BOO
Bash
Basic4GL
Batch
BibTeX
Blitz Basic
Blitz3D
BlitzMax
BrainFuck
C
C (WinAPI)
C Intermediate Language
C for Macs
C#
C++
C++ (WinAPI)
C++ (with Qt extensions)
C: Loadrunner
CAD DCL
CAD Lisp
CFDG
CMake
COBOL
CSS
Ceylon
ChaiScript
Chapel
Clojure
Clone C
Clone C++
CoffeeScript
ColdFusion
Cuesheet
D
DCL
DCPU-16
DCS
DIV
DOT
Dart
Delphi
Delphi Prism (Oxygene)
Diff
E
ECMAScript
EPC
Easytrieve
Eiffel
Email
Erlang
Euphoria
F#
FO Language
Falcon
Filemaker
Formula One
Fortran
FreeBasic
FreeSWITCH
GAMBAS
GDB
GDScript
Game Maker
Genero
Genie
GetText
Go
Godot GLSL
Groovy
GwBasic
HQ9 Plus
HTML
HTML 5
Haskell
Haxe
HicEst
IDL
INI file
INTERCAL
IO
ISPF Panel Definition
Icon
Inno Script
J
JCL
JSON
Java
Java 5
JavaScript
Julia
KSP (Kontakt Script)
KiXtart
Kotlin
LDIF
LLVM
LOL Code
LScript
Latex
Liberty BASIC
Linden Scripting
Lisp
Loco Basic
Logtalk
Lotus Formulas
Lotus Script
Lua
M68000 Assembler
MIX Assembler
MK-61/52
MPASM
MXML
MagikSF
Make
MapBasic
Markdown (PRO members only)
MatLab
Mercury
MetaPost
Modula 2
Modula 3
Motorola 68000 HiSoft Dev
MySQL
Nagios
NetRexx
Nginx
Nim
NullSoft Installer
OCaml
OCaml Brief
Oberon 2
Objeck Programming Langua
Objective C
Octave
Open Object Rexx
OpenBSD PACKET FILTER
OpenGL Shading
Openoffice BASIC
Oracle 11
Oracle 8
Oz
PARI/GP
PCRE
PHP
PHP Brief
PL/I
PL/SQL
POV-Ray
ParaSail
Pascal
Pawn
Per
Perl
Perl 6
Phix
Pic 16
Pike
Pixel Bender
PostScript
PostgreSQL
PowerBuilder
PowerShell
ProFTPd
Progress
Prolog
Properties
ProvideX
Puppet
PureBasic
PyCon
Python
Python for S60
QBasic
QML
R
RBScript
REBOL
REG
RPM Spec
Racket
Rails
Rexx
Robots
Roff Manpage
Ruby
Ruby Gnuplot
Rust
SAS
SCL
SPARK
SPARQL
SQF
SQL
SSH Config
Scala
Scheme
Scilab
SdlBasic
Smalltalk
Smarty
StandardML
StoneScript
SuperCollider
Swift
SystemVerilog
T-SQL
TCL
TeXgraph
Tera Term
TypeScript
TypoScript
UPC
Unicon
UnrealScript
Urbi
VB.NET
VBScript
VHDL
VIM
Vala
Vedit
VeriLog
Visual Pro Log
VisualBasic
VisualFoxPro
WHOIS
WhiteSpace
Winbatch
XBasic
XML
XPP
Xojo
Xorg Config
YAML
YARA
Z80 Assembler
ZXBasic
autoconf
jQuery
mIRC
newLISP
q/kdb+
thinBasic
Paste Expiration:
Never
Burn after read
10 Minutes
1 Hour
1 Day
1 Week
2 Weeks
1 Month
6 Months
1 Year
Paste Exposure:
Public
Unlisted
Private
Folder:
(members only)
Password
NEW
Enabled
Disabled
Burn after read
NEW
Paste Name / Title:
Create New Paste
Hello
Guest
Sign Up
or
Login
Sign in with Facebook
Sign in with Twitter
Sign in with Google
You are currently not logged in, this means you can not edit or delete anything you paste.
Sign Up
or
Login
Public Pastes
Secrets.kd
54 min ago | 0.25 KB
STAN internet
1 hour ago | 2.03 KB
Vscode-Extensions
6 hours ago | 0.88 KB
Mapscan v2.4 - Archeagus Grey Hack Series, Ep...
JavaScript | 1 day ago | 12.26 KB
OoT rando seed 6/13
1 day ago | 202.05 KB
w
2 days ago | 0.10 KB
[email protected]
- idiot sending fr...
2 days ago | 1.35 KB
Untitled
2 days ago | 0.03 KB
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the
Cookies Policy
.
OK, I Understand
Not a member of Pastebin yet?
Sign Up
, it unlocks many cool features!