Skip to content

Commit

Permalink
Merge pull request #1 from bugout-dev/inventory
Browse files Browse the repository at this point in the history
An Inventory system for web3 games
  • Loading branch information
ogarciarevett authored Jan 11, 2023
2 parents ecef34a + 456ec8e commit 2c04437
Show file tree
Hide file tree
Showing 37 changed files with 8,200 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.sol linguist-language=Solidity
*.vy linguist-language=Python
151 changes: 151 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

#Node
node_modules/
yarn.lock
package-lock.json

#next
.next/

# Custom
.venv/
.game7/
.secrets/
.vscode/

prod.env
test.env
dev.env
prod.test.env
dev.test.env

scratch/
147 changes: 147 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,149 @@
# contracts

Main repo for Game7 contracts

## Setup

### Using Python and [eth-brownie](https://github.com/eth-brownie/brownie)

First, set up a Python3 environment:

- Check if you have Python3 installed on your system: `python3 --version`.
- If the above command errors out, you need to install Python3. You can find instructions for how to
do this at https://python.org.
- Create a Python virtual environment in the root of this directory: `python3 -m venv .game7`
- Activate the virtual environment: `source .game7/bin/activate` (when you are finished working in this
code base, you can deactivate the virtual environment using the `deactivate` command).
- Install the `game7ctl` package: `pip install -e game7ctl/`

Following these steps will make the `game7ctl` command available in your shell. You can use this command-line
tool to deploy and interact with the smart contracts in this repository. For more details:

```
game7ctl --help
```

#### Development

To compile the smart contracts using `brownie`, run the following command from the project root directory:

```
brownie compile
```

To set up a *development* environment, you have to also install the developer dependencies using:

```
pip install -e "game7ctl/[dev]"
```

You can then run Python tests by invoking:

```
bash game7ctl/test.sh
```

If you make a change to any of the smart contracts in the [`contracts/`](./contracts/) directory, you
can regenerate the Python interface to that contract using:

```
moonworm generate-brownie -p . -o game7ctl/game7ctl -n $CONTRACT_NAME
```

For example, after modifying `InventoryFacet`, you would run:

```
moonworm generate-brownie -p . -o game7ctl/game7ctl -n InventoryFacet
```

- - -

## Deploying contracts

### `game7ctl`

Once you have set up `game7ctl`, you can use it to deploy the contracts in this repository. For example,
to deploy the Inventory contract as a Diamond proxy, you would use the `game7ctl core inventory-gogogo` command.

To see all the parameters you can pass in the deployment, run:

```
$ game7ctl core inventory-gogogo --help
usage: game7ctl inventory-gogogo [-h] --network NETWORK [--address ADDRESS] --sender SENDER [--password PASSWORD] [--gas-price GAS_PRICE] [--max-fee-per-gas MAX_FEE_PER_GAS]
[--max-priority-fee-per-gas MAX_PRIORITY_FEE_PER_GAS] [--confirmations CONFIRMATIONS] [--nonce NONCE] [--value VALUE] [--verbose] --admin-terminus-address
ADMIN_TERMINUS_ADDRESS --admin-terminus-pool-id ADMIN_TERMINUS_POOL_ID --subject-erc721-address SUBJECT_ERC721_ADDRESS
[--diamond-cut-address DIAMOND_CUT_ADDRESS] [--diamond-address DIAMOND_ADDRESS] [--diamond-loupe-address DIAMOND_LOUPE_ADDRESS]
[--ownership-address OWNERSHIP_ADDRESS] [--inventory-facet-address INVENTORY_FACET_ADDRESS] [-o OUTFILE]
Deploy Inventory diamond contract
options:
-h, --help show this help message and exit
--network NETWORK Name of brownie network to connect to
--address ADDRESS Address of deployed contract to connect to
--sender SENDER Path to keystore file for transaction sender
--password PASSWORD Password to keystore file (if you do not provide it, you will be prompted for it)
--gas-price GAS_PRICE
Gas price at which to submit transaction
--max-fee-per-gas MAX_FEE_PER_GAS
Max fee per gas for EIP1559 transactions
--max-priority-fee-per-gas MAX_PRIORITY_FEE_PER_GAS
Max priority fee per gas for EIP1559 transactions
--confirmations CONFIRMATIONS
Number of confirmations to await before considering a transaction completed
--nonce NONCE Nonce for the transaction (optional)
--value VALUE Value of the transaction in wei(optional)
--verbose Print verbose output
--admin-terminus-address ADMIN_TERMINUS_ADDRESS
Address of Terminus contract defining access control for this GardenOfForkingPaths contract
--admin-terminus-pool-id ADMIN_TERMINUS_POOL_ID
Pool ID of Terminus pool for administrators of this GardenOfForkingPaths contract
--subject-erc721-address SUBJECT_ERC721_ADDRESS
Address of ERC721 contract that the Inventory modifies
--diamond-cut-address DIAMOND_CUT_ADDRESS
Address to deployed DiamondCutFacet. If provided, this command skips deployment of a new DiamondCutFacet.
--diamond-address DIAMOND_ADDRESS
Address to deployed Diamond contract. If provided, this command skips deployment of a new Diamond contract and simply mounts the required facets onto the existing
Diamond contract. Assumes that there is no collision of selectors.
--diamond-loupe-address DIAMOND_LOUPE_ADDRESS
Address to deployed DiamondLoupeFacet. If provided, this command skips deployment of a new DiamondLoupeFacet. It mounts the existing DiamondLoupeFacet onto the Diamond.
--ownership-address OWNERSHIP_ADDRESS
Address to deployed OwnershipFacet. If provided, this command skips deployment of a new OwnershipFacet. It mounts the existing OwnershipFacet onto the Diamond.
--inventory-facet-address INVENTORY_FACET_ADDRESS
Address to deployed InventoryFacet. If provided, this command skips deployment of a new InventoryFacet. It mounts the existing InventoryFacet onto the Diamond.
-o OUTFILE, --outfile OUTFILE
(Optional) file to write deployed addresses to
```

