-
-
Save Daltonic/f66b58a3f938d4d7b41da56c3c2d22be to your computer and use it in GitHub Desktop.
Event X
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//SPDX-License-Identifier:MIT | |
pragma solidity >=0.7.0 <0.9.0; | |
import '@openzeppelin/contracts/access/Ownable.sol'; | |
import '@openzeppelin/contracts/utils/Counters.sol'; | |
import '@openzeppelin/contracts/token/ERC721/ERC721.sol'; | |
import '@openzeppelin/contracts/security/ReentrancyGuard.sol'; | |
contract DappEventX is Ownable, ReentrancyGuard, ERC721 { | |
using Counters for Counters.Counter; | |
Counters.Counter private _totalEvents; | |
Counters.Counter private _totalTokens; | |
struct EventStruct { | |
uint256 id; | |
string title; | |
string imageUrl; | |
string description; | |
address owner; | |
uint256 sales; | |
uint256 ticketCost; | |
uint256 capacity; | |
uint256 seats; | |
uint256 startsAt; | |
uint256 endsAt; | |
uint256 timestamp; | |
bool deleted; | |
bool paidOut; | |
bool refunded; | |
bool minted; | |
} | |
struct TicketStruct { | |
uint256 id; | |
uint256 eventId; | |
address owner; | |
uint256 ticketCost; | |
uint256 timestamp; | |
bool refunded; | |
bool minted; | |
} | |
uint256 public balance; | |
uint256 private servicePct; | |
mapping(uint256 => EventStruct) events; | |
mapping(uint256 => TicketStruct[]) tickets; | |
mapping(uint256 => bool) eventExists; | |
constructor(uint256 _pct) ERC721('Event X', 'EVX') { | |
servicePct = _pct; | |
} | |
function createEvent( | |
string memory title, | |
string memory description, | |
string memory imageUrl, | |
uint256 capacity, | |
uint256 ticketCost, | |
uint256 startsAt, | |
uint256 endsAt | |
) public { | |
require(ticketCost > 0 ether, 'TicketCost must be greater than zero'); | |
require(capacity > 0, 'Capacity must be greater than zero'); | |
require(bytes(title).length > 0, 'Title cannot be empty'); | |
require(bytes(description).length > 0, 'Description cannot be empty'); | |
require(bytes(imageUrl).length > 0, 'ImageUrl cannot be empty'); | |
require(startsAt > 0, 'Start date must be greater than zero'); | |
require(endsAt > startsAt, 'End date must be greater than start date'); | |
_totalEvents.increment(); | |
EventStruct memory eventX; | |
eventX.id = _totalEvents.current(); | |
eventX.title = title; | |
eventX.description = description; | |
eventX.imageUrl = imageUrl; | |
eventX.capacity = capacity; | |
eventX.ticketCost = ticketCost; | |
eventX.startsAt = startsAt; | |
eventX.endsAt = endsAt; | |
eventX.owner = msg.sender; | |
eventX.timestamp = currentTime(); | |
eventExists[eventX.id] = true; | |
events[eventX.id] = eventX; | |
} | |
function updateEvent( | |
uint256 eventId, | |
string memory title, | |
string memory description, | |
string memory imageUrl, | |
uint256 capacity, | |
uint256 ticketCost, | |
uint256 startsAt, | |
uint256 endsAt | |
) public { | |
require(eventExists[eventId], 'Event not found'); | |
require(events[eventId].owner == msg.sender, 'Unauthorized entity'); | |
require(ticketCost > 0 ether, 'TicketCost must be greater than zero'); | |
require(capacity > 0, 'capacity must be greater than zero'); | |
require(bytes(title).length > 0, 'Title cannot be empty'); | |
require(bytes(description).length > 0, 'Description cannot be empty'); | |
require(bytes(imageUrl).length > 0, 'ImageUrl cannot be empty'); | |
require(startsAt > 0, 'Start date must be greater than zero'); | |
require(endsAt > startsAt, 'End date must be greater than start date'); | |
events[eventId].title = title; | |
events[eventId].description = description; | |
events[eventId].imageUrl = imageUrl; | |
events[eventId].capacity = capacity; | |
events[eventId].ticketCost = ticketCost; | |
events[eventId].startsAt = startsAt; | |
events[eventId].endsAt = endsAt; | |
} | |
function deleteEvent(uint256 eventId) public { | |
require(eventExists[eventId], 'Event not found'); | |
require(events[eventId].owner == msg.sender || msg.sender == owner(), 'Unauthorized entity'); | |
require(!events[eventId].paidOut, 'Event already paid out'); | |
require(!events[eventId].refunded, 'Event already refunded'); | |
require(!events[eventId].deleted, 'Event already deleted'); | |
require(refundTickets(eventId), 'Event failed to refund'); | |
events[eventId].deleted = true; | |
} | |
function getEvents() public view returns (EventStruct[] memory Events) { | |
uint256 available; | |
for (uint256 i = 1; i <= _totalEvents.current(); i++) { | |
if (!events[i].deleted) { | |
available++; | |
} | |
} | |
Events = new EventStruct[](available); | |
uint256 index; | |
for (uint256 i = 1; i <= _totalEvents.current(); i++) { | |
if (!events[i].deleted) { | |
Events[index++] = events[i]; | |
} | |
} | |
} | |
function getMyEvents() public view returns (EventStruct[] memory Events) { | |
uint256 available; | |
for (uint256 i = 1; i <= _totalEvents.current(); i++) { | |
if (!events[i].deleted && events[i].owner == msg.sender) { | |
available++; | |
} | |
} | |
Events = new EventStruct[](available); | |
uint256 index; | |
for (uint256 i = 1; i <= _totalEvents.current(); i++) { | |
if (!events[i].deleted && events[i].owner == msg.sender) { | |
Events[index++] = events[i]; | |
} | |
} | |
} | |
function getSingleEvent(uint256 eventId) public view returns (EventStruct memory) { | |
return events[eventId]; | |
} | |
function buyTickets(uint256 eventId, uint256 numOfticket) public payable { | |
require(eventExists[eventId], 'Event not found'); | |
require(msg.value >= events[eventId].ticketCost * numOfticket, 'Insufficient amount'); | |
require(numOfticket > 0, 'NumOfticket must be greater than zero'); | |
require( | |
events[eventId].seats + numOfticket <= events[eventId].capacity, | |
'Out of seating capacity' | |
); | |
for (uint i = 0; i < numOfticket; i++) { | |
TicketStruct memory ticket; | |
ticket.id = tickets[eventId].length; | |
ticket.eventId = eventId; | |
ticket.owner = msg.sender; | |
ticket.ticketCost = events[eventId].ticketCost; | |
ticket.timestamp = currentTime(); | |
tickets[eventId].push(ticket); | |
} | |
events[eventId].seats += numOfticket; | |
balance += msg.value; | |
} | |
function getTickets(uint256 eventId) public view returns (TicketStruct[] memory Tickets) { | |
return tickets[eventId]; | |
} | |
function refundTickets(uint256 eventId) internal returns (bool) { | |
for (uint i = 0; i < tickets[eventId].length; i++) { | |
tickets[eventId][i].refunded = true; | |
payTo(tickets[eventId][i].owner, tickets[eventId][i].ticketCost); | |
balance -= tickets[eventId][i].ticketCost; | |
} | |
events[eventId].refunded = true; | |
return true; | |
} | |
function payout(uint256 eventId) public { | |
require(eventExists[eventId], 'Event not found'); | |
require(!events[eventId].paidOut, 'Event already paid out'); | |
require(currentTime() > events[eventId].endsAt, 'Event still ongoing'); // disable while testing | |
require(events[eventId].owner == msg.sender || msg.sender == owner(), 'Unauthorized entity'); | |
require(mintTickets(eventId), 'Event failed to mint'); | |
uint256 revenue = events[eventId].ticketCost * events[eventId].seats; | |
uint256 feePct = (revenue * servicePct) / 100; | |
payTo(events[eventId].owner, revenue - feePct); | |
payTo(owner(), feePct); | |
events[eventId].paidOut = true; | |
balance -= revenue; | |
} | |
function mintTickets(uint256 eventId) internal returns (bool) { | |
for (uint i = 0; i < tickets[eventId].length; i++) { | |
_totalTokens.increment(); | |
tickets[eventId][i].minted = true; | |
_mint(tickets[eventId][i].owner, _totalTokens.current()); | |
} | |
events[eventId].minted = true; | |
return true; | |
} | |
function payTo(address to, uint256 amount) internal { | |
(bool success, ) = payable(to).call{ value: amount }(''); | |
require(success); | |
} | |
function currentTime() internal view returns (uint256) { | |
return (block.timestamp * 1000) + 1000; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment