Mock smart contracts for writing Ethereum test suites

Overview

Automated test suite

Documentation Status

Mock smart contracts for writing Ethereum test suites

This package contains common Ethereum smart contracts to be used in automated test suites. This was created for Trading Strategy, but can be used for any other projects as well. As opposite to slower and messier mainnet forking test strategies, this project aims to explicit clean deployments and very fast test execution.

Smart contract support includes

  • ERC-20 token
  • SushiSwap: router, factory, pool (Uniswap v2, PancakeSwape, QuickSwap, Trader Joe and others are 99% Sushiswap compatible)
  • High-quality API documentation
  • Full type hinting support for optimal developer experience
  • (More integrations to come)

Table of contents

Precompiled ABI file distribution

This package primarly supports Python, Web3.p3 and Brownie developers. For other programming languages and frameworks, you can find precompiled Solidity smart contracts in abi folder.

These files are good to go with any framework:

  • Web3.js
  • Ethers.js
  • Hardhat
  • Truffle
  • Web3j

Each JSON file has abi and bytecode keys you need to deploy a contract.

Just download and embed in your project. The compiled source code files are mixture of MIT and GPL v2 license.

Python usage

The Python support is available as smart_contract_test_fixtures Python package.

The package depends only on web3.py and not others, like Brownie. It grabs popular ABI files with their bytecode and compilation artifacts so that the contracts are easily deployable on any Ethereum tester interface. No Ganache is needed and everything can be executed on faster eth-tester enginer.

[Read the full API documnetation](High-quality API documentation). For code examples please see below.

Prerequisites

ERC-20 token example

To use the package to deploy a simple ERC-20 token in pytest testing:

str: """User account.""" return web3.eth.accounts[1] @pytest.fixture() def user_2(web3) -> str: """User account.""" return web3.eth.accounts[2] def test_deploy_token(web3: Web3, deployer: str): """Deploy mock ERC-20.""" token = create_token(web3, deployer, "Hentai books token", "HENTAI", 100_000 * 10**18) assert token.functions.name().call() == "Hentai books token" assert token.functions.symbol().call() == "HENTAI" assert token.functions.totalSupply().call() == 100_000 * 10**18 assert token.functions.decimals().call() == 18 def test_tranfer_tokens_between_users(web3: Web3, deployer: str, user_1: str, user_2: str): """Transfer tokens between users.""" token = create_token(web3, deployer, "Telos EVM rocks", "TELOS", 100_000 * 10**18) # Move 10 tokens from deployer to user1 token.functions.transfer(user_1, 10 * 10**18).transact({"from": deployer}) assert token.functions.balanceOf(user_1).call() == 10 * 10**18 # Move 10 tokens from deployer to user1 token.functions.transfer(user_2, 6 * 10**18).transact({"from": user_1}) assert token.functions.balanceOf(user_1).call() == 4 * 10**18 assert token.functions.balanceOf(user_2).call() == 6 * 10**18">
import pytest
from web3 import Web3, EthereumTesterProvider

from smart_contracts_for_testing.token import create_token


@pytest.fixture
def tester_provider():
    return EthereumTesterProvider()


@pytest.fixture
def eth_tester(tester_provider):
    return tester_provider.ethereum_tester


@pytest.fixture
def web3(tester_provider):
    return Web3(tester_provider)


@pytest.fixture()
def deployer(web3) -> str:
    """Deploy account."""
    return web3.eth.accounts[0]


@pytest.fixture()
def user_1(web3) -> str:
    """User account."""
    return web3.eth.accounts[1]


@pytest.fixture()
def user_2(web3) -> str:
    """User account."""
    return web3.eth.accounts[2]


def test_deploy_token(web3: Web3, deployer: str):
    """Deploy mock ERC-20."""
    token = create_token(web3, deployer, "Hentai books token", "HENTAI", 100_000 * 10**18)
    assert token.functions.name().call() == "Hentai books token"
    assert token.functions.symbol().call() == "HENTAI"
    assert token.functions.totalSupply().call() == 100_000 * 10**18
    assert token.functions.decimals().call() == 18


