Tokenspice
EVM agent-based token simulator ππͺοΈ
Install / Use
/learn @tokenspice/TokenspiceREADME
TokenSPICE: EVM Agent-Based Token Simulator
<div align="center"> <!-- Pytest and MyPy Badges --> <img alt="Pytest Unit Testing" src="https://github.com/tokenspice/tokenspice/actions/workflows/pytest.yml/badge.svg"> <img alt="MyPy Static Type Checking" src="https://github.com/tokenspice/tokenspice/actions/workflows/mypy.yml/badge.svg"> <!-- Codacy Badges --> </div>β Note: as of mid 2023, this codebase is not being maintained. It might work, it might not. If you find a bug, feel free to report it, but do not expect it to be fixed. If you do a PR where tests pass, we're happy to merge it. And feel free to fork this repo and change it as you wish (including bug fixes).
TokenSPICE simulates tokenized ecosystems via an agent-based approach, with EVM in-the-loop.
It can help in Token Engineering flows, to design, tune, and verify tokenized ecosystems. It's young but promising. We welcome you to contribute! π
- TokenSPICE simulates by simply running a loop. At each iteration, each agent in the netlist takes a step. That's it! Simple is good.
- A netlist wires up a collection of agents to interact in a given way.Β Each agent is a class. It has an Ethereum wallet, and does work to earn money. Agents may be written in pure Python, or with an EVM-based backend.
- One models a system by writing a netlist and tracking metrics (KPIs). One can write their own netlists and agents to simulate whatever they like. The netlists directory has examples.
Contents
- π Initial Setup
- π Running, Debugging
- π¦ Agents and Netlists
- π Updating Envt
- π‘ Backlog
- π Benefits of EVM Agent Simulation
- π¦ Resources
- π License
π Initial Setup
Prerequisites
- Linux/MacOS
- Python 3.8.5+
- solc 0.8.0+ [Instructions]
- ganache. To install:
npm install ganache --global - nvm 16.13.2, not nvm 17. To install:
nvm install 16.13.2; nvm use 16.13.2. [Details]
Install TokenSPICE
Open a new terminal and:
#clone repo
git clone https://github.com/tokenspice/tokenspice
cd tokenspice
#create a virtual environment
python3 -m venv venv
#activate env
source venv/bin/activate
#install dependencies
pip install -r requirements.txt
#install brownie packages (you can ignore FileExistsErrors)
./brownie-install.sh
Potential issues & workarounds
- Issue: Brownie doesn't support Python 3.11 yet. Workaround: before "install dependencies" step above, run
pip install vyper==0.3.7 --ignore-requires-pythonandsudo apt-get install python3.11-dev - Issue: MacOS might flag "Unsupported architecture". Workaround: install including ARCHFLAGS:
ARCHFLAGS="-arch x86_64" pip install -r requirements.txt
Run Ganache
From "Prerequisites", you should have Ganache installed.
Open a new console and go to tokenspice directory. Then:
source venv/bin/activate
./ganache.py
This will start a Ganache chain, and populate 9 accounts.
TokenSPICE CLI
tsp is the command-line interface for TokenSPICE.
Open a new console and go to tokenspice directory. Then:
source venv/bin/activate
#add pwd to bash path
export PATH=$PATH:.
#see tsp help
tsp
Compile the contracts
NOTE: if you have a directory named contracts from before, which is side-by-side with your tokenspice directory, you'll get issues. To avoid this, rename or move that contracts directory.
From the same terminal:
#install 3rd party libs, then call "brownie compile" in sol057/ and sol080/
tsp compile
TokenSPICE sees smart contracts as classes. How:
- When it starts, it calls
brownie.project.load('./sol057', name="MyProject")to load the ABIs in./sol057/build/. Similar forsol080. - That's enough info to treat each contract in
sol057/contracts/as a class. Then, calldeploy()on it to create a new object.
π Running, Debugging
Testing
From terminal:
#run single test. It uses brownie, which auto-starts Ganache local blockchain node.
pytest sol057/contracts/simpletoken/test/test_Simpletoken.py::test_transfer
#run all of a directory's tests
pytest sol057/contracts/simpletoken/test
#run all unit tests
pytest
#run static type-checking. By default, uses config mypy.ini. Note: pytest does dynamic type-checking.
mypy ./
#run linting on code style
pylint *
#auto-fix some pylint complaints
black ./
Go here for details on linting / style.
Simulating with TokenSPICE
From terminal:
#run simulation, sending results to 'outdir_csv' (clear dir first, to be sure)
rm -rf outdir_csv; tsp run netlists/scheduler/netlist.py outdir_csv
You'll see an output like:
Arguments: NETLIST=netlists/...
Launching 'ganache-cli --accounts 10 --hardfork ...
mnemonic: 'sausage bunker giant drum ...
INFO:master:Begin.
INFO:master:SimStrategy={OCEAN_funded=5.0, duration_seconds=157680000, ...}
INFO:master:Tick=0 (0.0 h, 0.0 d, 0.0 mo, 0.0 y); timestamp=1642844072; OCEAN_vested=0, ...
INFO:master:Tick=3 (2160.0 h, 90.0 d, 3.0 mo, 0.2 y); timestamp=1650620073; OCEAN_vested=0.0, ...
INFO:master:Tick=6 (4320.0 h, 180.0 d, 6.0 mo, 0.5 y); timestamp=1658396073; OCEAN_vested=0.0, ...
INFO:master:Tick=9 (6480.0 h, 270.0 d, 9.0 mo, 0.7 y); timestamp=1666172074; OCEAN_vested=0.0, ...
INFO:master:Tick=12 (8640.0 h, 360.0 d, 12.0 mo, 1.0 y); timestamp=1673948074; OCEAN_vested=0.0, ...
INFO:master:Tick=15 (10800.0 h, 450.0 d, 15.0 mo, 1.2 y); timestamp=1681724074; OCEAN_vested=0.232876 ...
Now, let's view the results visually. In the same terminal:
#create output plots in 'outdir_png' (clear dir first, to be sure)
rm -rf outdir_png; tsp plot netlists/scheduler/netlist.py outdir_csv outdir_png
#view plots
eog outdir_png
To see the blockchain txs apart from the other logs: open a new terminal and:
#activate env't
cd tokenspice
source venv/bin/activate
#run ganache
export PATH=$PATH:.
tsp ganache
Now, from your original terminal:
#run the sim. It will auto-connect to ganache
rm -rf outdir_csv; tsp run netlists/scheduler/netlist.py outdir_csv
For longer runs (eg wsloop), we can log to a file while watching the console in real-time:
#run the sim in the background, logging to out.txt
rm -rf outdir_csv; tsp run netlists/wsloop/netlist.py outdir_csv > out.txt 2>&1 &
#monitor in real-time
tail -f out.txt
To kill a sim in the background:
#find the background process
ps ax |grep "tsp run"
#example result:
#223429 pts/4 Rl 0:02 python ./tsp run netlists/wsloop/netlist.py outdir_csv
#to kill it:
kill 223429
Debugging from Brownie Console
Brownie console is a Python console, with some extra Brownie goodness, so that we can interactively play with Solidity contracts as Python classes, and deployed Solidity contracts as Python objects.
From terminal:
#brownie needs a directory with ./contracts/. Go to one.
cd sol057/
#start console
brownie console
In brownie console:
>>> st = Simpletoken.deploy("DT1", "Simpletoken 1", 18, Wei('100 ether'), {'from': accounts[0], "priority_fee": chain.priority_fee, "max_fee": chain.base_fee + 2 *
chain.priority_fee})
Transaction sent: 0x9d20d3239d5c8b8a029f037fe573c343efd9361efd4d99307e0f5be7499367ab
Gas price: 0.0 gwei Gas limit: 6721975
Simpletoken.constructor confirmed - Block: 1 Gas used: 601010 (8.94%)
Simpletoken deployed at: 0x3194cBDC3dbcd3E11a07892e7bA5c3394048Cc87
>>> st.symbol()
'DT1'
>>> st.balanceOf(accounts[0])/1e18
>>> dir(st)
[abi, address, allowance, approve, balance, balanceOf, bytecode, decimals, decode_input, get_method, get_method_object, info, name, selectors, signatures, symbol, topics, totalSupply, transfer, transferFrom, tx]
π¦ Agents and Netlists
Agents Basics
Agents are defined at agents/. Agents are in a separate directory than netlists, to facilitate reuse across many netlists.
All agents are written in Python. Some may include EVM behavior (more on this later).
Each Agent has an AgentWallet, which holds a Web3Wallet. The Web3Wallet holds a private key and creates transactions (txs).
Netlists Basics
The netlist defines what you simulate, and how.
Netlists are defined at netlists/. You can reuse existing netlists or create your own.
What A Netlist Definition MustΒ Hold
TokenSPICE expects a netlist module (in a netlist.py file) that defines these specific classes and functions:
SimStrategyclass: simulation run parametersKPIsclass andnetlist_createLogData()function: what metrics to log during the runnetlist_plotInstructions()function: how to plot the metrics after the run
