Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update eas logic #16

Merged
merged 4 commits into from
Aug 11, 2024
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
26 changes: 26 additions & 0 deletions apps/contract/scripts/deploy-purchase-ticket.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// When running the script with `npx hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
require('dotenv').config({ path: '../.env' })
const { ethers } = require('hardhat')

async function main() {
const [deployer] = await ethers.getSigners()
console.log('Deploying contracts with the account:', deployer.address)

console.log('deployer', deployer)

const PurchaseTicket = await ethers.getContractFactory('PurchaseTicket')
const purchaseTicket = await PurchaseTicket.deploy('0xcDbFCE45c57b31Dc8B196aB58F74E2b8e478fc7e')

console.log('PurchaseTicket details:', purchaseTicket)
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error)
process.exitCode = 1
})
26 changes: 26 additions & 0 deletions apps/contract/scripts/deploy-ticket-redeem-v2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// When running the script with `npx hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
require('dotenv').config({ path: '../.env' })
const { ethers } = require('hardhat')

async function main() {
const [deployer] = await ethers.getSigners()
console.log('Deploying contracts with the account:', deployer.address)

console.log('deployer', deployer)

const RedeemResolverV2 = await ethers.getContractFactory('RedeemResolverV2')
const redeemResolverV2 = await RedeemResolverV2.deploy('0x4200000000000000000000000000000000000021', '0xcDbFCE45c57b31Dc8B196aB58F74E2b8e478fc7e')

console.log('RedeemResolverV2 details:', redeemResolverV2)
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error)
process.exitCode = 1
})
7 changes: 0 additions & 7 deletions apps/contract/scripts/deploy-ticket-redeem.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,9 @@ async function main() {

console.log('deployer', deployer)

// const deployerBalance = (await deployer.getBalance()).toString()
// console.log('Account balance:', deployerBalance)

// if (deployerBalance === '0') return // deployment will fail

const RedeemResolver = await ethers.getContractFactory('RedeemResolver')
const redeemResolver = await RedeemResolver.deploy('0x4200000000000000000000000000000000000021')
await redeemResolver.deployed()

console.log('RedeemResolver deployed to:', redeemResolver.address)
console.log('RedeemResolver details:', redeemResolver)
}

Expand Down
40 changes: 0 additions & 40 deletions apps/contract/src/PuchaseTicket.sol

This file was deleted.

59 changes: 59 additions & 0 deletions apps/contract/src/PurchaseTicket.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "@openzeppelin/contracts/access/Ownable.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";

contract PurchaseTicket is Ownable {
using Address for address payable;

error AlreadyPurchased();
error AlreadyIssued();
error Duplicate();
error Insufficient();

address private paymentAddress;

mapping(string => mapping(string => uint256)) private prices;
mapping(string => mapping(string => bool)) private proofs;
mapping(string => mapping(string => bool)) private ticketSeats;

constructor(address _paymentAddress) Ownable(msg.sender) {
paymentAddress = _paymentAddress;
}

function setPrice(string memory eventId, string memory ticketType, uint256 price) external onlyOwner {
prices[eventId][ticketType] = price;
}

function getPrice(string memory eventId, string memory ticketType) public view returns (uint256) {
return prices[eventId][ticketType];
}

function purchase(
string memory eventId,
string memory seat,
string memory ticketType,
string memory worldProof
) external payable {
bool purchased = proofs[eventId][worldProof];
if (purchased == true) {
revert AlreadyPurchased();
}

bool issued = ticketSeats[eventId][seat];
if (issued == true) {
revert AlreadyIssued();
}

uint256 price = prices[eventId][ticketType];
if (msg.value < price) {
revert Insufficient();
}

proofs[eventId][worldProof] = true;
ticketSeats[eventId][seat] = true;
payable(paymentAddress).transfer(msg.value);
}

}
2 changes: 0 additions & 2 deletions apps/contract/src/RedeemResolver.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@

// redeem ticket attestation resolver
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

Expand Down
116 changes: 116 additions & 0 deletions apps/contract/src/RedeemResolverV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import { SchemaResolver } from "@ethereum-attestation-service/eas-contracts/contracts/resolver/SchemaResolver.sol";
import { IEAS, Attestation } from "@ethereum-attestation-service/eas-contracts/contracts/IEAS.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";

contract RedeemResolverV2 is SchemaResolver, Ownable {
using Address for address payable;

error OutOfBounds();
error AlreadyPurchased();
error AlreadyIssued();
error Duplicate();
error Insufficient();

address private paymentAddress;

mapping(bytes32 => bool) private redeemedMap;
mapping(string => mapping(string => uint256)) private prices;
mapping(string => mapping(string => bool)) private proofs;
mapping(string => mapping(string => bool)) private ticketSeats;
mapping(address => mapping(string => bool)) private ticketRecipients;
mapping(address => string[]) private ticketRecipientsArr;

constructor(IEAS eas, address _paymentAddress) SchemaResolver(eas) Ownable(msg.sender) {
paymentAddress = _paymentAddress;
}

function isPayable() public pure override returns (bool) {
return true;
}

function setPrice(string memory eventId, string memory ticketType, uint256 price) external onlyOwner {
prices[eventId][ticketType] = price;
}

function getPrice(string memory eventId, string memory ticketType) public view returns (uint256) {
return prices[eventId][ticketType];
}

function getTickets() public view returns (string[] memory) {
return ticketRecipientsArr[msg.sender];
}

function purchase(
string memory eventId,
string memory seat,
string memory ticketType,
string memory worldProof,
string memory attestationId
) external payable {
bool purchased = proofs[eventId][worldProof];
if (purchased == true) {
revert AlreadyPurchased();
}

bool issued = ticketSeats[eventId][seat];
if (issued == true) {
revert AlreadyIssued();
}

bool recipient = ticketRecipients[msg.sender][attestationId];
if (recipient == true) {
revert Duplicate();
}

uint256 price = prices[eventId][ticketType];
if (msg.value < price) {
revert Insufficient();
}

proofs[eventId][worldProof] = true;
ticketSeats[eventId][seat] = true;
ticketRecipients[msg.sender][attestationId] = true;
ticketRecipientsArr[msg.sender].push(attestationId);
payable(paymentAddress).transfer(msg.value);
}

function onAttest(Attestation calldata attestation, uint256 /*value*/) internal view override returns (bool) {
bytes32 uid = _toBytes32(attestation.data, 0);
string memory uidStr = string(abi.encodePacked(uid));
bool exist = ticketRecipients[attestation.recipient][uidStr];
if (exist == true) {
return true;
}

return false;
}

function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
return true;
}

function toBytes32(bytes memory data, uint256 start) external pure returns (bytes32) {
return _toBytes32(data, start);
}

function _toBytes32(bytes memory data, uint256 start) private pure returns (bytes32) {
unchecked {
if (data.length < start + 32) {
revert OutOfBounds();
}
}

bytes32 tempBytes32;

// solhint-disable-next-line no-inline-assembly
assembly {
tempBytes32 := mload(add(add(data, 0x20), start))
}

return tempBytes32;
}
}
Loading