def test_tranfer_tokens_between_users(web3: Web3, deployer: str, user_1: str, user_2: str):
    """Transfer tokens between users."""
    token = create_token(web3, deployer, "Telos EVM rocks", "TELOS", 100_000 * 10**18)

    # Move 10 tokens from deployer to user1
    token.functions.transfer(user_1, 10 * 10**18).transact({"from": deployer})
    assert token.functions.balanceOf(user_1).call() == 10 * 10**18

    # Move 10 tokens from deployer to user1
    token.functions.transfer(user_2, 6 * 10**18).transact({"from": user_1})
    assert token.functions.balanceOf(user_1).call() == 4 * 10**18
    assert token.functions.balanceOf(user_2).call() == 6 * 10**18

See full example.

For more information how to user Web3.py in testing, see Web3.py documentation.

Uniswap swap example

WETH path = [usdc.address, weth.address] # Path tell how the swap is routed # https://docs.uniswap.org/protocol/V2/reference/smart-contracts/router-02#swapexacttokensfortokens router.functions.swapExactTokensForTokens( usdc_amount_to_pay, 0, path, user_1, FOREVER_DEADLINE, ).transact({ "from": user_1 }) # Check the user_1 received ~0.284 ethers assert weth.functions.balanceOf(user_1).call() / 1e18 == pytest.approx(0.28488156127668085)">
import pytest
from web3 import Web3
from web3.contract import Contract

from smart_contracts_for_testing.uniswap_v2 import UniswapV2Deployment, deploy_trading_pair, FOREVER_DEADLINE


def test_swap(web3: Web3, deployer: str, user_1: str, uniswap_v2: UniswapV2Deployment, weth: Contract, usdc: Contract):
    """User buys WETH on Uniswap v2 using mock USDC."""

    # Create the trading pair and add initial liquidity
    deploy_trading_pair(
        web3,
        deployer,
        uniswap_v2,
        weth,
        usdc,
        10 * 10**18,  # 10 ETH liquidity
        17_000 * 10**18,  # 17000 USDC liquidity
    )

    router = uniswap_v2.router

    # Give user_1 500 dollars to buy ETH and approve it on the router
    usdc_amount_to_pay = 500 * 10**18
    usdc.functions.transfer(user_1, usdc_amount_to_pay).transact({"from": deployer})
    usdc.functions.approve(router.address, usdc_amount_to_pay).transact({"from": user_1})

    # Perform a swap USDC->WETH
    path = [usdc.address, weth.address]  # Path tell how the swap is routed
    # https://docs.uniswap.org/protocol/V2/reference/smart-contracts/router-02#swapexacttokensfortokens
    router.functions.swapExactTokensForTokens(
        usdc_amount_to_pay,
        0,
        path,
        user_1,
        FOREVER_DEADLINE,
    ).transact({
        "from": user_1
    })

    # Check the user_1 received ~0.284 ethers
    assert weth.functions.balanceOf(user_1).call() / 1e18 == pytest.approx(0.28488156127668085)

See the full example.

How to use the library in your Python project

Add smart_contract_test_fixtures as a development dependency:

Using Poetry:

poetry add -D smart_contract_test_fixtures

Development

This step will extract compiled smart contract from Sushiswap repository.

Requires

  • Node v14
  • npx
  • yarn
  • GNU Make
  • Unix shell

Make

To build the ABI distribution:

git submodule update --recursive --init
make all

See SushiSwap continuous integration files for more information.

Version history

See change log.

Discord

Join Discord for any questions.

Notes

Currently there is no Brownie support. To support Brownie, one would need to figure out how to import an existing Hardhat based project (Sushiswap) to Brownie project format.

License

MIT

Owner
Trading Strategy
Algorithmic trading for decentralised markets
Trading Strategy
Object factory for Django

Model Bakery: Smart fixtures for better tests Model Bakery offers you a smart way to create fixtures for testing in Django. With a simple and powerful

Model Bakers 632 Jan 08, 2023
User-oriented Web UI browser tests in Python

