Cafe (solidity)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Cafe {
address public owner;
struct MenuItem {
string name;
string description;
uint256 price; // price in Wei (smallest unit of Ether)
}
struct Order {
uint256 orderId;
address customer;
uint256 itemId;
uint256 timestamp;
bool isCompleted;
}
mapping(uint256 => MenuItem) public menu; // Menu ID to Menu Item
mapping(uint256 => Order) public orders; // Order ID to Order
uint256 public menuCount;
uint256 public orderCount;
event MenuItemAdded(uint256 itemId, string name, uint256 price);
event OrderPlaced(uint256 orderId, address customer, uint256 itemId, uint256 price);
event OrderCompleted(uint256 orderId);
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can perform this action");
_;
}
modifier onlyCustomer(uint256 orderId) {
require(orders[orderId].customer == msg.sender, "You are not the customer for this order");
_;
}
constructor() {
owner = msg.sender;
}
// Add a menu item (only accessible by owner)
function addMenuItem(string memory name, string memory description, uint256 price) public onlyOwner {
menuCount++;
menu[menuCount] = MenuItem(name, description, price);
emit MenuItemAdded(menuCount, name, price);
}
// Remove a menu item (only accessible by owner)
function removeMenuItem(uint256 itemId) public onlyOwner {
delete menu[itemId];
}
// Place an order
function placeOrder(uint256 itemId) public payable {
require(itemId > 0 && itemId <= menuCount, "Invalid menu item");
MenuItem memory item = menu[itemId];
require(msg.value >= item.price, "Insufficient payment");
orderCount++;
orders[orderCount] = Order(orderCount, msg.sender, itemId, block.timestamp, false);
payable(owner).transfer(msg.value); // Send the payment to the owner
emit OrderPlaced(orderCount, msg.sender, itemId, item.price);
}
// Mark an order as completed (only accessible by owner)
function completeOrder(uint256 orderId) public onlyOwner {
require(!orders[orderId].isCompleted, "Order is already completed");
orders[orderId].isCompleted = true;
emit OrderCompleted(orderId);
}
// Get order details
function getOrder(uint256 orderId) public view returns (Order memory) {
return orders[orderId];
}
// Get menu item details
function getMenuItem(uint256 itemId) public view returns (MenuItem memory) {
return menu[itemId];
}
// Get the total number of orders
function getTotalOrders() public view returns (uint256) {
return orderCount;
}
// Get the total number of menu items
function getTotalMenuItems() public view returns (uint256) {
return menuCount;
}
}
☕ Solidity Smart Contract: Cafe
✅ License and Version
// SPDX-License-Identifier: MIT
- Declares the license type for the contract (MIT).
- It’s a best practice to include a license identifier for open-source clarity.
pragma solidity ^0.8.0;
- Specifies the compiler version (Solidity 0.8.0 or later).
pragmais a directive that ensures compatibility.
🏛️ Contract Declaration
contract Cafe {
- Declares a new contract named
Cafe. - A contract in Solidity is similar to a class in OOP languages.
👤 State Variables
address public owner;
address: a 20-byte Ethereum address type.public: creates a getter function automatically.owner: stores the Ethereum address of the contract’s owner.
📋 Structs (Custom Data Types)
struct MenuItem {
string name;
string description;
uint256 price; // price in Wei (smallest unit of Ether)
}
- Defines a menu item with a name, description, and price.
uint256: unsigned integer, 256 bits, used for gas efficiency.
struct Order {
uint256 orderId;
address customer;
uint256 itemId;
uint256 timestamp;
bool isCompleted;
}
- Represents an order placed by a customer.
- Includes order metadata: ID, customer address, menu item ID, time of order, and status.
🗺️ Mappings (Key-Value Storage)
mapping(uint256 => MenuItem) public menu;
- Maps a unique item ID to its
MenuItemstruct. public: makes it readable from outside.
mapping(uint256 => Order) public orders;
- Maps a unique order ID to its
Orderstruct.
uint256 public menuCount;
uint256 public orderCount;
- Counters to keep track of menu items and orders.
📣 Events
event MenuItemAdded(uint256 itemId, string name, uint256 price);
event OrderPlaced(uint256 orderId, address customer, uint256 itemId, uint256 price);
event OrderCompleted(uint256 orderId);
events allow off-chain applications (like dApps) to listen for important contract actions.
🛡️ Modifiers (Access Control)
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can perform this action");
_;
}
- Restricts function access to the contract owner.
msg.sender: address calling the function._: represents the function body that uses the modifier.
modifier onlyCustomer(uint256 orderId) {
require(orders[orderId].customer == msg.sender, "You are not the customer for this order");
_;
}
- Restricts access to the customer who placed the specific order.
⚙️ Constructor
constructor() {
owner = msg.sender;
}
- Runs once during deployment.
- Assigns the contract deployer as the owner.
🍽️ Function: Add Menu Item
function addMenuItem(string memory name, string memory description, uint256 price) public onlyOwner {
menuCount++;
menu[menuCount] = MenuItem(name, description, price);
emit MenuItemAdded(menuCount, name, price);
}
memory: temporary storage (vs.storage).- Increments the menu counter.
- Saves a new
MenuIteminto the mapping. - Emits an event for tracking.
🧹 Function: Remove Menu Item
function removeMenuItem(uint256 itemId) public onlyOwner {
delete menu[itemId];
}
- Deletes a menu item by setting its struct values to default (empty).
- Only owner can do this.
🛒 Function: Place Order
function placeOrder(uint256 itemId) public payable {
require(itemId > 0 && itemId <= menuCount, "Invalid menu item");
MenuItem memory item = menu[itemId];
require(msg.value >= item.price, "Insufficient payment");
orderCount++;
orders[orderCount] = Order(orderCount, msg.sender, itemId, block.timestamp, false);
payable(owner).transfer(msg.value);
emit OrderPlaced(orderCount, msg.sender, itemId, item.price);
}
payable: allows the function to receive Ether.- Checks the menu item is valid and that payment is sufficient.
- Creates a new order and transfers the Ether to the owner.
block.timestamp: the time the block was mined.payable(owner).transfer(...): sends Ether.
✅ Function: Complete Order
function completeOrder(uint256 orderId) public onlyOwner {
require(!orders[orderId].isCompleted, "Order is already completed");
orders[orderId].isCompleted = true;
emit OrderCompleted(orderId);
}
- Marks an order as completed.
- Prevents re-completing the same order.
🔍 Read Functions (View)
function getOrder(uint256 orderId) public view returns (Order memory) {
return orders[orderId];
}
- Returns full details of a specific order.
function getMenuItem(uint256 itemId) public view returns (MenuItem memory) {
return menu[itemId];
}
- Returns full details of a specific menu item.
function getTotalOrders() public view returns (uint256) {
return orderCount;
}
- Returns total number of orders.
function getTotalMenuItems() public view returns (uint256) {
return menuCount;
}
- Returns total number of menu items.
🧾 Summary
| Concept | Usage |
|---|---|
address |
Stores Ethereum addresses (e.g., owner, customers) |
struct |
Groups multiple variables (e.g., MenuItem, Order) |
mapping |
Key-value storage for menu and orders |
event |
Logs key actions for front-end and monitoring |
modifier |
Restricts access to specific users (owner/customer) |
constructor |
Initializes the contract state |
payable |
Enables function to receive/send Ether |
block.timestamp |
Provides the current block time |