Skip to content

Commit

Permalink
Merge pull request #4 from iamdefinitelyahuman/v0.1.0
Browse files Browse the repository at this point in the history
v0.1.0
  • Loading branch information
iamdefinitelyahuman committed Jan 25, 2021
2 parents 24c8b8c + 55cb08c commit aff7a95
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 56 deletions.
61 changes: 33 additions & 28 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,36 @@ jobs:
- name: Run Tox
run: tox -e lint

# TODO uncomment once test suite is ready
# core:
# runs-on: ${{ matrix.os }}
# strategy:
# fail-fast: false
# matrix:
# os: [macos-latest, ubuntu-latest, windows-latest]
# python-minor: [6, 7, 8]

# steps:
# - uses: actions/checkout@v2

# - name: Setup Python 3.${{ matrix.python-minor }}
# uses: actions/setup-python@v2
# with:
# python-version: 3.${{ matrix.python-minor }}

# - name: Install Tox
# run: pip install tox wheel

# - name: Run Tox
# run: tox -e py3${{ matrix.python-minor }}

# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v1
# with:
# file: ./coverage.xml
# fail_ci_if_error: true
core:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
python-minor: [6, 7, 8]

steps:
- uses: actions/checkout@v2

- name: Setup Node.js
uses: actions/setup-node@v1

- name: Install Ganache
run: npm install -g ganache-cli@6.11.0

- name: Setup Python 3.${{ matrix.python-minor }}
uses: actions/setup-python@v2
with:
python-version: 3.${{ matrix.python-minor }}

- name: Install Tox
run: pip install tox wheel

