
Heimdall is an advanced EVM toolkit which aims to make dealing with smart contracts on EVM based chains easier.
Installation & Usage
Ensure that Rust & Cargo are installed:
curl https://sh.rustup.rs -sSf | sh
Heimdall's update and installation manager, bifrost
, can be installed using the following command:
curl -L http://get.heimdall.rs | bash
Alternatively, you can install through GitHub directly using the following command:
curl -L https://raw.githubusercontent.com/Jon-Becker/heimdall-rs/main/bifrost/install | bash
If you want to manually install bifrost, you can download the latest release from here.
Once you have installed bifrost
, you can use it to install Heimdall using the following command from a new terminal:
bifrost
After compilation, the heimdall
command will be available to use from a new terminal. For advanced options, see the bifrost documentation.
Having trouble? Check out the Troubleshooting section in the wiki.
Documentation
Documentation for all of heimdall-rs is available in the wiki.
Examples
Examples for heimdall-rs modules are available in the wiki.
Contributing
If you'd like to contribute to Heimdall or add a module, please open a pull-request with your changes, as well as detailed information on what is changed, added, or improved.
For more detailed information, see the contributing guide.
Issues
If you've found an issue or have a question, please open an issue here. All issues must follow their respective templates.
Credits
A list of all contributors can be found in the wiki.
Heimdall is an advanced Ethereum smart contract toolkit for forensic and heuristic analysis.
nft-generator-py

nft-generator-py is a python based NFT generator which programatically generates unique images using weighted layer files. The program is simple to use, and new layers can be added by adding a new layer object and adding names, weights, and image files to the object.
You can View The Demo here.
Usage
As of v2.0.0, nft-generator-py will use the argparse library in order to support external configuration files and won't require users to interact with the python files themselves.
-
Install requirements: python3 -m pip install -r requirements.txt
-
Make a configuration JSON file. See the configuration section below for specifications.
-
Add layer files into the /images
folder.
-
Run the command python3 generate.py --amount AMOUNT --config CONFIG
where:
AMOUNT
is the amount of images to generate
CONFIG
is the path pointing to a .json
file containing valid program configuration.
How it works
- A call to
generate_unique_images(amount, config)
is made, which is the meat of the application where all the processing happens.
- The
config
object is read and for each object in the layers
list, random values are selected and checked for uniqueness against all previously generated metadata files.
- Once we have
amount
unique tokens created, we layer them against eachother and output them and their metadata to their respective folders, ./metadata
and ./images
.
Configuration
{
"layers": [
{
"name": "Background",
"values": ["Blue", "Orange", "Purple", "Red", "Yellow"],
"trait_path": "./trait-layers/backgrounds",
"filename": ["blue", "orange", "purple", "red", "yellow"],
"weights": [30, 45, 15, 5, 10]
},
...
],
"incompatibilities": [
{
"layer": "Background",
"value": "Blue",
"incompatible_with": ["Python Logo 2"],
"default": {
"value": "Default Incompatibility",
"filename": "./trait-layers/foreground/logo"
}
}
],
"baseURI": ".",
"name": "NFT #",
"description": "This is a description for this NFT series."
}
The config
object is a dict that contains configuration instructions that can be changed to produce different outputs when running the program. Within metadata files, tokens are named using the configuration's name
parameter, and described using the description
parameter.
- In ascending order, tokenIds are appended to the
name
resulting in NFT metadata names such as NFT #0001.
- tokenIds are padded to the largest amount generated. IE, generating 999 objects will result in names NFT #001, using the above configuration, and generating 1000 objects will result in NFT #0001.
- As of
v1.0.2
, padding filenames has been removed.
The layers
list contains layer
objects that define the layers for the program to use when generating unique tokens. Each layer
has a name, which will be displayed as an attribute, values, trait_path, filename, and weights.
trait_path
refers to the path where the image files in filename
can be found. Please note that filenames omit .png, and it will automatically be prepended.
weight
corresponds with the percent chance that the specific value that weight corresponds to will be selected when the program is run. The weights must add up to 100, or the program will fail.
The incompatibilities
list contains an object that tells the program what layers are incompatible with what. In the above configuration, A Blue Background layer
will never be generated with Python Logo 2.
layer
refers to the targeted layer.
value
is the value of the layer that is incompatible with attributes within the incompatible_with
list.
incompatible_with
is the list of incompatible layers that will never be selected when layer
has attribute value
.
- An optional
default
object can be provided to each incompatibility. This object will be selected 100% of the time if present and an incompatible layer is selected. The default
object has a value
and filename
attribute.
value
is the name of the default selection which will be displayed in the metadata.
filename
is the path to the image file that will be used as the default selection.
As of v1.0.2
, the IPFS CID may be updated programatically after generating NFTs and uploading /images
to IPFS. This will update all metadata files to correctly point "image"
to the IPFS CID.
- This is an optional step, and can be exited safely using
enter
or control + c
.
Troubleshooting
- All images should be in .png format.
- All images should be the same size in pixels, IE: 1000x1000.
- The weight values for each attribute should add up to equal 100.
Credits
This project is completely coded by Jonathan Becker, using no external libraries.
nft-generator-py allows users to generate sets of unique images & corresponding metadata using weighted layer collections.
renoun

