Introduction
In this article, we will be building a ticketing contract on the Celo blockchain that introduces a decentralized approach to managing event tickets. By leveraging smart contracts, this solution offers a secure and transparent platform for event creation, ticket purchase, ticket transfer, ticket resale, event details retrieval, and ticket owner retrieval.
By the end of this tutorial, you will have gained solid knowledge of creating a smart contract on the Celo blockchain .This skill can be applied in various situations, providing practical and efficient solutions for payment on the Celo network.
Prerequisites
To follow this tutorial, you will need:
-
Some knowledge of Solidity
Requirements
Writing the Smart Contract
Ticket.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract TicketingContract {
struct Ticket {
uint256 eventId;
address owner;
bool isAvailable;
}
struct Event {
uint256 eventId;
string name;
string date;
string venue;
uint256 totalTickets;
uint256 pricePerTicket;
uint256 ticketsSold;
}
mapping(uint256 => Event) public events;
mapping(uint256 => Ticket[]) public eventTickets;
event TicketPurchased(
uint256 indexed eventId,
address indexed buyer,
uint256 ticketId
);
event TicketTransferred(
uint256 indexed eventId,
address indexed from,
address indexed to,
uint256 ticketId
);
event TicketResold(
uint256 indexed eventId,
address indexed seller,
address indexed buyer,
uint256 ticketId
);
function createEvent(
uint256 eventId,
string memory name,
string memory date,
string memory venue,
uint256 totalTickets,
uint256 pricePerTicket
) external {
require(
events[eventId].eventId == 0,
"Event with the same ID already exists"
);
Event storage newEvent = events[eventId];
newEvent.eventId = eventId;
newEvent.name = name;
newEvent.date = date;
newEvent.venue = venue;
newEvent.totalTickets = totalTickets;
newEvent.pricePerTicket = pricePerTicket;
newEvent.ticketsSold = 0;
}
function purchaseTicket(uint256 eventId) external payable {
Event storage selectedEvent = events[eventId];
require(selectedEvent.eventId != 0, "Event does not exist");
require(
selectedEvent.ticketsSold < selectedEvent.totalTickets,
"All tickets are sold out"
);
require(
msg.value >= selectedEvent.pricePerTicket,
"Insufficient payment"
);
Ticket[] storage tickets = eventTickets[eventId];
uint256 ticketId = tickets.length;
tickets.push(Ticket(eventId, msg.sender, true));
selectedEvent.ticketsSold++;
emit TicketPurchased(eventId, msg.sender, ticketId);
}
function transferTicket(
uint256 eventId,
address to,
uint256 ticketId
) external {
Ticket[] storage tickets = eventTickets[eventId];
require(ticketId < tickets.length, "Invalid ticket ID");
Ticket storage ticket = tickets[ticketId];
require(msg.sender == ticket.owner, "You are not the ticket owner");
ticket.owner = to;
emit TicketTransferred(eventId, msg.sender, to, ticketId);
}
function resellTicket(
uint256 eventId,
address buyer,
uint256 ticketId
) external payable {
Event storage selectedEvent = events[eventId];
require(selectedEvent.eventId != 0, "Event does not exist");
require(
msg.value >= selectedEvent.pricePerTicket,
"Insufficient payment"
);
Ticket[] storage tickets = eventTickets[eventId];
require(ticketId < tickets.length, "Invalid ticket ID");
Ticket storage ticket = tickets[ticketId];
require(msg.sender == ticket.owner, "You are not the ticket owner");
require(ticket.isAvailable, "Ticket is not available for resale");
ticket.owner = buyer;
ticket.isAvailable = false;
emit TicketResold(eventId, msg.sender, buyer, ticketId);
}
function getEventDetails(uint256 eventId)
external
view
returns (
string memory name,
string memory date,
string memory venue,
uint256 totalTickets,
uint256 pricePerTicket,
uint256 ticketsSold
)
{
Event storage selectedEvent = events[eventId];
require(selectedEvent.eventId != 0, "Event does not exist");
return (
selectedEvent.name,
selectedEvent.date,
selectedEvent.venue,
selectedEvent.totalTickets,
selectedEvent.pricePerTicket,
selectedEvent.ticketsSold
);
}
function getTicketOwner(uint256 eventId, uint256 ticketId)
external
view
returns (address)
{
Ticket[] storage tickets = eventTickets[eventId];
require(ticketId < tickets.length, "Invalid ticket ID");
Ticket storage ticket = tickets[ticketId];
return ticket.owner;
}
}
Breakdown
- struct
The struct Ticket can be used to create instances of tickets, where each instance will have its own eventId
, owner
, and isAvailable
values while the struct event
can be used to create instances of events containing eventId
, name
, date
, venue
, totalTickets
, pricePerTickets
and ticketsSold
.
- mapping
The events mapping allows you to access event details by their unique event IDs, while the eventTickets mapping enables you to retrieve an array of tickets associated with a specific event ID.
- events
These events enable us to keep track of the state changes in our contract. The TicketPurchased
event is emitted when a ticket is purchased, TicketTransferred
event is emitted when a ticket is transferred from one address to another and the TicketResold
event is emitted when a ticket is resold from one address to another.
- createEvent
The function createEvent
creates a new event and stores it in a mapping called events
.
- purchaseTicket
The purchaseTicket
function allows users to buy tickets for specific events, and it performs various checks to ensure that the event exists, there are available tickets, and the payment is sufficient. It also updates the state of the event and emits the event to notify about the ticket purchase.
- transferTicket
The transferTicket
function allows the transfer of a ticket ownership from the current owner to a new owner.
- getEventDetails
The getEventDetails
that retrieves the details of an event based on the provided eventId
.
- getTicketOwner
The getTicketOwner
that retrieves the owner address of a specific ticket within an event.
Deployment
To ensure a successful deployment of our smart contract, we need to have the celo extension wallet. You can download it here:
To proceed, we also need to fund the wallet we have just created. This can be done using the celo alfajores faucet
Once these initial steps are complete, locate the plugin logo positioned at the bottom left corner and initiate a search for the celo plugin.
Install the plugin and you will notice the celo logo appearing in the side tab once the installation process is finalized.
After connecting your celo wallet, you will be able to choose the desired contract for deployment. simply click on the deploy
button to deploy.
Conclusion
We have now come to the end of this tutorial. By following this tutorial, you should have a good understanding of how to build an event ticketing smart contract with solidity on the celo blockchain.
Next Step
You can check out these resources if you wish to learn more
Author
Kyrian Chigozie is a Technical Writer with a passion for web3 technology. Connect with me on Twitter and LinkedIn.