Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 121 additions & 55 deletions contracts/VenueMint.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
Expand Down Expand Up @@ -29,38 +29,57 @@ contract VenueMint is ERC1155Holder, ERC1155 {
address private owner; // Deployer of contract (us)
address private self; // The address of the contract (self)

mapping (string => address payable) private event_to_vendor; // Mapping event descriptions to vendor wallets
mapping (uint256 => uint256) private ticket_costs; // Mapping nft ids to cost
mapping(string => address payable) private event_to_vendor; // Mapping event descriptions to vendor wallets
mapping(uint256 => uint256) private ticket_costs; // Mapping nft ids to cost
// mapping nft ids to their original costs (ticket_costs gets zero'd on purchase)
mapping (uint256 => uint256) private original_ticket_costs;
mapping (string => Ids) private event_to_ids; // Mapping event descriptions to NFT ids
// Mapping ticket id to whether they are allowed to be transferred to another user
mapping (uint256 => Transferable) private id_to_transferable;
mapping (uint256 => string) private ids_to_description; // Mapping ticket id to event description
mapping(uint256 => uint256) private original_ticket_costs;
mapping(string => Ids) private event_to_ids; // Mapping event descriptions to NFT ids
// Mapping ticket id to whether they are allowed to be transferred to another user
mapping(uint256 => Transferable) private id_to_transferable;
mapping(uint256 => uint256) private ids_to_events_index;

uint256 last_id = 0; // The last id that we minted

Event[] private events;

event Event_Commencement(address indexed from, string description, string venue_URI, uint256 capacity);
event Event_Commencement(
address indexed from,
string description,
string venue_URI,
uint256 capacity
);
event Buy_Ticket_Event(string description, uint256 count);
event User_To_User_Transfer_Concluded(address indexed seller, address indexed buyer);
event User_To_User_Transfer_Concluded(
address indexed seller,
address indexed buyer
);

// Set the owner to the deployer and self to the address of the contract
constructor() ERC1155("https://onlytickets.co/api/tokens/{id}.json") {
constructor() ERC1155("https://client.dev.opentix.co/api/tokens/{id}.json") {
owner = msg.sender;
self = address(this);
//console.log("Contract address is ", self, " and owner address is", owner);
}

// Create a new event check the costs, emit an event being made
function create_new_event(string calldata description, string calldata vendor_url,
uint256 general_admission, uint256 unique_seats,
uint256[] calldata costs) public returns (bool) {
require(costs.length == unique_seats + general_admission,
"Must provide the same number of costs as general admission and unique seats.");

emit Event_Commencement(msg.sender, description, vendor_url, general_admission + unique_seats);
function create_new_event(
string calldata description,
string calldata vendor_url,
uint256 general_admission,
uint256 unique_seats,
uint256[] calldata costs
) public {
require(
costs.length == unique_seats + general_admission,
"Must provide the same number of costs as general admission and unique seats."
);

emit Event_Commencement(
msg.sender,
description,
vendor_url,
general_admission + unique_seats
);

//console.log("Description is %s", description);
//console.log("Venue URL is %s", from);
Expand All @@ -74,7 +93,9 @@ contract VenueMint is ERC1155Holder, ERC1155 {

// Set the ids and the amounts of each along with the cost of each being minted
uint256[] memory ids = new uint256[](unique_seats + general_admission);
uint256[] memory amounts = new uint256[](unique_seats + general_admission);
uint256[] memory amounts = new uint256[](
unique_seats + general_admission
);
uint256 i = last_id;

for (; i < last_id + ids.length; ++i) {
Expand All @@ -89,8 +110,7 @@ contract VenueMint is ERC1155Holder, ERC1155 {
}

id_to_transferable[i].exists = true;
ids_to_description[i] = description;

ids_to_events_index[i] = events.length;

/*
if(i < unique_seats) {
Expand All @@ -107,36 +127,49 @@ contract VenueMint is ERC1155Holder, ERC1155 {
// Track the vendor wallet so they can be paid when someone buys a ticket to their event
// Save the event to events
event_to_vendor[description] = payable(msg.sender);
events.push(Event({ description:description, count: general_admission + unique_seats}));
events.push(
Event({
description: description,
count: general_admission + unique_seats
})
);

// keep track of the NFT ids for the event
Ids memory tmp;
tmp.min = last_id;
tmp.max = i-1;
tmp.max = i - 1;
tmp.exists = true;
event_to_ids[description] = tmp;

_mintBatch(self, ids, amounts, "");
// Keep up with the last nft we minted;
last_id = i;
return true;
}

function get_events() public view returns (string[] memory) {
string[] memory ret = new string[](events.length > 100 ? 100 : events.length);
string[] memory ret = new string[](
events.length > 100 ? 100 : events.length
);
uint256 j = 0;

for (uint256 i = 0; i < events.length; ++i) {
if (events[i].count > 0) {
ret[j++] = string(abi.encodePacked(events[i].description,
" Capacity is ", Strings.toString(events[i].count)));
ret[j++] = string(
abi.encodePacked(
events[i].description,
" Capacity is ",
Strings.toString(events[i].count)
)
);
}
}
return ret;
}

// returns a list of all valid NFT ids for the event
function get_event_ids(string calldata description) public view returns (uint256[] memory, Ids memory) {
function get_event_ids(
string calldata description
) public view returns (uint256[] memory, Ids memory) {
Ids memory tmp = event_to_ids[description];
uint256 count = 0;

Expand All @@ -150,7 +183,7 @@ contract VenueMint is ERC1155Holder, ERC1155 {
}
}

uint256[] memory result = new uint256[](count);
uint256[] memory result = new uint256[](count);
uint256 j = 0;
for (uint256 i = tmp.min; i <= tmp.max; i++) {
if (ticket_costs[i] != 0) {
Expand All @@ -164,17 +197,23 @@ contract VenueMint is ERC1155Holder, ERC1155 {
}

// get the event description with the ticket id
function get_event_description(uint256 id) public view returns (string memory) {
return ids_to_description[id];
function get_event_description(
uint256 id
) public view returns (string memory) {
return events[ids_to_events_index[id]].description;
}

// returns true if the description is available. false otherwise
function is_description_available(string calldata description) public view returns (bool) {
function is_description_available(
string calldata description
) public view returns (bool) {
return !event_to_ids[description].exists;
}

// Give the cost of tickets so that we can pass that into value field on frontend
function get_cost_for_tickets(uint256[] calldata ids) public view returns (uint256) {
function get_cost_for_tickets(
uint256[] calldata ids
) public view returns (uint256) {
uint256 total_cost = 0;
for (uint256 i = 0; i < ids.length; ++i) {
total_cost += ticket_costs[ids[i]];
Expand All @@ -183,32 +222,42 @@ contract VenueMint is ERC1155Holder, ERC1155 {
}

// Enable users to buy tickets (NFTs)
function buy_tickets(string calldata event_description, uint256[] calldata ids) payable public
returns (bool, uint256) {
function buy_tickets(
string calldata event_description,
uint256[] calldata ids
) public payable returns (bool, uint256) {
// Get the total cost of each tickets
uint256 total_cost = 0;
for (uint256 i = 0; i < ids.length; ++i) {
total_cost += ticket_costs[ids[i]];
}

// Check if they are able to buy those tickets and that they have enough money
require (total_cost > 0, "You are attempting to buy unavailable tickets.");
require(msg.value >= total_cost, "You do not have enough money to purchase the desired tickets.");

require(
total_cost > 0,
"You are attempting to buy unavailable tickets."
);
require(
msg.value >= total_cost,
"You do not have enough money to purchase the desired tickets."
);

// Buy one since they're NFTs
uint256[] memory values = new uint256[](ids.length);
for (uint256 i = 0; i < ids.length; ++i) {
values[i] = 1;
}

// Transfer the money to the vendor
(bool success, ) = event_to_vendor[event_description].call{value:total_cost}("");
(bool success, ) = event_to_vendor[event_description].call{
value: total_cost
}("");
require(success, "transfer to vender failed.");

// Transfer the tickets to the user
_safeBatchTransferFrom(self, msg.sender, ids, values, "");
emit Buy_Ticket_Event(event_description, ids.length);

// 0 out the costs so that we can't double sell tickets
for (uint256 i = 0; i < ids.length; ++i) {
ticket_costs[ids[i]] = 0;
Expand All @@ -218,14 +267,19 @@ contract VenueMint is ERC1155Holder, ERC1155 {
}

// this enables the input user to transfer the callers tickets
function allow_user_to_user_ticket_transfer(uint256 ticketid) public returns (bool) {
function allow_user_to_user_ticket_transfer() public {
setApprovalForAll(self, true);
}

function check_ticket_transfer_permission() public view returns (bool) {
return isApprovedForAll(msg.sender, self);
}

function allow_ticket_to_be_transfered(uint256 ticketid) public {
Transferable memory tmp = id_to_transferable[ticketid];
require(tmp.exists, "The ticket id provided is not valid.");

id_to_transferable[ticketid].transferable = true;

setApprovalForAll(self, true);
return true;
}

// disables the contracts control of the senders tokens
Expand All @@ -234,17 +288,31 @@ contract VenueMint is ERC1155Holder, ERC1155 {
}

// this should be called buy the purchaser of the ticket
function buy_ticket_from_user(address user, uint256 ticketid) payable public returns (bool) {
function buy_ticket_from_user(
address user,
uint256 ticketid
) public payable {
Transferable memory tmp = id_to_transferable[ticketid];

// we need to make sure this is a valid transfer
require(tmp.exists, "The ticket id provided is not valid.");
require(isApprovedForAll(user, self), "The seller has not authorized a transfer.");
require(tmp.transferable, "This ticket id provided is not transferable.");
require(msg.value >= original_ticket_costs[ticketid],"You did not send enough money to purchase the ticket.");
require(
isApprovedForAll(user, self),
"The seller has not authorized a transfer."
);
require(
tmp.transferable,
"This ticket id provided is not transferable."
);
require(
msg.value >= original_ticket_costs[ticketid],
"You did not send enough money to purchase the ticket."
);

// send the money to the user
(bool success, ) = user.call{value:original_ticket_costs[ticketid]}("");
(bool success, ) = user.call{value: original_ticket_costs[ticketid]}(
""
);
require(success, "Failed to pay the user you are purchasing from.");

// transfer the nft to the purchaser
Expand All @@ -253,13 +321,11 @@ contract VenueMint is ERC1155Holder, ERC1155 {
id_to_transferable[ticketid].transferable = false;

emit User_To_User_Transfer_Concluded(user, msg.sender);

return true;
}

function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155, ERC1155Holder)
returns (bool) {
function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC1155, ERC1155Holder) returns (bool) {
return super.supportsInterface(interfaceId);
}

}
}
3 changes: 2 additions & 1 deletion test/VenueMint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ describe("VenueMint", function () {

// buy the tickets and give the contract permission to control the holders tokens
const resp = await holder_instance.buy_tickets("test", [0], {value: ethers.parseEther("1")});
const resp1 = await holder_instance.allow_user_to_user_ticket_transfer(0);
const resp1 = await holder_instance.allow_user_to_user_ticket_transfer();
const resp11 = await holder_instance.allow_ticket_to_be_transfered(0);

// variable to check that we removed the contracts ability to control our tokens
// a filter that allows us to only execute the function based on the holder and purchaser address
Expand Down