Renoun is a project inspired by the work of @achalvs which allows for automatic minting of non-transferrable tokens on Ethereum based chains.
I've deployed the contracts on Optimism for free use, and for demonstration purposes. Feel free to open a Pull Request to this repository to test out the minting!
Check out tokenURI()
for _tokenIds
4 and above (the renderer was broken before then).
Installation
-
First, clone this repository using
git clone https://github.com/Jon-Becker/renoun.git .
-
Deploy both the BadgeRenderer.sol
and renoun.sol
contracts onto your chain of choice. The renderer contract is very large, 10kb+, so I recommend deploying on a L2.
- When deploying renoun.sol, you'll need to specify the deployed renderer address
-
On your repository of choice, set up 3 GitHub Secrets
PRIVATE_KEY
- which stores the private key of the deploying address
RPC_URL
- which stores the full RPC url of your web3 provider
DEPLOYMENT_ADDRESS
- which stores the deployment address of renoun.sol
-
Copy src/scripts
and src/json
to your repository, and create a GitHub action with the script from mint_token.yml
.
-
Edit the chain ID on line 60 of main.py
-
Profit.
Pull Request Standard
In order for the GitHub action to work properly, the Pull Request must be closed and merged. It must also contain a 20 byte Ethereum address, which main.py
will extract from the pull request and mint the token to.
For a full demo, you can check out Pull Request #3
Credits
On-chain, non-transferrable badges for GitHub contributions.
Heimdall [DEPRECATED]

Heimdall is an advanced and modular smart-contract toolkit which aims to make dealing with smart contracts on EVM based chains easier.
THIS REPOSITORY IS DEPRECATED AND WILL NOT BE UPDATED OR SUPPORTED AS OF JUN 24, 2022.
Installation & Usage

pip install eth-heimdall
Heimdall operates off the argparse
library, with modules specifying which operation you with to perform.
heimdall MODULE [-v] [--default] [-arguments]
Modules & Help
You may find the various modules supported by Heimdall by using the -h option, which opens the help menu by default.
Options:
-h, --help Show the help message and exit
-hh Show advanced help message and exit
--version Display version information and exit
--update Updates heimdall to the latest release
-v, --verbose Toggle verbose output
Modules:
Below is a list of modules currently supported on Heimdall
# | Name | Description
| |
0 | Config | Easily modify the configuration on Heimdall
1 | Debug | Easily access Heimdall debug information
2 | Decompile | Decompile and download the target smart contract
Parameters:
-m MODULE, --module MODULE Operation module, either name or number from list
-t TARGET, --target TARGET Target of operation (file, transaction id,
or address)
-o PATH, --output PATH Path to write output to
-c ID, --chain ID Chain ID of target
-p URL, --provider URL URL of custom Ethereum provider
Additional:
--open, --edit Attempts to open nano / edit on the operation
--redeploy ID Redeploys the contract from -n onto ID
--beautify Attempts to beautify the downloaded contract using
statistical renaming and spacing
--default Always use defaults when prompted for input
--flush, --ignore-cache Flushes the cache and rewrites it
Please keep in mind as more modules are released, module numbers may change. It's recommended to use the module name instead.
Module Documentation
Specific module documentation can be found in the /docs
folder, or quickly navigate using the links beow.
Configuration
You may save environment information, such as remote and local providers, to the configuration folder in env/conf.json
.
Contributing
If you'd like to contribute to Heimdall or add a module, please open a pull-request with your changes, as well as detailed information on what is changed, added, or improved.
Modules
To add a module, you must add a .py
file within the /lib/modules
folder. In order for your pull-request to be accepted, your module must begin with a meta
object, which is used when displaying what it does to end-users.
Example meta object:
meta = {
"title": "Decompile",
"description": "Decompile and download the target smart contract",
"author": "Jonathan Becker <jonathan@jbecker.dev>",
"version": "v1.0.0",
}
You will also need to add detailed documentation to this readme file in the Module Documentation
section.
Troubleshooting
If you encounter an issue, please create one using the link below. You MUST follow the issue format, or it will be marked as invalid.
Issues that remain inactive for 72 hours will be marked inactive and closed. If your issue is accepted by a contributor, they will assign themselves to it and add corresponding tags.
Credits
This project is coded in its entirety by Jonathan Becker. Various contributors can be found in the sidebar.
Powerful Ethereum Smart-Contract Toolkit
Recurring Payments on Ethereum