Selene - User-oriented Web UI browser tests in Python (Selenide port) Main features: User-oriented API for Selenium Webdriver (code like speak common

Iakiv Kramarenko 575 Jan 02, 2023
Generates realistic traffic for load testing tile servers

Generates realistic traffic for load testing tile servers. Useful for: Measuring throughput, latency and concurrency of your tile serving stack. Ident

Brandon Liu 23 Dec 05, 2022
An Instagram bot that can mass text users, receive and read a text, and store it somewhere with user details.

Instagram Bot 🤖 July 14, 2021 Overview 👍 A multifunctionality automated instagram bot that can mass text users, receive and read a message and store

Abhilash Datta 14 Dec 06, 2022
reCaptchaBypasser For Bypass Any reCaptcha For Selenium Python

reCaptchaBypasser ' Usage : from selenium import webdriver from reCaptchaBypasser import reCaptchaScraper import time driver = webdriver.chrome(execu

Dr.Linux 8 Dec 17, 2022
Android automation project with pytest+appium

Android automation project with pytest+appium

1 Oct 28, 2021
The Good Old Days. | Testing Out A New Module-

The-Good-Old-Days. The Good Old Days. | Testing Out A New Module- Installation Asciimatics supports Python versions 2 & 3. For the precise list of tes

Syntax. 2 Jun 08, 2022
pytest plugin to test mypy static type analysis

pytest-mypy-testing — Plugin to test mypy output with pytest pytest-mypy-testing provides a pytest plugin to test that mypy produces a given output. A

David Fritzsche 21 Dec 21, 2022
Faker is a Python package that generates fake data for you.

Faker is a Python package that generates fake data for you. Whether you need to bootstrap your database, create good-looking XML documents, fill-in yo

Daniele Faraglia 15.2k Jan 01, 2023
HTTP client mocking tool for Python - inspired by Fakeweb for Ruby

HTTPretty 1.0.5 HTTP Client mocking tool for Python created by Gabriel FalcĂŁo . It provides a full fake TCP socket module. Inspired by FakeWeb Github

Gabriel FalcĂŁo 2k Jan 06, 2023
Tutorial for integrating Oxylabs' Residential Proxies with Selenium

Oxylabs’ Residential Proxies integration with Selenium Requirements For the integration to work, you'll need to install Selenium on your system. You c

Oxylabs.io 8 Dec 08, 2022
Fidelipy - Semi-automated trading on fidelity.com

fidelipy fidelipy is a simple Python 3.7+ library for semi-automated trading on fidelity.com. The scope is limited to the Trade Stocks/ETFs simplified

Darik Harter 8 May 10, 2022
Fully functioning price detector built with selenium and python

Fully functioning price detector built with selenium and python

mark sikaundi 4 Mar 30, 2022
A collection of testing examples using pytest and many other libreris

Effective testing with Python This project was created for PyConEs 2021 Check out the test samples at tests Check out the slides at slides (markdown o

HĂ©ctor Canto 10 Oct 23, 2022
The Social-Engineer Toolkit (SET) repository from TrustedSec - All new versions of SET will be deployed here.

đź’Ľ The Social-Engineer Toolkit (SET) đź’Ľ Copyright 2020 The Social-Engineer Toolkit (SET) Written by: David Kennedy (ReL1K) @HackingDave Company: Trust

trustedsec 8.4k Dec 31, 2022
Avocado is a set of tools and libraries to help with automated testing.

Welcome to Avocado Avocado is a set of tools and libraries to help with automated testing. One can call it a test framework with benefits. Native test

Ana Guerrero Lopez 1 Nov 19, 2021
Just a small test with lists in cython

Test for lists in cython Algorithm create a list of 10^4 lists each with 10^4 floats values (namely: 0.1) - 2 nested for iterate each list and compute

Federico Simonetta 32 Jul 23, 2022
show python coverage information directly in emacs

show python coverage information directly in emacs

wouter bolsterlee 30 Oct 26, 2022
It helps to use fixtures in pytest.mark.parametrize

pytest-lazy-fixture Use your fixtures in @pytest.mark.parametrize. Installation pip install pytest-lazy-fixture Usage import pytest @pytest.fixture(p

Marsel Zaripov 299 Dec 24, 2022
A pure Python script to easily get a reverse shell

easy-shell A pure Python script to easily get a reverse shell. How it works? After sending a request, it generates a payload with different commands a

Cristian Souza 48 Dec 12, 2022