- name: Run Tox
run: tox -e py3${{ matrix.python-minor }}

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
file: ./coverage.xml
fail_ci_if_error: true
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ This changelog format is based on [Keep a Changelog](https://keepachangelog.com/
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased](https://github.com/iamdefinitelyahuman/brownie-token-tester)
- Add custom minting logic for tokens: pBTC, wZEC, renZEC, renBTC, wBTC, sBTC, tBTC, aave tokens

## [0.1.0](https://github.com/iamdefinitelyahuman/brownie-token-tester/tree/v0.1.0) - 2021-01-25
### Added
- Custom minting logic for tokens: pBTC, wZEC, renZEC, renBTC, wBTC, sBTC, tBTC, aave tokens
- `forked.py`: Add handling of custom minting logic if token name starts with a specified prefix (e.g. 'AAVE') and custom minting logic for address does not exist
- Better error when using incompatible return types for `ERC20`

## [0.0.3](https://github.com/iamdefinitelyahuman/brownie-token-tester/tree/v0.0.3) - 2021-01-13
### Fixed
Expand Down
43 changes: 23 additions & 20 deletions brownie_tokens/forked.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def _mint_for_testing(self, target: str, amount: Wei, tx: Dict = None) -> None:
# check for token name if no custom minting
# logic exists for address
for name in _token_names:
if hasattr(self, 'name') and self.name().startswith(name):
if hasattr(self, "name") and self.name().startswith(name):
fn_name = f"mint_{name}"
if hasattr(sys.modules[__name__], fn_name):
getattr(sys.modules[__name__], fn_name)(self, target, amount)
Expand Down Expand Up @@ -76,13 +76,14 @@ def mint_0x5228a22e72ccC52d415EcFd199F99D0665E7733b(
token: MintableForkToken, target: str, amount: int
) -> None:
# pBTC
token.mint(target, amount, {'from': "0x3423Fb35149875e965f06c926DA8BA82D63f7ddb"})
token.mint(target, amount, {"from": "0x3423Fb35149875e965f06c926DA8BA82D63f7ddb"})


def mint_0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D(token: MintableForkToken, target: str, amount: int) -> None:
def mint_0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D(
token: MintableForkToken, target: str, amount: int
) -> None:
# renBTC
token.mint(target, amount, {
"from": "0xe4b679400F0f267212D5D812B95f58C83243EE71"})
token.mint(target, amount, {"from": "0xe4b679400F0f267212D5D812B95f58C83243EE71"})


def mint_0x1C5db575E2Ff833E46a2E9864C22F4B22E0B37C2(
Expand All @@ -100,18 +101,19 @@ def mint_0x196f4727526eA7FB1e17b2071B3d8eAA38486988(
token.mint(target, amount, {"from": token.minter()})


def mint_0xfE18be6b3Bd88A2D2A7f928d00292E7a9963CfC6(token: MintableForkToken, target: str, amount: int) -> None:
def mint_0xfE18be6b3Bd88A2D2A7f928d00292E7a9963CfC6(
token: MintableForkToken, target: str, amount: int
) -> None:
# Synth sBTC
target_contract = Contract(
"0xDB91E4B3b6E19bF22E810C43273eae48C9037e74")
target_contract.issue(target, amount, {
"from": "0x778D2d3E3515e42573EB1e6a8d8915D4a22D9d54"})
target_contract = Contract("0xDB91E4B3b6E19bF22E810C43273eae48C9037e74")
target_contract.issue(target, amount, {"from": "0x778D2d3E3515e42573EB1e6a8d8915D4a22D9d54"})


def mint_0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa(token: MintableForkToken, target: str, amount: int) -> None:
def mint_0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa(
token: MintableForkToken, target: str, amount: int
) -> None:
# tBTC
token.mint(target, amount, {
"from": "0x526c08E5532A9308b3fb33b7968eF78a5005d2AC"})
token.mint(target, amount, {"from": "0x526c08E5532A9308b3fb33b7968eF78a5005d2AC"})


def mint_0x674C6Ad92Fd080e4004b2312b45f796a192D27a0(
Expand All @@ -121,7 +123,9 @@ def mint_0x674C6Ad92Fd080e4004b2312b45f796a192D27a0(
token.deposit(target, amount, {"from": "0x90f85042533F11b362769ea9beE20334584Dcd7D"})


def mint_0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599(token: MintableForkToken, target: str, amount: int) -> None:
def mint_0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599(
token: MintableForkToken, target: str, amount: int
) -> None:
# wBTC
token.mint(target, amount, {"from": "0xCA06411bd7a7296d7dbdd0050DFc846E95fEBEB7"})
return
Expand All @@ -134,15 +138,14 @@ def mint_0x4A64515E5E1d1073e83f30cB97BEd20400b66E10(
token.mint(target, amount, {"from": "0x5Ca1262e25A5Fb6CA8d74850Da2753f0c896e16c"})


# to add custom minting logic for a token that starts with [NAME], add [NAME] to `_token_names` and add a function `mint_[NAME]`
# to add custom minting logic for a token that starts with [NAME], add [NAME] to
# `_token_names` and add a function `mint_[NAME]`


def mint_Aave(token: MintableForkToken, target: str, amount: int) -> None:
# aave token
token = MintableForkToken(token.UNDERLYING_ASSET_ADDRESS())
lending_pool = Contract(
"0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9")
lending_pool = Contract("0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9")
token._mint_for_testing(target, amount)
token.approve(lending_pool, amount, {'from': target})
lending_pool.deposit(token, amount,
target, 0, {'from': target})
token.approve(lending_pool, amount, {"from": target})
lending_pool.deposit(token, amount, target, 0, {"from": target})
12 changes: 7 additions & 5 deletions brownie_tokens/template.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
from brownie import Contract, compile_source
from pathlib import Path
from typing import Union
from typing import Dict, Union

RETURN_TYPE = {
RETURN_TYPE: Dict = {
True: " -> bool",
False: " -> bool",
None: "",
}

RETURN_STATEMENT = {
RETURN_STATEMENT: Dict = {
True: "return True",
False: "return False",
None: "return",
}

FAIL_STATEMENT = {
FAIL_STATEMENT: Dict = {
"revert": "raise",
True: "return True",
False: "return False",
None: "return",
}

STRING_CONVERT = {
STRING_CONVERT: Dict = {
"true": True,
"false": False,
"none": None,
Expand Down Expand Up @@ -72,6 +72,8 @@ def ERC20(
if fail not in FAIL_STATEMENT:
valid_keys = [str(i) for i in FAIL_STATEMENT.keys()]
raise ValueError(f"Invalid value for `fail`, valid options are: {', '.join(valid_keys)}")
if None in (fail, success) and fail is not success:
raise ValueError("Cannot use `None` for only one of `success` and `fail`.")

source = TEMPLATE.format(
return_type=RETURN_TYPE[success],
Expand Down
3 changes: 2 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.0.3
current_version = 0.1.0

[bumpversion:file:setup.py]

Expand Down Expand Up @@ -28,3 +28,4 @@ addopts =
--cov brownie_tokens/
--cov-report term
--cov-report xml

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
name="brownie-token-tester",
packages=find_packages(exclude=["tests", "tests.*"]),
py_modules=["brownie_tokens"],
version="0.0.3", # don't change this manually, use bumpversion instead
version="0.1.0", # don't change this manually, use bumpversion instead
license="MIT",
description="Helper objects for generating ERC20s while testing a Brownie project.",
long_description=long_description,
Expand Down
23 changes: 23 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import brownie
import pytest


def pytest_configure():
brownie.network.connect("development")


@pytest.fixture(scope="function", autouse=True)
def isolation():
brownie.chain.snapshot()
yield
brownie.chain.revert()


@pytest.fixture(scope="session")
def alice():
yield brownie.accounts[0]


@pytest.fixture(scope="session")
def bob():
yield brownie.accounts[1]
83 changes: 83 additions & 0 deletions tests/test_erc20_return_values.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import itertools
import pytest
from brownie.exceptions import VirtualMachineError

from brownie_tokens import ERC20
from brownie_tokens.template import FAIL_STATEMENT, RETURN_STATEMENT


@pytest.fixture(scope="module", params=itertools.product(RETURN_STATEMENT, FAIL_STATEMENT))
def token(request, alice):
success, fail = request.param
if None in (fail, success) and fail is not success:
pytest.skip()
contract = ERC20(success=success, fail=fail)
contract._mint_for_testing(alice, 10 ** 18, {"from": alice})
yield (contract, success, fail)


def test_transfer_success(alice, bob, token):
token, success, fail = token
tx = token.transfer(bob, 0, {"from": alice})
if success is None:
assert len(tx.return_value) == 0
else:
assert tx.return_value is success


def test_transfer_fail(alice, bob, token):
token, success, fail = token
if fail == "revert":
with pytest.raises(VirtualMachineError):
token.transfer(bob, 10 ** 19, {"from": alice})
else:
tx = token.transfer(bob, 10 ** 19, {"from": alice})
if fail is None:
assert len(tx.return_value) == 0
else:
assert tx.return_value is fail


def test_approve(alice, bob, token):
token, success, fail = token
tx = token.approve(alice, 10 ** 21, {"from": bob})
if success is None:
assert len(tx.return_value) == 0
else:
assert tx.return_value is success


def test_transferFrom_success(alice, bob, token):
token, success, fail = token
tx = token.transferFrom(alice, bob, 0, {"from": alice})
if success is None:
assert len(tx.return_value) == 0
else:
assert tx.return_value is success


def test_transferFrom_fail_allowance(alice, bob, token):
token, success, fail = token
if fail == "revert":
with pytest.raises(VirtualMachineError):
token.transferFrom(alice, bob, 10 ** 18, {"from": bob})
else:
tx = token.transferFrom(alice, bob, 10 ** 18, {"from": bob})
if fail is None:
assert len(tx.return_value) == 0
else:
assert tx.return_value is fail


def test_transferFrom_fail_balance(alice, bob, token):
token, success, fail = token
token.approve(bob, 10 ** 21, {"from": alice})
if fail == "revert":
with pytest.raises(VirtualMachineError):
token.transferFrom(alice, bob, 10 ** 21, {"from": bob})
else:
tx = token.transferFrom(alice, bob, 10 ** 21, {"from": bob})
if fail is None:
assert len(tx.return_value) == 0
else:
assert tx.return_value is fail

0 comments on commit aff7a95

Please sign in to comment.