Recurring payments on the blockchain have been a topic of discussion for some time. First introduced in EIP-1337 in 2018, the proposal never really caught on. My approach to recurring payments on Ethereum takes a simpler approach than EIP-1337 did, which may help it have a larger impact on the community.
You can find this PoC write-up on my research page.
Live demo's of the contract can be found on the Ropsten network at the following links:
RecurringPayments: https://ropsten.etherscan.io/address/0xF4EfF5176bA24156d483Fddf89A09aAA12e67bAB
ERC-20: https://ropsten.etherscan.io/token/0x119b1b4697d31589fa209ba627355BfB20bebDA6
0x01. Abstract
The recurring payment implementation I will explore throughout this paper is an application of the ERC-20 Token Standard's approve(...)
function. An unlimited allowance (2^256-1
) is approved to the subscription contract address, which periodically allows the _payee
to call a timelocked proxy of ERC-20's transferFrom(...)
method.
0x02. Detailed Analysis
Consequences
Pros:
_spender
must only call 2 transactions to create a subscription; approve(...)
and createSubscription(...)
.The burden is on the payee to call the transferFrom(...)
proxy, meaning they must pay the gas fees to process future payments.
- Subscriptions can be cancelled at any time, by either the
_spender
or the _payee
.
Cons:
- This approach requires an unlimited* approval to the smart contract handling the recurring payments.
- * Technically, this approval can be any amount as long as the
_spender
approves at least enough to pay for a minimum of 2 transactions. Although unlimited approvals of ERC-20 tokens are against Solidity best practice, this PoC allows for recurring payments on Ethereum in a generally secure manner, where the only potential losses lie in the smart contract's integrity.
- We rely on
block.timestamp
for the timelock. This is generally not an issue, but should be noted.
Specification
Methods
-
getSubscription
Returns the Subscription of _customer
to _payee
.
function getSubscription(address _customer, address _payee) public view returns(Subscription memory)
-
subscriptionTimeRemaining
Returns the time in seconds remaining until the subscription payment may be charged again.
function subscriptionTimeRemaining(address _customer, address _payee) public view returns(uint256)
-
createSubscription
Creates a Subscription which allows _payee
to charge the caller _subscriptionCost
every _subscriptionPeriod
, until the Subscription is cancelled.
This may only be called by the customer, and will automatically charge them for the first billing period. Requires an approval to the subscription contract address of _subscriptionCost * 2
.
Emits a Transfer
, NewSubscription
, and SubscriptionPaid
event.
function createSubscription(address _payee, uint256 _subscriptionCost, address _token, string memory _name, string memory _description, uint256 _subscriptionPeriod ) public virtual
-
cancelSubscription
Cancels a subscription between _customer
and _payee
and disallows further executePayment(...)
calls.
This can be called by either party.
function cancelSubscription(address _customer, address _payee ) public virtual
-
executePayment
Charges _customer
for the subscription between _customer
and the payee a total of _subscriptionCost
, given that they have enough token balance and _subscriptionPaid
is false
.
This must be called by the payee.
function executePayment(address _customer) public virtual
-
_subscriptionPaid
An internal function that returns true
if the subscription between _customer
and _payee
has been paid for the current period, or false
if otherwise.
function _subscriptionPaid(address _customer, address _payee) internal view returns(bool)
Events
-
NewSubscription
MUST be called whenever a new subscription is created.
event NewSubscription(Customer, Payee, Allowance, TokenAddress, Name, Description, LastExecutionDate, SubscriptionPeriod);
-
SubscriptionCancelled
MUST be called whenever a new subscription is cancelled.
event SubscriptionCancelled(Customer, Payee);
-
SubscriptionPaid
MUST be called whenever a new subscription is paid.
event SubscriptionPaid(Customer, Payee, PaymentDate, PaymentAmount, NextPaymentDate);
0x04. Conclusion
This method of allowing smart-contracts to recursively call transferFrom(...)
based on an timelocked proxy function enables subscriptions on the blockchain, one of the most important aspects when it comes to running a service or business. The approach this PoC takes is also trustless, and can be revoked any time by the owner, allowing for a truly decentralized form of recurring payments & subscriptions on Ethereum.
0x05. Resources & Citations
- Fabian Vogelsteller, Vitalik Buterin, "EIP-20: Token Standard," Ethereum Improvement Proposals, no. 20, November 2015. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-20.
- Kevin Owocki, Andrew Redden, Scott Burke, Kevin Seagraves, Luka Kacil, Štefan Šimec, Piotr Kosiński, ankit raj, John Griffin, Nathan Creswell, "EIP-1337: Subscriptions on the blockchain," Ethereum Improvement Proposals, no. 1337, August 2018. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1337.
Ethereum-Recurring-Payments
A PoC for recurring payments on Ethereum using the ERC20 standard and a timelocked proxy of transferFrom().
Revoke.Finance

