How to Build a Ticketing Contract with Solidity on Celo

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:

  • Remix

  • 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.

References

9 Likes

Look forward to the finished article. Really curious on how this turns out!!

4 Likes

Anticipating😎

1 Like

Nice idea

2 Likes

Nice one… Great idea

1 Like

I will be looking forward to seeing how you implement this. I’ll also appreciate if you can add images to aid the learning

1 Like

Fantastic news! Your proposal has landed in this week’s top voted list. As you begin your project journey, remember to align with our community and technical guidelines, ensuring a high quality platform for our developers. Congratulations! :mortar_board: :seedling:

Note: @thompsonogoyi1t based on the number of votes you received, we would like to proceed with your tutorial. However, it is quite similar to a number of tutorials we have on the platform already. Kindly revise the article to align with our proposal guidelines and provide a unique take on this concept. Once you are ready, we will conduct an additional review and proceed with rewarding you for this tutorial. Thank you!

3 Likes

Hi @Kyrian I’ll bereviewing your piece in 1 to 2 days

1 Like