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
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ Generate ABI: `npm run generate_abi_wsl` or `npm run generate_abi`

# Current deployed address

0x41c3462A19a267D8F5690D5b411c4e46aCf0bbcB
0x8BE301eD017D23977F98b48CD9D18EaB91C0ae26

## Mainnet

0xeB60D2D16F2D48324C84D9ffB26465A88d40659f

## Steps
* npm run rebuild - Will clean and compile all contracts in contracts/
Expand Down
165 changes: 78 additions & 87 deletions contracts/VenueMint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
// import "hardhat/console.sol";

struct Event {
uint256 count;
string description;
}

// holds the minimum and maximum ids for that event
struct Ids {
// both inclusive
Expand All @@ -20,23 +15,30 @@ struct Ids {
bool exists;
}

struct Transferable {
bool transferable;
struct Event {
uint256 count;
string description;
Ids ids;
address vendor_wallet;
}

struct EventsIndex {
uint256 index;
bool exists;
}

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 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 nft ids to cost
mapping(uint256 => uint256) private ticket_costs;

// 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;
mapping(uint256 => bool) private id_to_transferable;

// map description to the event
mapping(string => EventsIndex) private description_to_events_index;

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

Expand Down Expand Up @@ -83,16 +85,6 @@ contract VenueMint is ERC1155Holder, ERC1155 {
general_admission + unique_seats
);

//console.log("Description is %s", description);
//console.log("Venue URL is %s", from);
//console.log("General admission is %d", general_admission);
//console.log("Unique seats is %d", unique_seats);

/*
uint256[] memory ids = new uint256[](unique_seats + 1);
uint256[] memory amounts = new uint256[](unique_seats + 1);
*/ // Uncomment this if we want to try semi-fungible tickets

// 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[](
Expand All @@ -105,44 +97,31 @@ contract VenueMint is ERC1155Holder, ERC1155 {
amounts[i - last_id] = 1;
if (i < unique_seats) {
ticket_costs[i] = costs[i - last_id];
original_ticket_costs[i] = costs[i - last_id];
} else {
ticket_costs[i] = costs[costs.length - 1];
original_ticket_costs[i] = costs[costs.length - 1];
}
}

id_to_transferable[i].exists = true;
ids_to_events_index[i] = events.length;

/*
if(i < unique_seats) {
amounts[i] = 1;
} else {
amounts[i] = general_admission;
}
*/ // Uncomment this if we want to try semi-fungible tickets
// keep track of the NFT ids for the event
Ids memory tmp;
tmp.min = last_id;
tmp.max = i - 1;
tmp.exists = true;

// console.log("ids[%d] = %d", i, ids[i]);
// console.log("amounts[%d] = %d", i, amounts[i]);
}
EventsIndex memory tmp2;
tmp2.exists = true;
tmp2.index = events.length;

// 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);
description_to_events_index[description] = tmp2;
events.push(
Event({
description: description,
count: general_admission + unique_seats
count: general_admission + unique_seats,
ids: tmp,
vendor_wallet: payable(msg.sender)
})
);

// keep track of the NFT ids for the event
Ids memory tmp;
tmp.min = last_id;
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;
Expand Down Expand Up @@ -172,24 +151,26 @@ contract VenueMint is ERC1155Holder, ERC1155 {
function get_event_ids(
string calldata description
) public view returns (uint256[] memory, Ids memory) {
Ids memory tmp = event_to_ids[description];
uint256 count = 0;
EventsIndex memory tmp2 = description_to_events_index[description];

// check that there is a valid description
require(tmp.exists, "Please provide a description for a valid event.");
require(tmp2.exists, "Please provide a description for a valid event.");

Ids memory tmp = events[description_to_events_index[description].index]
.ids;
uint256 count = 0;

// figure out how big our array needs to be
for (uint256 i = tmp.min; i <= tmp.max; i++) {
if (ticket_costs[i] != 0) {
if (balanceOf(self, i) > 0) {
count++;
}
}

uint256[] memory result = new uint256[](count);
uint256 j = 0;
for (uint256 i = tmp.min; i <= tmp.max; i++) {
if (ticket_costs[i] != 0) {
//console.log(i);
if (balanceOf(self, i) > 0) {
result[j] = i;
j++;
}
Expand All @@ -202,14 +183,21 @@ contract VenueMint is ERC1155Holder, ERC1155 {
function get_event_description(
uint256 id
) public view returns (string memory) {
return events[ids_to_events_index[id]].description;
for (uint256 i = 0; i < events.length; i++) {
Ids memory tmp = events[i].ids;

if (id >= tmp.min && id <= tmp.max) {
return events[i].description;
}
}
return "";
}

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

// Give the cost of tickets so that we can pass that into value field on frontend
Expand All @@ -228,9 +216,21 @@ contract VenueMint is ERC1155Holder, ERC1155 {
string calldata event_description,
uint256[] calldata ids
) public payable returns (bool, uint256) {
// Make sure its a real event
require(
description_to_events_index[event_description].exists,
"Please provide a description for a valid event."
);

// Get the total cost of each tickets
uint256 total_cost = 0;
for (uint256 i = 0; i < ids.length; ++i) {
// Make sure the contract currently has these tickets
require(
balanceOf(self, ids[i]) > 0,
"One of these tickets has already been sold."
);

total_cost += ticket_costs[ids[i]];
}

Expand All @@ -251,20 +251,15 @@ contract VenueMint is ERC1155Holder, ERC1155 {
}

// Transfer the money to the vendor
(bool success, ) = event_to_vendor[event_description].call{
value: total_cost
}("");
(bool success, ) = events[
description_to_events_index[event_description].index
].vendor_wallet.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;
}

return (true, total_cost);
}

Expand All @@ -277,32 +272,30 @@ contract VenueMint is ERC1155Holder, ERC1155 {
return isApprovedForAll(msg.sender, self);
}

function check_ticket_transferable(uint256 ticketid) public view returns (bool) {
Transferable memory tmp = id_to_transferable[ticketid];
require(tmp.exists, "The ticket id provided is not valid.");
return tmp.transferable;
function check_ticket_transferable(
uint256 ticketid
) public view returns (bool) {
return id_to_transferable[ticketid];
}

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.");
require(ticketid < last_id, "The ticket id provided is not valid.");
require(
balanceOf(msg.sender, ticketid) > 0,
"Can't allow ticket transfer for a ticket you do not own."
);

id_to_transferable[ticketid].transferable = true;
id_to_transferable[ticketid] = true;
}

function disallow_ticket_to_be_transfered(uint256 ticketid) public {
Transferable memory tmp = id_to_transferable[ticketid];
require(tmp.exists, "The ticket id provided is not valid.");
require(ticketid < last_id, "The ticket id provided is not valid.");
require(
balanceOf(msg.sender, ticketid) > 0,
"Can't disallow ticket transfer for a ticket you do not own."
);

id_to_transferable[ticketid].transferable = false;
id_to_transferable[ticketid] = false;
}

// disables the contracts control of the senders tokens
Expand All @@ -315,37 +308,35 @@ contract VenueMint is ERC1155Holder, ERC1155 {
address user,
uint256 ticketid
) public payable {
Transferable memory tmp = id_to_transferable[ticketid];
bool 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(ticketid < last_id, "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(tmp, "This ticket id provided is not transferable.");
require(
balanceOf(user, ticketid) > 0,
"Requested seller does not own the ticket."
);

uint256 cost = ticket_costs[ticketid];

require(
msg.value >= original_ticket_costs[ticketid],
msg.value >= cost,
"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: cost}("");
require(success, "Failed to pay the user you are purchasing from.");

// transfer the nft to the purchaser
_safeTransferFrom(user, msg.sender, ticketid, 1, "");

id_to_transferable[ticketid].transferable = false;
id_to_transferable[ticketid] = false;

emit User_To_User_Transfer_Concluded(user, msg.sender);
}
Expand Down
18 changes: 12 additions & 6 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "hardhat-gas-reporter";
require('dotenv').config();
require("dotenv").config();

const poly_api_key = process.env.POLYGONSCAN_API_KEY || ""
const private_key = process.env.PRIVATE_KEY || "0000000000000000000000000000000000000000000000000000000000000000";
const coinmarketcap_api_key = process.env.COINMARKETCAP_API_KEY || ""
const poly_api_key = process.env.POLYGONSCAN_API_KEY || "";
const private_key =
process.env.PRIVATE_KEY ||
"0000000000000000000000000000000000000000000000000000000000000000";
const coinmarketcap_api_key = process.env.COINMARKETCAP_API_KEY || "";

const config: HardhatUserConfig = {
solidity: "0.8.27",
defaultNetwork: 'hardhat',
defaultNetwork: "hardhat",
networks: {
hardhat: {
blockGasLimit: 1000000000000, // whatever you want here
Expand All @@ -18,12 +20,16 @@ const config: HardhatUserConfig = {
url: `https://rpc-amoy.polygon.technology`,
accounts: [private_key],
},
polygon: {
url: `https://polygon-rpc.com/`,
accounts: [private_key],
},
},
etherscan: {
apiKey: poly_api_key,
},
gasReporter: {
currency: 'USD',
currency: "USD",
L1: "polygon",
coinmarketcap: coinmarketcap_api_key,
L1Etherscan: poly_api_key,
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"deploy_mint": "npx hardhat ignition deploy ./ignition/modules/VenueMint.ts --network localhost",
"deploy": "rm -r ./ignition/deployments ; npx hardhat ignition deploy ./ignition/modules/VenueMint.ts --network polygon_amoy",
"local_console": "npx hardhat console --network localhost",
"generate_abi": "solc-windows.exe --base-path . --include-path node_modules\\ contracts\\VenueMint.sol --abi -o abis --overwrite",
"generate_abi_wsl": "solc --base-path . --include-path ./node_modules/ ./contracts/VenueMint.sol --abi -o abis --overwrite"
"generate_abi": "./solc-windows.exe --base-path . --include-path node_modules\\ contracts\\VenueMint.sol --abi -o abis --overwrite",
"generate_abi_wsl": "./solc-windows.exe --base-path . --include-path ./node_modules/ ./contracts/VenueMint.sol --abi -o abis --overwrite"
},
"author": "",
"license": "ISC",
Expand Down
Loading