Revoke.finance is a simple DApp which allows users to see all open token approvals on their Ethereum account and manage them in an elegant React UI. I made this project after witnessing the DDoSing of revoke.cash as well as etherscan.io during the February 19 OpenSea phishing attack.
This project will be deployed to IPFS and will be DDoS proof as long as one node is hosting the file. All valid IPFS CIDs can be found on Revoke.finance, which will be updated as the project recieves further updates.
URL: https://revoke.finance/
IPFS Mirror: ipfs://bafybeifvkg4o5b7vxitg46xevmgmza7rkjjhc6fd2dx6spl5rnrkfxgiru
0x01. Features
ERC20 Approval List
The main feature of this project is the approval list, which will show all active approvals from supported ERC-20 tokens. This allows users to view the Token
, Contract Address
, Spender Address
, and Allowance Amount
for each approval, and give them the option to edit or revoke this approval.
Incident Feed
Another valuable feature of this DApp is the incident feed, which will allow users to see in real-time incidents that are ongoing within the cryptospace. This includes hacks, exploits, or bugs, and will allow users on the application to see which approvals may be risked due to an ongoing incident.
Open Source
This entire project is open-source and crowdsourced. If you have an ERC-20 token you want supported, or want to report an incident, all you have to do is open a pull-request and it will be added to the DApp. For more information on contributing, see the next section.
0x02. Contributing
Adding support for a token
If you want to add support for a token or change token information, follow these steps:
-
- Fork this repository
-
- Add or edit the token within public/assets/json/erc20.json.
- In order to be accepted, follow the JSON format below:
{
chainId: number, // Chain ID
address: string, // Contract address
name: string, // Name of token, 40 chars max
symbol: string, // Symbol of token, 20 chars max
decimals: number, // Number of decimals token uses
logoURI: string | null, // URI / URL for token logo
extensions: {
link: string | null, // URL of token's website
description: string | null, // Short description of token (1000 chars max)
ogImage: string | null // URL of Open Graph image of token website
}
}
- Fields that do not exist should be marked
null
.
-
- Open a pull request to the main branch.
- If you are updating a token, explain why within your PR.
Reporting an Incident
If you are reporting an incident that is ongoing or has happened in the past, follow these steps:
-
- Fork this repository
-
- Add or edit the incident within public/assets/json/incidents.json.
- In order to be accepted, follow the JSON format below:
{
severity: string , // high, medium, or low
platform: {
name: string, // Name of platform
address: string | null, // Contract address of platform
logoURI: string | null, // Link to platform Logo
},
description: string, // Detailed description of incident (50 char min, 1000 max)
source: string | null, // Valid source regarding incident
date: string, // Date of incident, YYYY-MM-DD HH24:MM:SS (2022-03-05 23:59:59)
}
- Fields that do not exist should be marked
null
.
-
- Open a pull request to the main branch.
- If you are updating an incident, explain why within your PR.
0x03 Resources & Citations
A simple DApp which allows users to see all open token approvals on their Ethereum account and manage them in an elegant React UI.