#### Notes on arguments

##### `--network`

`--network` should be a `brownie` network. You can add networks to `brownie` using the `brownie networks add` command.

For example, to add a new Polygon RPC endpoint, you would run:

```
brownie networks add Polygon $NETWORK_NAME host=$JSONRPC_URL chainid=137 explorer=https://api.polygonscan.com/api multicall2=0xc8E51042792d7405184DfCa245F2d27B94D013b6
```

The only keys which are not optional are `chainid` and `host`.

Then, you could pass `--network $NETWORK_NAME` as an argument to `game7ctl core inventory-gogogo`.

##### `--sender`

The CLI says that `--sender` should be a keystore file, but it can also be a `brownie account`. To import
an existing Ethereum account into `brownie`, use:

```
brownie accounts new $ACCOUNT_NAME
```

This will prompt you for the account private key and a password with which to encrypt the account on disk.

Then you can pass `--sender $ACCOUNT_NAME` to `game7ctl`.

The preferred way of using `--sender` is still by passing a keystore file.

`brownie` will always prompt you to unlock the account with a password.
12 changes: 12 additions & 0 deletions brownie-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
dependencies:
- "OpenZeppelin/[email protected]"
- "bugout-dev/[email protected]"
- "bugout-dev/[email protected]"

compiler:
solc:
remappings:
- "@openzeppelin-contracts=OpenZeppelin/[email protected]"
- "@openzeppelin/contracts=OpenZeppelin/[email protected]"
- "@moonstream=bugout-dev/[email protected]"
- "@moonstream-engine=bugout-dev/[email protected]"
58 changes: 58 additions & 0 deletions contracts/diamond/Diamond.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Adapted from the Diamond 3 reference implementation by Nick Mudge:
// https://github.com/mudgen/diamond-3-hardhat

import {LibDiamond} from "./libraries/LibDiamond.sol";
import {IDiamondCut} from "./interfaces/IDiamondCut.sol";

contract Diamond {
constructor(address _contractOwner, address _diamondCutFacet) payable {
LibDiamond.setContractOwner(_contractOwner);

// Add the diamondCut external function from the diamondCutFacet
IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1);
bytes4[] memory functionSelectors = new bytes4[](1);
functionSelectors[0] = IDiamondCut.diamondCut.selector;
cut[0] = IDiamondCut.FacetCut({
facetAddress: _diamondCutFacet,
action: IDiamondCut.FacetCutAction.Add,
functionSelectors: functionSelectors
});
LibDiamond.diamondCut(cut, address(0), "");
}

// Find facet for function that is called and execute the
// function if a facet is found and return any value.
fallback() external payable {
LibDiamond.DiamondStorage storage ds;
bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION;
// get diamond storage
assembly {
ds.slot := position
}
// get facet from function selector
address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress;
require(facet != address(0), "Diamond: Function does not exist");
// Execute external function from facet using delegatecall and return any value.
assembly {
// copy function selector and any arguments
calldatacopy(0, 0, calldatasize())
// execute function call using the facet
let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
// get any return value
returndatacopy(0, 0, returndatasize())
// return any return value or error back to the caller
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}

receive() external payable {}
}
Loading

0 comments on commit 2c04437

Please sign in to comment.