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

added some ceptor games in #1

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<br />
</div>

# 🏗🔴 Scaffold-OP
# 🏗🔴 Ceptor-Games-Scaffold

<h4 align="center">
<a href="https://docs.scaffoldeth.io">Documentation</a> |
Expand Down
137 changes: 137 additions & 0 deletions packages/hardhat/contracts/BuyMeACeptor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

/**
* @title World
* @dev World struct
*/
struct World {
string vibe;
string gameMasterName;
string gameMasterTwitterHandle;
string description;
uint256 time;
address gameMasterAddress;
}

/**
* @title BuyMeACeptorWorld
* @dev BuyMeACeptorWorld contract to accept donations and for our users to create a world for us
*/
contract BuyMeACeptor{
address payable public owner;
uint256 public price;
World[] public worlds;

error InsufficientFunds();
error InvalidArguments(string message);
error OnlyOwner();

event BuyMeACeptorWorldEvent(address indexed buyer, uint256 price);
event NewWorld(address indexed gameMasterAddress, uint256 time, string vibe, string gameMasterName, string gameMasterTwitterHandle, string description);

constructor() {
owner = payable(msg.sender);
price = 0.0001 ether;
}

/**
* WRITE FUNCTIONS *************
*/

/**
* @dev Function to buy a world
* @param gameMasterName The name of the game master
* @param gameMasterTwitterHandle The Twitter handle of the game master
* @param description The description of the world
* (Note: Using calldata for gas efficiency)
*/
function buyWorld(string calldata vibe, string calldata gameMasterName, string calldata gameMasterTwitterHandle, string calldata description) public payable {
if (msg.value < price) {
revert InsufficientFunds();
}

emit BuyMeACeptorWorldEvent(msg.sender, msg.value);

if (bytes(gameMasterName).length == 0 && bytes(description).length == 0) {
revert InvalidArguments("Invalid gameMasterName or description");
}

worlds.push(World(vibe, gameMasterName, gameMasterTwitterHandle, description, block.timestamp, msg.sender));

emit NewWorld(msg.sender, block.timestamp, vibe, gameMasterName, gameMasterTwitterHandle, description);
}

/**
* @dev Function to remove a world
* @param index The index of the world
*/
function removeWorld(uint256 index) public {
if (index >= worlds.length) {
revert InvalidArguments("Invalid index");
}

World memory world = worlds[index];

// if operation isnt sent from the same game master or the owner, then not allowed
if (world.gameMasterAddress != msg.sender && msg.sender != owner) {
revert InvalidArguments("Operation not allowed");
}

World memory indexWorld = worlds[index];
worlds[index] = worlds[worlds.length - 1];
worlds[worlds.length - 1] = indexWorld;
worlds.pop();
}

/**
* @dev Function to modify a world description
* @param index The index of the world
* @param description The description of the world
*/
function modifyWorldDescription(uint256 index, string memory description) public {
if (index >= worlds.length) {
revert InvalidArguments("Invalid index");
}

World memory world = worlds[index];

if (world.gameMasterAddress != msg.sender || msg.sender != owner) {
revert InvalidArguments("Operation not allowed");
}

worlds[index].description = description;
}

/**
* @dev Function to withdraw the balance
*/
function withdrawTips() public {
if (msg.sender != owner) {
revert OnlyOwner();
}

if (address(this).balance == 0) {
revert InsufficientFunds();
}

(bool sent,) = owner.call{value: address(this).balance}("");
require(sent, "Failed to send Ether");
}

/**
* READ FUNCTIONS *************
*/

/**
* @dev Function to get the worlds
*/
function getWorlds() public view returns (World[] memory) {
return worlds;
}

/**
* @dev Recieve function to accept ether
*/
receive() external payable {}
}
156 changes: 0 additions & 156 deletions packages/hardhat/contracts/BuyMeACoffee.sol

This file was deleted.

90 changes: 90 additions & 0 deletions packages/hardhat/contracts/CeptorCS.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";

contract CeptorCharacterSheets is ERC721URIStorage, VRFConsumerBaseV2, Ownable {
struct Stats {
uint8 strength;
uint8 dexterity;
uint8 constitution;
uint8 intelligence;
uint8 wisdom;
uint8 charisma;
uint8 luck;
}

struct Character {
Stats stats;
string name;
uint swapsLeft;
}

mapping(address => uint256) public ownerToTokenId;
mapping(uint256 => Character) public tokenIdToCharacter;

uint256 public tokenIdCounter;
bytes32 public keyHash;
uint256 public fee;
uint64 public subscriptionId;

event CharacterCreated(uint256 indexed tokenId, address owner);
event StatsSwapped(uint256 indexed tokenId, address owner);

constructor(
address vrfCoordinator,
address linkToken,
bytes32 _keyHash,
uint64 _subscriptionId
)
VRFConsumerBaseV2(vrfCoordinator)
ERC721("CeptorCharacterSheets", "CCS")
{
keyHash = _keyHash;
fee = 0.1 * 10**18; // Chainlink VRF fee
subscriptionId = _subscriptionId;
tokenIdCounter = 1;
}

function createCharacter(string memory name) external {
require(ownerToTokenId[msg.sender] == 0, "Owner already has a character");
uint256 tokenId = tokenIdCounter++;
ownerToTokenId[msg.sender] = tokenId;
tokenIdToCharacter[tokenId] = Character({
name: name,
stats: Stats(0, 0, 0, 0, 0, 0, 0),
swapsLeft: 3
});
_safeMint(msg.sender, tokenId);
emit CharacterCreated(tokenId, msg.sender);
requestStats(tokenId);
}

function requestStats(uint256 tokenId) internal {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK");
requestRandomWords(keyHash, subscriptionId, 3, fee, 1);
}

function fulfillRandomWords(uint256, uint256[] memory randomWords) internal override {
uint256 tokenId = ownerToTokenId[msg.sender];
Character storage character = tokenIdToCharacter[tokenId];
character.stats.strength = uint8(randomWords[0] % 16 + 3);
character.stats.dexterity = uint8(randomWords[1] % 16 + 3);
character.stats.constitution = uint8(randomWords[2] % 16 + 3);
character.stats.intelligence = uint8(randomWords[3] % 16 + 3);
character.stats.wisdom = uint8(randomWords[4] % 16 + 3);
character.stats.charisma = uint8(randomWords[5] % 16 + 3);
character.stats.luck = uint8(randomWords[6] % 16 + 3);
}

function swapStats(uint256 tokenId) external {
require(ownerOf(tokenId) == msg.sender, "Not the owner");
Character storage character = tokenIdToCharacter[tokenId];
require(character.swapsLeft > 0, "No swaps left");
character.swapsLeft--;
requestStats(tokenId);
emit StatsSwapped(tokenId, msg.sender);
}
}
Loading
Loading