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

Biocash contracts #6

Open
wants to merge 19 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
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
# Biocash

Biocash is an in-game currency for Biome-1. You can join the economy by enabling the hook here: https://biocash-scaffold.onrender.com/

Placing certain items in a chest will mint you new biocash coins, an ERC-20 on the restone L2 network.

Biocash is a normal erc-20 token deployed here: https://explorer.redstone.xyz/address/0x55d53Cb744d9948D0ffD4DDB6b23d274278F933D

## Features
- Buying items from a chest will always cost 1.1x + 1 as much as selling them.
- Admin can set the price of any item in biocash
- New biocash is minted when players sell an item, and biocash is burned from the users wallet (sent to 0 address) when they buy and item.
- Admin can update the biocash token address in the hook to deploy new currencies.
- Admin can update the hook address in biocash to deploy new hooks with more features in the future.

<hr>

# Biomes AW Extensions Template

An easy to use template for creating extensions in Biomes.
Expand Down
25,335 changes: 25,335 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

65 changes: 64 additions & 1 deletion packages/hardhat/contracts/Game.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,37 @@ import { BEFORE_CALL_SYSTEM, AFTER_CALL_SYSTEM, ALL } from "@latticexyz/world/sr
import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol";
import { OptionalSystemHooks } from "@latticexyz/world/src/codegen/tables/OptionalSystemHooks.sol";

import { hasBeforeAndAfterSystemHook, getEntityAtCoord, getEntityFromPlayer, getPosition, getIsLoggedOff, getPlayerFromEntity } from "../utils/EntityUtils.sol";

import { IWorld } from "@biomesaw/world/src/codegen/world/IWorld.sol";
import { VoxelCoord } from "@biomesaw/utils/src/Types.sol";

import {Biocash} from "./biocash.sol";

contract Game is ICustomUnregisterDelegation, IOptionalSystemHook {
address public immutable biomeWorldAddress;

address public delegatorAddress;

address public biocashAddress = 0x55d53Cb744d9948D0ffD4DDB6b23d274278F933D;
Biocash biocash = Biocash(biocashAddress);

//money money money
mapping(address => bool) isAdmin;
mapping(uint256 => uint16) valueTable;

constructor(address _biomeWorldAddress, address _delegatorAddress) {
biomeWorldAddress = _biomeWorldAddress;
isAdmin[msg.sender] = true;
isAdmin[0x95E9A0c113AA9931a4230f91AdE08A491D3f8d54] = true;

// Set the store address, so that when reading from MUD tables in the
// Biomes world, we don't need to pass the store address every time.
StoreSwitch.setStoreAddress(_biomeWorldAddress);

delegatorAddress = _delegatorAddress;

valueTable[37] = 1;
}

// Use this modifier to restrict access to the Biomes World contract only
Expand Down Expand Up @@ -72,7 +87,34 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook {
address msgSender,
ResourceId systemId,
bytes memory callData
) external override onlyBiomeWorld {}
) external override onlyBiomeWorld {

//get transfer data
Slice callDataArgs = SliceLib.getSubslice(callData, 4);
address player = msgSender;
//function transfer(bytes32 srcEntityId, bytes32 dstEntityId, uint8 transferObjectTypeId, uint16 numToTransfer);
bytes32 sourceEntityID;
bytes32 destinationEntityID;
uint8 itemTypeID;
uint16 numToTransfer;

(sourceEntityID, destinationEntityID, itemTypeID, numToTransfer)= abi.decode(callDataArgs.toBytes(), (bytes32, bytes32, uint8, uint16));

//if transfer from player to chest
//add money
//mint tokens
address playerAddress = msgSender;
if(getPlayerFromEntity(sourceEntityID) == playerAddress){
//player is the sender
biocash.mint(playerAddress, numToTransfer * valueTable[itemTypeID]);
}

//if transfer from chest to player
if(getPlayerFromEntity(destinationEntityID) == playerAddress){
//remove tokens. buy price is (1.1 * sell price) + 1
biocash.transferFrom(playerAddress, address(0), 1 + (valueTable[itemTypeID] * 11/10) );
}
}

