bsc-genesis-contract holds the system contracts BNB Smart Chain boots from
The genesis contracts of BNB Smart Chain.
At a glance
- What is it?
- bsc-genesis-contract is the Solidity and Python source for the BNB Smart Chain genesis contracts, together with the scripts that generate a genesis.json for mainnet, testnet or a local dev net. It is a chain operator's tool: the contracts are already deployed, and what you build here is a new chain that starts from them.
- Who is it for?
- bsc-genesis-contract suits a team that wants to run a BNB Smart Chain style chain, a fork or a local dev net with the real system contracts rather than mock ones, since the contracts, the genesis template and the generation scripts are all in the repository. It is the wrong tool if you want to interact with BNB Smart Chain, because that is a matter of an RPC endpoint, and it is not a place to change live chain behaviour.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 42 days ago.
- What is it written in?
- Mainly Solidity, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The contracts a chain starts from
bsc-genesis-contract holds the genesis contracts of BNB Smart Chain, and the README points at the BNB Chain documentation for more detail on the system contracts. More details are available on the doc site.
The repository root shows the whole shape of the project. There is a contracts directory, an abi directory, a scripts directory, a test directory, a wbnb directory, and at the root the genesis files themselves: genesis.json, genesis-dev.json, genesis-testnet.json and genesis-template.json, which is the template the others are generated from. A foundry.toml holds the Solidity build configuration, a hardhat.config.ts holds the JavaScript side, and there is a pyproject.toml and poetry.lock for the Python scripts.
The lint scripts in package.json name the system contracts directly, which is the clearest inventory of what is in there: BSCTimelock.sol, GovToken.sol, BSCGovernor.sol, TokenRecoverPortal.sol, StakeCredit.sol, StakeHub.sol and SystemV2.sol. Those cover the governance token and its governor, the timelock, staking with its credit accounting, a token recovery escape hatch and the system contract that dispatches to the others.
The licence needs care. The README says the library is licensed under the Apache License, Version 2.0, and points to a LICENSE file in the repository, while the repository root listing shows a file named LICENCE. The GitHub licence field is not classified. The README and the file should be read together, and any specific question about the terms belongs with your own counsel.
Three toolchains, one repository
Preparing the project means installing three separate toolchains, and the README is explicit that you need all of them.
The Node.js dependencies come from npm:
```shell script npm install
The Solidity side needs Foundry, installed through the foundryup script and then the standard library:
shell script curl -L https://foundry.paradigm.xyz | bash foundryup forge install --no-git foundry-rs/[email protected]
And the Python scripts need Poetry:
shell script curl -sSL https://install.python-poetry.org | python3 - poetry install ```
There is also a tip for managing multiple Node versions, with nvm install 18.17.0 and nvm use 18.17.0 as the example.
That this project needs npm, Foundry and Poetry at once is a fair signal of what it is. The Solidity is compiled and tested with forge, the genesis generation scripts are Python, and some of the tooling around them is JavaScript. The package manifest shows the JavaScript dependencies, OpenZeppelin contracts and the upgradeable variant at ^4.9.3, commander, nunjucks for templating, rlp for the recursive length prefix encoding the chain state uses, and web3 at ^4.11.0, with ethers and ts-node in dev dependencies. The Python side is web3 6.11.4, jinja2 for the templates, typer for the command line, pyunormalize and setuptools.
Generating a genesis file for a local chain
The genesis generation is the part of the project a new user is most likely to touch, and the workflow is documented in a specific order.
First you edit the inputs. You edit init_holders.js to allocate the initial BNB holder, and you edit validators.js to allocate the initial validator set, and you edit the system contract settings as needed. Then you run node scripts/generate-genesis.js, which produces genesis.json.
The npm scripts wrap that for the three networks, and each one is followed by a Python step that cleans up:
```shell # build mainnet genesis file & clean npm run generate:mainnet && poetry run python -m scripts.generate recover
# build testnet genesis file & clean npm run generate:testnet && poetry run python -m scripts.generate recover
# build local dev-net genesis file & clean npm run generate:dev && poetry run python -m scripts.generate recover ```
The dev net variant is where the interesting parameters live, and package.json shows them in full: an init burn ratio, an init felony slash scope, the breathe block interval of 10 minutes, a block interval of 3 seconds, the unbond period of 2 minutes, a downtime jail time of 2 minutes, a felony jail time of 3 minutes, an init voting period of 2 minutes divided by the block interval, a governor protector address and a token recover portal protector address. The README points at generate:dev in package.json as the place to see how to customise parameters for a local dev net.
A block interval of 3 seconds is what makes a local chain usable, and it is worth remembering that every one of those governance timings is derived from it, so changing the block interval changes the meaning of the jail and voting periods.
Verifying the bytecode in genesis.json
The README includes a verification recipe, and it is the step that tells you whether the generated file matches the source in front of you.
The claim is that you can check the bytecode in genesis.json with solc, using StakeHub.sol as the example, with a specific compiler version pinned to 0.8.17 and a specific set of optimisation flags:
# you can verify the bytecode in genesis.json with solc, take ./contracts/StakeHub.sol for example:
solc-select use 0.8.17
solc --optimize --optimize-runs 200 --abi --metadata-hash none --bin-runtime ./contracts/StakeHub.sol --base-path . --include-path ./node_modules/ -o outputThe flags are not incidental. --optimize-runs 200 has to match what the build pipeline used, and --metadata-hash none is what makes the output byte comparable, since a metadata hash embeds a hash of the source paths and would differ between machines.
This is a good sign about how the project is put together. A genesis file that cannot be reproduced from the sources in the repository is a file you have to trust, and the verification step exists to remove that need.
The remaining chain-specific scripts are smaller. Flattening all system contracts is bash scripts/flatten.sh, with the output going into the flattened directory under contracts. The ABI files are refreshed with forge inspect {{contract}} abi redirected into the abi directory, and the test interface for a contract is generated from the compiled JSON with cast interface, targeting the ^0.8.0 compiler range and writing into the test utils interface directory.
Running the tests needs an archive node
The unit tests run against a fork of chain state rather than a local empty chain, and the README says you can get a free archive node endpoint from nodereal.io.
The test command is:
```shell script forge test --fork-url ${archive_node_rpc} ```
Forking a real archive node is the right way to test system contracts, because the behaviour of a validator or staking contract depends on the chain state it is deployed against, and a blank chain would not exercise that. The cost is that the test suite now depends on a third party service being reachable, which is a dependency most unit test suites try to avoid.
The BEP-171 automation script is a separate piece of tooling with its own setup: ts-node installed globally, the .env.example copied to .env, and the UNLOCK_RECEIVER and OPERATOR_PRIVATE_KEY variables set in it, then the script run with ts-node scripts/bep171-unlock-bot.ts. The .env.example also carries an RPC_BSC entry pointing at a dataseed endpoint, along with the two empty variables.
The release history shows the project still moving. v1.2.6, named Pasteur, was tagged on 2026-06-17, v1.2.5, Fermi, on 2025-11-04, and v1.2.4 on 2024-07-26. The last push was on 2026-09-11, and the repository is not archived.
Editorial conclusion
bsc-genesis-contract suits a team that wants to run a BNB Smart Chain style chain, a fork or a local dev net with the real system contracts rather than mock ones, since the contracts, the genesis template and the generation scripts are all in the repository. It is the wrong tool if you want to interact with BNB Smart Chain, because that is a matter of an RPC endpoint, and it is not a place to change live chain behaviour. Before using it, read the contract set in contracts/ and the parameters the generate:dev script exposes, and check the LICENSE file, since the repository carries both a LICENCE file and an Apache 2.0 statement in the README and the GitHub licence field is not classified.
Frequently asked questions
What is in the bsc-genesis-contract repository?
The Solidity source for the BNB Smart Chain genesis system contracts, including BSCTimelock, GovToken, BSCGovernor, TokenRecoverPortal, StakeCredit, StakeHub and SystemV2, together with the Python and JavaScript scripts that generate genesis.json for mainnet, testnet or a local dev net.
How do I generate a genesis file for a local BNB Smart Chain dev net?
Edit init_holders.js for the initial BNB holder and validators.js for the initial validator set, then run npm run generate:dev followed by poetry run python -m scripts.generate recover. The generate:dev script in package.json lists the chain parameters such as the 3 second block interval, the unbond period and the jail times.
How do I run the bsc-genesis-contract tests?
The README says you can get a free archive node endpoint from nodereal.io and then run forge test --fork-url ${archive_node_rpc}. The forge test suite forks real chain state, so the archive endpoint is what the tests read from.
Official sources
Was this useful?