From 5fc8fe1131a8a9183407da2ba4b99acdcdac4fd9 Mon Sep 17 00:00:00 2001 From: caleb Date: Thu, 30 May 2024 00:36:41 -0400 Subject: [PATCH 1/4] =?UTF-8?q?init=20=E2=98=94=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chain/src/contracts/PrizeRegistry.sol | 77 +++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 chain/src/contracts/PrizeRegistry.sol diff --git a/chain/src/contracts/PrizeRegistry.sol b/chain/src/contracts/PrizeRegistry.sol new file mode 100644 index 0000000..21fd932 --- /dev/null +++ b/chain/src/contracts/PrizeRegistry.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import { IERC721 } from "openzeppelin/token/ERC721/IERC721.sol"; +import { IERC1155 } from "openzeppelin/token/ERC1155/IERC1155.sol"; +import { IERC20 } from "openzeppelin/token/ERC20/IERC20.sol"; +import { ERC1155Holder } from "openzeppelin/token/ERC1155/utils/ERC1155Holder.sol"; +import { ERC721Holder } from "openzeppelin/token/ERC721/utils/ERC721Holder.sol"; +import { ReentrancyGuard } from "openzeppelin/utils/ReentrancyGuard.sol"; + +contract PrizeRegistry is ERC1155Holder, ERC721Holder, ReentrancyGuard { + + struct Prize { + string ercType; // ERC721 | ERC1155 | ERC20 + address tokenAddress; + address from; + uint256 tokenId; + uint256 amount; + uint256 price; + } + + event Deposit(string ercType, address tokenAddress, address from, uint256 tokenId, uint256 amount, uint256 price); + + Prize[] public prizes; + + function deposit721(IERC721 _token, uint256 _tokenId, uint256 _price) external nonReentrant { + require(_token.ownerOf(_tokenId) == msg.sender, "You do not own this token"); + require(_price > 0, "Price must be greater than 0"); + + _token.safeTransferFrom(msg.sender, address(this), _tokenId); + prizes.push(Prize({ + ercType: "ERC721", + tokenAddress: address(_token), + from: msg.sender, + tokenId: _tokenId, + amount: 1, + price: _price + })); + + + emit Deposit("ERC721", address(_token), msg.sender, _tokenId, 1, _price); + } + + function deposit1155(IERC1155 _token, uint256 _tokenId, uint256 _amount, uint256 _price) external nonReentrant { + require(_amount <= _token.balanceOf(msg.sender, _tokenId), "You do not have enough of this token"); + require(_price > 0, "Price must be greater than 0"); + + _token.safeTransferFrom(msg.sender, address(this), _tokenId, _amount, ""); + prizes.push(Prize({ + ercType: "ERC1155", + tokenAddress: address(_token), + from: msg.sender, + tokenId: _tokenId, + amount: _amount, + price: _price + })); + + emit Deposit("ERC1155", address(_token), msg.sender, _tokenId, _amount, _price); + } + + function deposit20(IERC20 _token, uint256 _amount, uint256 _price) external nonReentrant { + require(_amount <= _token.balanceOf(msg.sender), "You do not have enough of this token"); + require(_price > 0, "Price must be greater than 0"); + + _token.transferFrom(msg.sender, address(this), _amount); + prizes.push(Prize({ + ercType: "ERC20", + tokenAddress: address(_token), + from: msg.sender, + tokenId: 0, + amount: _amount, + price: _price + })); + + emit Deposit("ERC20", address(_token), msg.sender, 0, _amount, _price); + } +} From 2076675110456d6341b34953db4c76418d2e2970 Mon Sep 17 00:00:00 2001 From: caleb Date: Thu, 30 May 2024 00:56:59 -0400 Subject: [PATCH 2/4] wip redeem --- chain/src/contracts/PrizeRegistry.sol | 127 +++++++++++++++++++------- 1 file changed, 94 insertions(+), 33 deletions(-) diff --git a/chain/src/contracts/PrizeRegistry.sol b/chain/src/contracts/PrizeRegistry.sol index 21fd932..6aec177 100644 --- a/chain/src/contracts/PrizeRegistry.sol +++ b/chain/src/contracts/PrizeRegistry.sol @@ -7,8 +7,12 @@ import { IERC20 } from "openzeppelin/token/ERC20/IERC20.sol"; import { ERC1155Holder } from "openzeppelin/token/ERC1155/utils/ERC1155Holder.sol"; import { ERC721Holder } from "openzeppelin/token/ERC721/utils/ERC721Holder.sol"; import { ReentrancyGuard } from "openzeppelin/utils/ReentrancyGuard.sol"; +import { AccessControl } from "openzeppelin/access/AccessControl.sol"; -contract PrizeRegistry is ERC1155Holder, ERC721Holder, ReentrancyGuard { + +contract PrizeRegistry is ERC1155Holder, ERC721Holder, ReentrancyGuard, AccessControl { + + bytes32 public constant PRIZE_REGISTRY_MANAGER = keccak256("PRIZE_REGISTRY_MANAGER"); struct Prize { string ercType; // ERC721 | ERC1155 | ERC20 @@ -23,55 +27,112 @@ contract PrizeRegistry is ERC1155Holder, ERC721Holder, ReentrancyGuard { Prize[] public prizes; + enum ERCType { ERC721, ERC1155, ERC20 } + + struct Prize { + ERCType ercType; + address tokenAddress; + address from; + uint256 tokenId; + uint256 amount; + uint256 price; + } + + event Deposit(ERCType ercType, address tokenAddress, address from, uint256 tokenId, uint256 amount, uint256 price); + event Redeem(ERCType ercType, address tokenAddress, address to, uint256 tokenId, uint256 amount); + + uint256 public prizeCount; + address public ticketAddress; + mapping(string => Prize) public availablePrizes; + mapping(string => Prize) public redeemedPrizes; + + constructor(address _admin, address _ticketAddress) { + _grantRole(DEFAULT_ADMIN_ROLE, _admin); + _grantRole(PRIZE_REGISTRY_MANAGER, _admin); + ticketAddress = _ticketAddress; + } + function deposit721(IERC721 _token, uint256 _tokenId, uint256 _price) external nonReentrant { require(_token.ownerOf(_tokenId) == msg.sender, "You do not own this token"); require(_price > 0, "Price must be greater than 0"); _token.safeTransferFrom(msg.sender, address(this), _tokenId); - prizes.push(Prize({ - ercType: "ERC721", - tokenAddress: address(_token), - from: msg.sender, - tokenId: _tokenId, - amount: 1, - price: _price - })); - + availablePrizes[prizeCount] = Prize({ + ercType: ERCType.ERC721, + tokenAddress: address(_token), + from: msg.sender, + tokenId: _tokenId, + amount: 1, + price: _price + }); + prizeCount++; - emit Deposit("ERC721", address(_token), msg.sender, _tokenId, 1, _price); + emit Deposit(ERCType.ERC721, address(_token), msg.sender, _tokenId, 1, _price); } function deposit1155(IERC1155 _token, uint256 _tokenId, uint256 _amount, uint256 _price) external nonReentrant { - require(_amount <= _token.balanceOf(msg.sender, _tokenId), "You do not have enough of this token"); + require(_amount > 0 && _amount <= _token.balanceOf(msg.sender, _tokenId), "Invalid token amount"); require(_price > 0, "Price must be greater than 0"); _token.safeTransferFrom(msg.sender, address(this), _tokenId, _amount, ""); - prizes.push(Prize({ - ercType: "ERC1155", - tokenAddress: address(_token), - from: msg.sender, - tokenId: _tokenId, - amount: _amount, - price: _price - })); - - emit Deposit("ERC1155", address(_token), msg.sender, _tokenId, _amount, _price); + availablePrizes[prizeCount] = Prize({ + ercType: ERCType.ERC1155, + tokenAddress: address(_token), + from: msg.sender, + tokenId: _tokenId, + amount: _amount, + price: _price + }); + prizeCount++; + + emit Deposit(ERCType.ERC1155, address(_token), msg.sender, _tokenId, _amount, _price); } function deposit20(IERC20 _token, uint256 _amount, uint256 _price) external nonReentrant { - require(_amount <= _token.balanceOf(msg.sender), "You do not have enough of this token"); + require(_amount > 0 && _amount <= _token.balanceOf(msg.sender), "Invalid token amount"); require(_price > 0, "Price must be greater than 0"); _token.transferFrom(msg.sender, address(this), _amount); - prizes.push(Prize({ - ercType: "ERC20", - tokenAddress: address(_token), - from: msg.sender, - tokenId: 0, - amount: _amount, - price: _price - })); - - emit Deposit("ERC20", address(_token), msg.sender, 0, _amount, _price); + availablePrizes[prizeCount] = Prize({ + ercType: ERCType.ERC20, + tokenAddress: address(_token), + from: msg.sender, + tokenId: 0, + amount: _amount, + price: _price + }); + prizeCount++; + + emit Deposit(ERCType.ERC20, address(_token), msg.sender, 0, _amount, _price); + } + + function redeem(string memory _prizeId) public { + require(availablePrizes[_prizeId].from != address(0), "Prize does not exist"); + require(availablePrizes[_prizeId].price <= IERC20(ticketAddress).balanceOf(msg.sender), "Insufficient ticket balance"); + + if (availablePrizes[_prizeId].ercType == ERCType.ERC721) { + IERC721(availablePrizes[_prizeId].tokenAddress).safeTransferFrom(address(this), msg.sender, availablePrizes[_prizeId].tokenId); + } else if (availablePrizes[_prizeId].ercType == ERCType.ERC1155) { + IERC1155(availablePrizes[_prizeId].tokenAddress).safeTransferFrom(address(this), msg.sender, availablePrizes[_prizeId].tokenId, availablePrizes[_prizeId].amount, ""); + } else if (availablePrizes[_prizeId].ercType == ERCType.ERC20) { + IERC20(availablePrizes[_prizeId].tokenAddress).transfer(msg.sender, availablePrizes[_prizeId].amount); + } + + redeemedPrizes[_prizeId] = availablePrizes[_prizeId]; + delete availablePrizes[_prizeId]; + + emit Redeem(redeemedPrizes[_prizeId].ercType, redeemedPrizes[_prizeId].tokenAddress, msg.sender, redeemedPrizes[_prizeId].tokenId, redeemedPrizes[_prizeId].amount); + } + + function withdraw721(IERC721 _token, uint256 _tokenId) external onlyRole(PRIZE_REGISTRY_MANAGER) { + _token.safeTransferFrom(address(this), owner(), _tokenId); + } + + function withdraw1155(IERC1155 _token, uint256 _tokenId, uint256 _amount) external onlyRole(PRIZE_REGISTRY_MANAGER) { + _token.safeTransferFrom(address(this), owner(), _tokenId, _amount, ""); + } + + function withdraw20(IERC20 _token, uint256 _amount) external onlyRole(PRIZE_REGISTRY_MANAGER) { + _token.transfer(owner(), _amount); } } From a195e3e1c967fdca056cf1d4634d69321cab427a Mon Sep 17 00:00:00 2001 From: caleb Date: Thu, 30 May 2024 01:07:21 -0400 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chain/src/contracts/PrizeRegistry.sol | 55 +++++++++++++-------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/chain/src/contracts/PrizeRegistry.sol b/chain/src/contracts/PrizeRegistry.sol index 6aec177..5b8111b 100644 --- a/chain/src/contracts/PrizeRegistry.sol +++ b/chain/src/contracts/PrizeRegistry.sol @@ -14,8 +14,15 @@ contract PrizeRegistry is ERC1155Holder, ERC721Holder, ReentrancyGuard, AccessCo bytes32 public constant PRIZE_REGISTRY_MANAGER = keccak256("PRIZE_REGISTRY_MANAGER"); + enum ERCType { ERC721, ERC1155, ERC20 } + + struct Ticket { + address tokenAddress; + uint256 tokenId; + } + struct Prize { - string ercType; // ERC721 | ERC1155 | ERC20 + ERCType ercType; address tokenAddress; address from; uint256 tokenId; @@ -23,33 +30,19 @@ contract PrizeRegistry is ERC1155Holder, ERC721Holder, ReentrancyGuard, AccessCo uint256 price; } - event Deposit(string ercType, address tokenAddress, address from, uint256 tokenId, uint256 amount, uint256 price); - - Prize[] public prizes; - - enum ERCType { ERC721, ERC1155, ERC20 } - - struct Prize { - ERCType ercType; - address tokenAddress; - address from; - uint256 tokenId; - uint256 amount; - uint256 price; - } - event Deposit(ERCType ercType, address tokenAddress, address from, uint256 tokenId, uint256 amount, uint256 price); event Redeem(ERCType ercType, address tokenAddress, address to, uint256 tokenId, uint256 amount); + Ticket public ticket; + uint256 public prizeCount; - address public ticketAddress; - mapping(string => Prize) public availablePrizes; - mapping(string => Prize) public redeemedPrizes; + mapping(uint256 => Prize) public availablePrizes; + mapping(uint256 => Prize) public redeemedPrizes; - constructor(address _admin, address _ticketAddress) { + constructor(address _admin, Ticket memory _ticket) { _grantRole(DEFAULT_ADMIN_ROLE, _admin); _grantRole(PRIZE_REGISTRY_MANAGER, _admin); - ticketAddress = _ticketAddress; + ticket = _ticket; } function deposit721(IERC721 _token, uint256 _tokenId, uint256 _price) external nonReentrant { @@ -106,9 +99,9 @@ contract PrizeRegistry is ERC1155Holder, ERC721Holder, ReentrancyGuard, AccessCo emit Deposit(ERCType.ERC20, address(_token), msg.sender, 0, _amount, _price); } - function redeem(string memory _prizeId) public { + function redeem(uint256 _prizeId) public { require(availablePrizes[_prizeId].from != address(0), "Prize does not exist"); - require(availablePrizes[_prizeId].price <= IERC20(ticketAddress).balanceOf(msg.sender), "Insufficient ticket balance"); + require(availablePrizes[_prizeId].price <= IERC1155(ticket.tokenAddress).balanceOf(msg.sender, ticket.tokenId), "Insufficient ticket balance"); if (availablePrizes[_prizeId].ercType == ERCType.ERC721) { IERC721(availablePrizes[_prizeId].tokenAddress).safeTransferFrom(address(this), msg.sender, availablePrizes[_prizeId].tokenId); @@ -124,15 +117,19 @@ contract PrizeRegistry is ERC1155Holder, ERC721Holder, ReentrancyGuard, AccessCo emit Redeem(redeemedPrizes[_prizeId].ercType, redeemedPrizes[_prizeId].tokenAddress, msg.sender, redeemedPrizes[_prizeId].tokenId, redeemedPrizes[_prizeId].amount); } - function withdraw721(IERC721 _token, uint256 _tokenId) external onlyRole(PRIZE_REGISTRY_MANAGER) { - _token.safeTransferFrom(address(this), owner(), _tokenId); + function managerWithdraw721(IERC721 _token, uint256 _tokenId, address _to) external onlyRole(PRIZE_REGISTRY_MANAGER) { + _token.safeTransferFrom(address(this), _to, _tokenId); + } + + function managerWithdraw1155(IERC1155 _token, uint256 _tokenId, uint256 _amount, address _to) external onlyRole(PRIZE_REGISTRY_MANAGER) { + _token.safeTransferFrom(address(this), _to, _tokenId, _amount, ""); } - function withdraw1155(IERC1155 _token, uint256 _tokenId, uint256 _amount) external onlyRole(PRIZE_REGISTRY_MANAGER) { - _token.safeTransferFrom(address(this), owner(), _tokenId, _amount, ""); + function managerWithdraw20(IERC20 _token, uint256 _amount, address _to) external onlyRole(PRIZE_REGISTRY_MANAGER) { + _token.transferFrom(address(this), _to, _amount); } - function withdraw20(IERC20 _token, uint256 _amount) external onlyRole(PRIZE_REGISTRY_MANAGER) { - _token.transfer(owner(), _amount); + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155Holder, AccessControl) returns (bool) { + return ERC1155Holder.supportsInterface(interfaceId) || AccessControl.supportsInterface(interfaceId); } } From fc016f4004a0737cbe8bd49f5c74ef6c225ba8bc Mon Sep 17 00:00:00 2001 From: caleb Date: Thu, 30 May 2024 13:29:40 -0400 Subject: [PATCH 4/4] up --- chain/src/contracts/PrizeRegistry.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/chain/src/contracts/PrizeRegistry.sol b/chain/src/contracts/PrizeRegistry.sol index 5b8111b..17a7287 100644 --- a/chain/src/contracts/PrizeRegistry.sol +++ b/chain/src/contracts/PrizeRegistry.sol @@ -117,6 +117,7 @@ contract PrizeRegistry is ERC1155Holder, ERC721Holder, ReentrancyGuard, AccessCo emit Redeem(redeemedPrizes[_prizeId].ercType, redeemedPrizes[_prizeId].tokenAddress, msg.sender, redeemedPrizes[_prizeId].tokenId, redeemedPrizes[_prizeId].amount); } + // @note manager withdraw should take in an ID an remove from the mapping to withdraw function managerWithdraw721(IERC721 _token, uint256 _tokenId, address _to) external onlyRole(PRIZE_REGISTRY_MANAGER) { _token.safeTransferFrom(address(this), _to, _tokenId); }