function basicGetter() external view returns (uint256) {
return 42;
Expand All @@ -81,4 +123,25 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook {
function getRegisteredPlayers() external view returns (address[] memory) {
return new address[](0);
}

//Name of Experience
function getDisplayName() external view returns (string memory){
return "Biocash";
}

//Optional: Dynamic Instructions to Show Player
function getStatus() external view returns (string memory){
string memory display = "Biocash: ";
uint256 balance = biocash.balanceOf(msg.sender);
string memory balanceStr = string(abi.encodePacked(balance)); // Convert balance to string
if(balance == 0){
return "Biocash: 0. Get Biocash by setlling items to chests.";
}
return string(abi.encodePacked(display, balanceStr));
}

function updateValueTable(uint itemID, uint16 _newValue) external{
require(isAdmin[msg.sender] == true);
valueTable[itemID] = _newValue;
}
}
39 changes: 39 additions & 0 deletions packages/hardhat/contracts/biocash.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";

contract Biocash is ERC20, Ownable, ERC20Permit {

address public bioGameContractAddress;

constructor(address initialOwner)
ERC20("Biocash", "BCASH")
Ownable()
ERC20Permit("Biocash")
{
_mint(msg.sender, 1000000 * 10 ** decimals());
}

function setBiomeHook(address newBiomeAddress) external onlyOwner{
bioGameContractAddress = newBiomeAddress;
}

function mint(address to, uint256 amount) public {
require(msg.sender == owner() || msg.sender == bioGameContractAddress);
_mint(to, amount);
}

/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
if(spender == bioGameContractAddress){
return 100 * 10 ** decimals(); //Game can always remove your tokens, for when player pulls items out of the chest
}
return super.allowance(owner, spender);
}
}
2 changes: 1 addition & 1 deletion packages/hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"ethers": "^6.10.0",
"hardhat": "^2.19.4",
"hardhat": "^2.22.3",
"hardhat-deploy": "^0.11.45",
"hardhat-deploy-ethers": "^0.4.1",
"hardhat-gas-reporter": "^1.0.9",
Expand Down
47 changes: 30 additions & 17 deletions packages/nextjs/components/Landing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,40 @@ export const Landing: React.FC = ({}) => {
</div>
<div className="grid grid-cols-12 flex flex-1">
<div className="col-span-12 lg:col-span-9 p-12 flex flex-col justify-between items-center">
<div style={{ width: "80%" }}>
<h1 className="text-3xl font-bold text-left mt-4">Your Game Title</h1>
<h1 className="text-left mt-4" style={{ lineHeight: "normal", margin: "0", wordWrap: "break-word" }}>
Your game description
</h1>

<div style={{ width: "80%"}}>

<div style={{display: "flex",justifyContent: "space-between", alignItems: "row"}}>
<div>
<h1 className="text-3xl font-bold text-left mt-4">Biocash</h1>
<h1 className="text-left mt-4" style={{ lineHeight: "normal", margin: "0", wordWrap: "break-word" }}>
Introducing a digital currency to the ecosystem of Biomes.
</h1>
</div>
<img src="/Biocash.png" alt="Biocash token" style={{ width: "auto", height: "100px" }} />

</div>
<div
style={{
border: "1px solid white",
width: "100%",
height: "500px", // Adjust the height as needed
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: "#000", // Optional: Background color
color: "#fff", // Text color
fontSize: "20px", // Adjust font size as needed
}}
style={{
border: "1px solid white",
width: "auto", // Let width remain auto
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: "#000", // Optional: Background color
color: "#fff", // Text color
fontSize: "20px", // Adjust font size as needed
overflow: "hidden", // Keeps everything neat
marginBottom: "30px",
}}
className="mt-4"
>
Your Game Image
<img src="/BiocashMarket.png" alt="Biomes market" style={{ width: "100%", height: "auto",}} />

</div>
<p>
Biocash enhances the economic aspect of Biomes fully on-chain interactive voxel experience. The token enables players to engage in sophisticated trading activities, allowing them to buy, sell, or barter items with NPC merchants within the game's expansive open world. By integrating Biocash Biomes transforms into a dynamic economic platform where players can experience the value and impact of a digital economy in a virtual setting.
</p>
</div>
</div>
<div
Expand Down
6 changes: 4 additions & 2 deletions packages/nextjs/components/RegisterBiomes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
import { useGlobalState } from "~~/services/store/store";
import { getAllContracts } from "~~/utils/scaffold-eth/contractsData";

const GameRequiredHooks: string[] = ["LogoffSystem"];
const contractsData = getAllContracts();

const GameRequiredHooks: string[] = ["TransferSystem"];

export const RegisterBiomes: React.FC = ({}) => {
const { address: connectedAddress } = useAccount();
Expand Down Expand Up @@ -87,7 +89,7 @@ export const RegisterBiomes: React.FC = ({}) => {
<h3 className="text-xl font-bold text-left mt-8">HOOKS</h3>
<CardSection
relevantSystems={GameRequiredHooks}
description={"Description of why you need the player to register the hooks on LogoffSystem"}
description={"We need the TransferSystem to transfer the items into a chest in order to sell it"}
>
<RegisterHookButton
hookAddress={contractsData["Game"].address}
Expand Down
2 changes: 1 addition & 1 deletion packages/nextjs/contracts/deployedContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ const deployedContracts = {
},
17069: {
Game: {
address: "0xB1f332427AdE17d97686395cB109B216A2B51F03",
address: "0xCdb63c58b907e76872474A0597C5252eDC97c883",
abi: [
{
inputs: [
Expand Down
4 changes: 2 additions & 2 deletions packages/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
"dependencies": {
"@biomesaw/utils": "0.0.8",
"@biomesaw/world": "0.0.8",
"@heroicons/react": "^2.0.11",
"@latticexyz/common": "2.0.8",
"@latticexyz/utils": "2.0.8",
"@latticexyz/world": "2.0.8",
"@heroicons/react": "^2.0.11",
"@rainbow-me/rainbowkit": "^2.0.2",
"@tanstack/react-query": "^5.28.6",
"@uniswap/sdk-core": "^4.0.1",
Expand Down Expand Up @@ -53,9 +53,9 @@
"eslint-config-next": "^14.0.4",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"prettier-plugin-solidity": "1.1.3",
"postcss": "^8.4.16",
"prettier": "^2.8.4",
"prettier-plugin-solidity": "1.1.3",
"tailwindcss": "^3.4.3",
"type-fest": "^4.6.0",
"typescript": "^5.1.6",
Expand Down
Binary file added packages/nextjs/public/Biocash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/nextjs/public/BiocashMarket.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/nextjs/public/biocashlanding.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading