├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── general.md
│ └── vip.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .snapcraft
└── travis_snapcraft.cfg
├── .travis.yml
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── bin
├── vyper
├── vyper-lll
└── vyper-serve
├── docs
├── Makefile
├── built-in-functions.rst
├── compiling-a-contract.rst
├── conf.py
├── contributing.rst
├── frequently-asked-questions.rst
├── index.rst
├── installing-vyper.rst
├── logging.rst
├── make.bat
├── structure-of-a-contract.rst
├── testing-deploying-contracts.rst
├── types.rst
├── vyper-by-example.rst
└── vyper-logo-transparent.svg
├── examples
├── auctions
│ └── simple_open_auction.vy
├── crowdfund.vy
├── market_maker
│ └── on_chain_market_maker.vy
├── name_registry
│ └── name_registry.vy
├── safe_remote_purchase
│ └── safe_remote_purchase.vy
├── stock
│ └── company.vy
├── tokens
│ ├── ERC20.vy
│ ├── ERC20_solidity_compatible
│ │ ├── ERC20.vy
│ │ └── README.md
│ ├── ERC721.vy
│ └── vypercoin.vy
├── voting
│ └── ballot.vy
└── wallet
│ ├── sign.js
│ └── wallet.vy
├── logo
├── vyper-logo-flat.png
├── vyper-logo-flat.svg
├── vyper-logo-transparent.png
├── vyper-logo-transparent.svg
└── vyper-logo.ai
├── requirements-dev.txt
├── requirements-docs.txt
├── scripts
├── fixed_address_creator.py
├── forwarder.py
├── rlp_decoder.py
└── rlp_decoder.se.py
├── setup.cfg
├── setup.py
├── snap
└── snapcraft.yaml
├── tests
├── __init__.py
├── compiler
│ ├── LLL
│ │ ├── __init__.py
│ │ ├── test_compile_lll.py
│ │ ├── test_repeat.py
│ │ └── test_with.py
│ ├── __init__.py
│ ├── test_bytecode_runtime.py
│ ├── test_calldatacopy.py
│ ├── test_clamps.py
│ ├── test_pre_parser.py
│ └── test_sha3_32.py
├── conftest.py
├── examples
│ ├── auctions
│ │ └── test_simple_open_auction.py
│ ├── company
│ │ └── test_company.py
│ ├── market_maker
│ │ └── test_on_chain_market_maker.py
│ ├── name_registry
│ │ └── test_name_registry.py
│ ├── safe_remote_purchase
│ │ └── test_safe_remote_purchase.py
│ ├── tokens
│ │ ├── ERC20_solidity_compatible
│ │ │ ├── nonvyper
│ │ │ │ ├── ERC20_solidity_1.sol
│ │ │ │ └── ERC20_solidity_2.sol
│ │ │ ├── run_tests.py
│ │ │ ├── test
│ │ │ │ ├── __init__.py
│ │ │ │ ├── erc20_tests_1.py
│ │ │ │ └── erc20_tests_2.py
│ │ │ └── utils
│ │ │ │ ├── __init__.py
│ │ │ │ └── pyethereum_test_utils.py
│ │ ├── test_erc721.py
│ │ └── test_vypercoin.py
│ ├── voting
│ │ └── test_ballot.py
│ └── wallet
│ │ └── test_wallet.py
└── parser
│ ├── exceptions
│ ├── __init__.py
│ ├── test_constancy_exception.py
│ ├── test_function_declaration_exception.py
│ ├── test_insufficient_arguments.py
│ ├── test_invalid_literal_exception.py
│ ├── test_invalid_payable.py
│ ├── test_invalid_same_variable_assignment.py
│ ├── test_invalid_type_exception.py
│ ├── test_parser_exception_pos.py
│ ├── test_structure_exception.py
│ ├── test_type_mismatch_exception.py
│ ├── test_undef_function.py
│ └── test_variable_declaration_exception.py
│ ├── features
│ ├── arithmetic
│ │ └── test_modulo.py
│ ├── decorators
│ │ ├── test_constant.py
│ │ ├── test_private.py
│ │ └── test_public.py
│ ├── external_contracts
│ │ ├── test_erc20_abi.py
│ │ ├── test_external_contract_calls.py
│ │ └── test_modifiable_external_contract_calls.py
│ ├── iteration
│ │ ├── test_break.py
│ │ ├── test_continue.py
│ │ ├── test_for_in_list.py
│ │ ├── test_range_in.py
│ │ └── test_repeater.py
│ ├── test_assert.py
│ ├── test_assignment.py
│ ├── test_bytes_map_keys.py
│ ├── test_clampers.py
│ ├── test_comments.py
│ ├── test_conditionals.py
│ ├── test_constructor.py
│ ├── test_gas.py
│ ├── test_internal_call.py
│ ├── test_logging.py
│ ├── test_logging_bytes_extended.py
│ ├── test_map_delete.py
│ └── test_packing.py
│ ├── functions
│ ├── __init__.py
│ ├── rlp
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ └── test_rlp_list.py
│ ├── test_bitwise.py
│ ├── test_block.py
│ ├── test_block_number.py
│ ├── test_ceil.py
│ ├── test_concat.py
│ ├── test_convert.py
│ ├── test_convert_int128.py
│ ├── test_convert_uint256.py
│ ├── test_default_function.py
│ ├── test_default_parameters.py
│ ├── test_ec.py
│ ├── test_ecrecover.py
│ ├── test_extract32.py
│ ├── test_floor.py
│ ├── test_is_contract.py
│ ├── test_length.py
│ ├── test_method_id.py
│ ├── test_minmax.py
│ ├── test_only_init_abi.py
│ ├── test_raw_call.py
│ ├── test_return_tuple.py
│ ├── test_send.py
│ ├── test_sha3.py
│ └── test_slice.py
│ ├── globals
│ ├── test_getters.py
│ ├── test_globals.py
│ └── test_setters.py
│ ├── integration
│ ├── test_basics.py
│ ├── test_crowdfund.py
│ └── test_escrow.py
│ ├── syntax
│ ├── __init__.py
│ ├── test_ann_assign.py
│ ├── test_as_uint256.py
│ ├── test_as_wei_value.py
│ ├── test_block.py
│ ├── test_blockscope.py
│ ├── test_bool.py
│ ├── test_byte_string.py
│ ├── test_bytes.py
│ ├── test_code_size.py
│ ├── test_concat.py
│ ├── test_constants.py
│ ├── test_create_with_code_of.py
│ ├── test_custom_units.py
│ ├── test_extract32.py
│ ├── test_for_range.py
│ ├── test_functions_call.py
│ ├── test_invalids.py
│ ├── test_len.py
│ ├── test_list.py
│ ├── test_logging.py
│ ├── test_maps.py
│ ├── test_minmax.py
│ ├── test_missing_return.py
│ ├── test_nested_list.py
│ ├── test_public.py
│ ├── test_raw_call.py
│ ├── test_return_tuple.py
│ ├── test_rlplist.py
│ ├── test_selfdestruct.py
│ ├── test_send.py
│ ├── test_sha3.py
│ ├── test_slice.py
│ ├── test_timestamp_timedelta.py
│ ├── test_tuple_assign.py
│ ├── test_unit_exponents.py
│ └── utils
│ │ ├── test_event_names.py
│ │ ├── test_function_names.py
│ │ └── test_variable_names.py
│ └── types
│ ├── numbers
│ ├── test_constants.py
│ ├── test_custom_units.py
│ ├── test_decimals.py
│ ├── test_int128.py
│ └── test_uint256.py
│ ├── test_bytes.py
│ ├── test_lists.py
│ ├── test_node_types.py
│ ├── test_string_literal.py
│ ├── test_variable_naming.py
│ └── value
│ └── test_as_wei_value.py
└── vyper
├── __init__.py
├── compile_lll.py
├── compiler.py
├── exceptions.py
├── functions
├── __init__.py
├── functions.py
└── signature.py
├── opcodes.py
├── optimizer.py
├── parser
├── __init__.py
├── context.py
├── expr.py
├── global_context.py
├── lll_node.py
├── parser.py
├── parser_utils.py
├── pre_parser.py
├── s_expressions.py
├── self_call.py
└── stmt.py
├── premade_contracts.py
├── server.py
├── signatures
├── __init__.py
├── event_signature.py
└── function_signature.py
├── types
├── __init__.py
├── convert.py
└── types.py
└── utils.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.vy linguist-language=Python
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/general.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: General Feedback
3 | about: Any general feedback or bug reports about the Vyper Compiler. No new features proposals.
4 | ---
5 |
6 | ### Version Information
7 |
8 | * vyper Version: x.x.x
9 | * pyethereum Version: x.x.x
10 | * OS: osx/linux/win
11 | * Python Version (python --version):
12 | * Environment (output of `pip freeze`):
13 |
14 | ### What's your issue about?
15 |
16 | Please include information like:
17 |
18 | * full output of the error you received
19 | * what command you ran
20 | * the code that caused the failure (see [this link](https://help.github.com/articles/basic-writing-and-formatting-syntax/) for help with formatting code)
21 |
22 |
23 | ### How can it be fixed?
24 |
25 | Fill this in if you know how to fix it.
26 |
27 | #### Cute Animal Picture
28 |
29 | > put a cute animal picture here.
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/vip.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Vyper Improvement Proposal (VIP)
3 | about: This is the suggested template for new VIPs.
4 | ---
5 | ## Simple Summary
6 | "If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the VIP.
7 |
8 | ## Abstract
9 | A short description of the technical issue being addressed.
10 |
11 | ## Motivation
12 | The motivation is critical for VIPs that add or change Vyper's functionality. It should clearly explain why the existing Vyper functionality is inadequate to address the problem that the VIP solves as well as how the VIP is in line with Vyper's goals and design philosophy.
13 |
14 | ## Specification
15 | The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow any developer to implement the functionality
16 |
17 | ## Backwards Compatibility
18 | All VIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The VIP must explain how the author proposes to deal with these incompatibilities.
19 |
20 | ## Copyright
21 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/)
22 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### - What I did
2 |
3 | ### - How I did it
4 |
5 | ### - How to verify it
6 |
7 | ### - Description for the changelog
8 |
9 | ### - Cute Animal Picture
10 |
11 | > put a cute animal picture here.
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # egg-related
7 | vyper.egg-info/
8 | build/
9 | dist/
10 | .eggs/
11 |
12 | .pytest_cache/
13 |
14 | # pyenv
15 | .python-version
16 |
17 | # dotenv
18 | .env
19 |
20 | # virtualenv
21 | .venv/
22 | venv/
23 | ENV/
24 |
25 | # Coverage tests
26 | .coverage
27 | .cache/
28 | htmlcov/
29 |
30 | # sphinx
31 | docs/_build
32 | docs/modules.rst
33 |
34 | # IDEs
35 | .idea/
36 |
--------------------------------------------------------------------------------
/.snapcraft/travis_snapcraft.cfg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/.snapcraft/travis_snapcraft.cfg
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - '3.6'
4 | cache: pip
5 | install:
6 | - pip install --upgrade pip setuptools
7 | - pip install coveralls
8 | - pip install flake8
9 | - pip install .
10 | script:
11 | - python setup.py test
12 | - flake8 vyper/ tests/
13 | sudo: required
14 | services:
15 | - docker
16 | after_success:
17 | - coveralls
18 | - openssl aes-256-cbc -K $encrypted_6ed035d313c9_key -iv $encrypted_6ed035d313c9_iv
19 | -in .snapcraft/travis_snapcraft.cfg -out .snapcraft/snapcraft.cfg -d
20 | deploy:
21 | skip_cleanup: true
22 | provider: script
23 | script: docker run -v $(pwd):$(pwd) -t snapcore/snapcraft sh -c
24 | "apt update -qq && cd $(pwd) &&
25 | snapcraft && snapcraft push *.snap --release edge"
26 | on:
27 | branch: master
28 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.6-slim
2 |
3 | # Specify label-schema specific arguments and labels.
4 | ARG BUILD_DATE
5 | ARG VCS_REF
6 | LABEL org.label-schema.build-date=$BUILD_DATE \
7 | org.label-schema.name="Vyper" \
8 | org.label-schema.description="Vyper is an experimental programming language" \
9 | org.label-schema.url="https://vyper.readthedocs.io/en/latest/" \
10 | org.label-schema.vcs-ref=$VCS_REF \
11 | org.label-schema.vcs-url="https://github.com/ethereum/vyper" \
12 | org.label-schema.vendor="Ethereum" \
13 | org.label-schema.schema-version="1.0"
14 |
15 | # coincurve requires libgmp
16 | RUN apt-get update && \
17 | apt-get install -y --no-install-recommends apt-utils gcc libc6-dev libc-dev libssl-dev libgmp-dev && \
18 | rm -rf /var/lib/apt/lists/*
19 |
20 | ADD . /code
21 |
22 | WORKDIR /code
23 |
24 | # Pass `--addopts "--version"` because want to execute `python setup.py test` to include test dependencies in built docker-image, but avoid to execute the whole test suite here.
25 | RUN python setup.py install && \
26 | python setup.py test --addopts "--version" && \
27 | apt-get purge -y --auto-remove apt-utils gcc libc6-dev libc-dev libssl-dev
28 |
29 | ENTRYPOINT ["/usr/local/bin/vyper"]
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015 Vitalik Buterin
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: test lint clean clean-pyc clean-build clean-test docs docker-build
2 |
3 | init:
4 | python setup.py install
5 |
6 | test:
7 | python setup.py test
8 |
9 | lint:
10 | flake8 vyper tests --ignore=E122,E124,E127,E128,E501,E731,W504
11 |
12 | clean: clean-build clean-pyc clean-test
13 |
14 | clean-build:
15 | rm -fr build/
16 | rm -fr dist/
17 | rm -fr *.egg-info
18 |
19 | clean-pyc:
20 | find . -name '*.pyc' -exec rm -f {} +
21 | find . -name '*.pyo' -exec rm -f {} +
22 | find . -name '*~' -exec rm -f {} +
23 | find . -name '__pycache__' -exec rmdir {} +
24 |
25 | clean-test:
26 | find . -name 'htmlcov' -exec rm -rf {} +
27 |
28 | docs:
29 | rm -f docs/vyper.rst
30 | rm -f docs/modules.rst
31 | sphinx-apidoc -o docs/ -d 2 vyper/
32 | $(MAKE) -C docs clean
33 | $(MAKE) -C docs html
34 | open docs/_build/html/index.html
35 |
36 | docker-build:
37 | @docker build -t vyper \
38 | --build-arg VCS_REF=`git rev-parse --short HEAD` \
39 | --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` .
40 |
--------------------------------------------------------------------------------
/bin/vyper-lll:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import argparse
4 | import vyper
5 |
6 | from vyper import (
7 | optimizer
8 | )
9 | from vyper.parser.s_expressions import parse_s_exp
10 | from vyper.parser.parser_utils import LLLnode
11 | from vyper import compile_lll
12 | parser = argparse.ArgumentParser(description='Vyper LLL for Ethereum')
13 | parser.add_argument('--version', action='version', version='{0}'.format(vyper.__version__))
14 | parser.add_argument('input_file', help='Vyper sourcecode to compile')
15 | parser.add_argument('-f', help='Format to print csv list of ir,opt_ir,asm,bytecode', default='bytecode', dest='format')
16 | parser.add_argument('--show-gas-estimates', help='Show gas estimates in ir output mode.', action="store_true")
17 |
18 | args = parser.parse_args()
19 |
20 | if __name__ == "__main__":
21 |
22 | with open(args.input_file) as f:
23 |
24 | if args.show_gas_estimates:
25 | LLLnode.repr_show_gas = True
26 |
27 | format_set = set(dict.fromkeys(args.format.split(',')))
28 | s_expressions = parse_s_exp(f.read())
29 | lll = LLLnode.from_list(s_expressions[0])
30 | if 'ir' in format_set:
31 | print(lll)
32 | optimised = optimizer.optimize(lll)
33 | if 'opt_ir' in format_set:
34 | print(optimised)
35 | asm = compile_lll.compile_to_assembly(lll)
36 | if 'asm' in format_set:
37 | print(asm)
38 | bytecode = '0x' + compile_lll.assembly_to_evm(asm).hex()
39 | if 'bytecode' in format_set:
40 | print(bytecode)
41 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = python -msphinx
7 | SPHINXPROJ = Vyper
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--------------------------------------------------------------------------------
/docs/compiling-a-contract.rst:
--------------------------------------------------------------------------------
1 | ####################
2 | Compiling a Contract
3 | ####################
4 | To compile a contract, use:
5 | ::
6 | vyper yourFileName.vy
7 |
8 | You can also compile to other formats such as ABI using the below format:
9 | ::
10 | vyper -f ['abi', 'abi_python', 'bytecode', 'bytecode_runtime', 'ir', 'asm'] yourFileName.vy
11 |
12 | It is also possible to use the `-f json` option, which is a legacy alias for `-f abi`.
13 |
14 | .. note::
15 | Since .vy is not officially a language supported by any syntax highlighters or linters,
16 | it is recommended to name your Vyper file ending with `.vy` in order to have Python syntax highlighting.
17 |
18 | An `online compiler `_ is available as well, which lets you experiment with
19 | the language without having to install Vyper. The online compiler allows you to compile to ``bytecode`` and/or ``LLL``.
20 |
21 | .. note::
22 | While the vyper version of the online compiler is updated on a regular basis it might
23 | be a bit behind the latest version found in the master branch of the repository.
24 |
--------------------------------------------------------------------------------
/docs/contributing.rst:
--------------------------------------------------------------------------------
1 | ############
2 | Contributing
3 | ############
4 |
5 | Help is always appreciated!
6 |
7 | To get started, you can try `installing Vyper `_ in order to familiarize
8 | yourself with the components of Vyper and the build process. Also, it may be
9 | useful to become well-versed at writing smart-contracts in Vyper.
10 |
11 | Types of Contributions
12 | ======================
13 |
14 | In particular, we need help in the following areas:
15 |
16 | * Improving the documentation
17 | * Responding to questions from other users on `StackExchange
18 | `_ and the `Vyper Gitter
19 | `_
20 | * Suggesting Improvements
21 | * Fixing and responding to `Vyper's GitHub issues `_
22 |
23 |
24 |
25 | How to Suggest Improvements
26 | ===========================
27 |
28 | To suggest an improvement, please create a Vyper Improvement Proposal (VIP for short)
29 | using the `VIP Template `_.
30 |
31 | How to Report Issues
32 | ====================
33 |
34 | To report an issue, please use the
35 | `GitHub issues tracker `_. When
36 | reporting issues, please mention the following details:
37 |
38 | * Which version of Vyper you are using
39 | * What was the source code (if applicable)
40 | * Which platform are you running on
41 | * Your operating system name and version
42 | * Detailed steps to reproduce the issue
43 | * What was the result of the issue
44 | * What the expected behaviour is
45 |
46 | Reducing the source code that caused the issue to a bare minimum is always
47 | very helpful and sometimes even clarifies a misunderstanding.
48 |
49 | Fix Bugs
50 | ========
51 |
52 | Find or report bugs at our `issues page `_. Anything tagged with "bug" is open to whoever wants to implement it.
53 |
54 | Workflow for Pull Requests
55 | ==========================
56 |
57 | In order to contribute, please fork off of the ``master`` branch and make your
58 | changes there. Your commit messages should detail *why* you made your change
59 | in addition to *what* you did (unless it is a tiny change).
60 |
61 | If you need to pull in any changes from ``master`` after making your fork (for
62 | example, to resolve potential merge conflicts), please avoid using ``git merge``
63 | and instead, ``git rebase`` your branch.
64 |
65 | **Implement Features**
66 |
67 | If you are writing a new feature, please ensure you write appropriate
68 | Boost test cases and place them under ``tests/``.
69 |
70 | If you are making a larger change, please consult first with the Gitter channel.
71 |
72 | Although we do CI testing, please make sure that the tests pass for supported Python version and ensure that it builds locally before submitting a pull request.
73 |
74 | Thank you for your help!
75 |
--------------------------------------------------------------------------------
/docs/frequently-asked-questions.rst:
--------------------------------------------------------------------------------
1 | ###########################
2 | Frequently Asked Questions
3 | ###########################
4 |
5 | ***************
6 | Basic Questions
7 | ***************
8 |
9 | ==============
10 | What is Vyper?
11 | ==============
12 | Vyper is a smart contract development language. Vyper aims to be auditable, secure, and human-readable. Being simple to read is more important than being simple to write.
13 |
14 | ==================
15 | Vyper or Solidity?
16 | ==================
17 | For the majority of use-cases, this is personal preference. To support the aims of being secure, auditable, and human-readable, a number of programming constructs included in Solidity are not included in Vyper. If your use-case requires these, use Solidity not Vyper.
18 |
19 | ==============================
20 | What is not included in Vyper?
21 | ==============================
22 | The following constructs are not included because their use can lead to misleading or difficult to understand code:
23 |
24 | * Modifiers
25 | * Class inheritance
26 | * Inline assembly
27 | * Function overloading
28 | * Operator overloading
29 | * Binary fixed point.
30 |
31 | Recursive calling and infinite-length loops are not included because they cannot set an upper bound on gas limits. An upper bound is required to prevent gas limit attacks and ensure the security of smart contracts built in Vyper.
32 |
33 | ======================
34 | How do for loops work?
35 | ======================
36 | Like Python for loops but with one significant difference. Vyper does not allow looping over variable lengths. Looping over variables introduces the possibility of infinite-length loops which make gas limit attacks possible.
37 |
38 | ====================
39 | How do structs work?
40 | ====================
41 | Structs group variables and are accessed using ``struct.argname``. They are similar to Python dictionaries::
42 |
43 | # define the struct
44 | struct: {
45 | arg1: int128, arg2: decimal
46 | }
47 |
48 | #access arg1 in struct
49 | struct.arg1 = 1
50 |
51 |
52 |
53 | ******************
54 | Advanced Questions
55 | ******************
56 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=python -msphinx
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 | set SPHINXPROJ=Vyper
13 |
14 | if "%1" == "" goto help
15 |
16 | %SPHINXBUILD% >NUL 2>NUL
17 | if errorlevel 9009 (
18 | echo.
19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed,
20 | echo.then set the SPHINXBUILD environment variable to point to the full
21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the
22 | echo.Sphinx directory to PATH.
23 | echo.
24 | echo.If you don't have Sphinx installed, grab it from
25 | echo.http://sphinx-doc.org/
26 | exit /b 1
27 | )
28 |
29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
30 | goto end
31 |
32 | :help
33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
34 |
35 | :end
36 | popd
37 |
--------------------------------------------------------------------------------
/docs/testing-deploying-contracts.rst:
--------------------------------------------------------------------------------
1 | .. index:: testing;deploying, testing;
2 |
3 | .. _testing_deploying:
4 |
5 | ******************
6 | Testing a Contract
7 | ******************
8 |
9 | The following example demonstrates how to compile and deploy your vyper contract.
10 | It requires ``pyethereum>=2.0.0`` for the ``tester`` module
11 |
12 | .. code-block:: python
13 | from vyper import compiler
14 | from ethereum.tools import tester
15 |
16 | # Get a new chain
17 | chain = tester.Chain()
18 | # Set the vyper compiler to run when the vyper language is requested
19 | tester.languages['vyper'] = compiler.Compiler()
20 |
21 | with open('my_contract.vy' 'r') as f:
22 | source_code = f.read()
23 | # Compile and Deploy contract to provisioned testchain
24 | # (e.g. run __init__ method) with given args (e.g. init_args)
25 | # from msg.sender = t.k1 (private key of address 1 in test acconuts)
26 | # and supply 1000 wei to the contract
27 | init_args = ['arg1', 'arg2', 3]
28 | contract = chain.contract(source_code, language="vyper",
29 | init_args, sender=t.k1, value=1000)
30 |
31 | contract.myMethod() # Executes myMethod on the tester "chain"
32 | chain.mine() # Mines the above transaction (and any before it) into a block
33 |
34 | Note: We are working on integration with `ethereum-tester `_,
35 | so this example will change.
36 |
37 | ===============================
38 | Testing Using vyper-run Command
39 | ===============================
40 |
41 | To allow quickly testing contracts, Vyper provides a command line tool for instantly executing a function:
42 | ::
43 | vyper-run yourFileName.vy "yourFunction();" -i some_init_param, another_init_param
44 |
45 | The vyper-run command is composed of 4 parts:
46 |
47 | - vyper-run
48 |
49 | - the name of the contract file you want to execute (for example: coolContract.vy)
50 |
51 | - a string (wrapped in double quotes) with the function you want to trigger, you can trigger multiple functions by adding a semicolon at the end of each function and then call the next function (for example: ``"myFunction1(100,4);myFunction2()"``) +
52 |
53 | - (Optional) the parameters for the ``__init__`` function of the contract (for example: given ``__init__(a: int128, b: int128)`` the syntax would be ``-i 8,27``).
54 |
55 | Putting it all together:
56 | ::
57 | vyper-run myContract.vy "myFunction1();myFunction2()" -i 1,3
58 |
59 | The vyper-run command will print out the returned value of the called functions as well as all the logged events emitted during the function's execution.
60 |
61 | ********************
62 | Deploying a Contract
63 | ********************
64 |
65 | You have several options to deploy a Vyper contract to the public testnets.
66 |
67 | One option is to take the bytecode generated by the vyper compiler and manually deploy it through mist or geth:
68 |
69 | .. code-block:: bash
70 | vyper yourFileName.vy
71 | # returns bytecode
72 |
73 | Or deploy it with current browser on `myetherwallet `_ contract menu.
74 |
75 | We are working on integration with `populus `_,
76 | this will be the preferred way of deploying vyper contracts in the future.
77 |
--------------------------------------------------------------------------------
/docs/vyper-logo-transparent.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/examples/auctions/simple_open_auction.vy:
--------------------------------------------------------------------------------
1 | # Open Auction
2 |
3 | # Auction params
4 | # Beneficiary receives money from the highest bidder
5 | beneficiary: public(address)
6 | auctionStart: public(timestamp)
7 | auctionEnd: public(timestamp)
8 |
9 | # Current state of auction
10 | highestBidder: public(address)
11 | highestBid: public(wei_value)
12 |
13 | # Set to true at the end, disallows any change
14 | ended: public(bool)
15 |
16 | # Create a simple auction with `_bidding_time`
17 | # seconds bidding time on behalf of the
18 | # beneficiary address `_beneficiary`.
19 | @public
20 | def __init__(_beneficiary: address, _bidding_time: timedelta):
21 | self.beneficiary = _beneficiary
22 | self.auctionStart = block.timestamp
23 | self.auctionEnd = self.auctionStart + _bidding_time
24 |
25 | # Bid on the auction with the value sent
26 | # together with this transaction.
27 | # The value will only be refunded if the
28 | # auction is not won.
29 | @public
30 | @payable
31 | def bid():
32 | # Check if bidding period is over.
33 | assert block.timestamp < self.auctionEnd
34 | # Check if bid is high enough
35 | assert msg.value > self.highestBid
36 | if not self.highestBid == 0:
37 | # Sends money back to the previous highest bidder
38 | send(self.highestBidder, self.highestBid)
39 | self.highestBidder = msg.sender
40 | self.highestBid = msg.value
41 |
42 |
43 | # End the auction and send the highest bid
44 | # to the beneficiary.
45 | @public
46 | def endAuction():
47 | # It is a good guideline to structure functions that interact
48 | # with other contracts (i.e. they call functions or send Ether)
49 | # into three phases:
50 | # 1. checking conditions
51 | # 2. performing actions (potentially changing conditions)
52 | # 3. interacting with other contracts
53 | # If these phases are mixed up, the other contract could call
54 | # back into the current contract and modify the state or cause
55 | # effects (Ether payout) to be performed multiple times.
56 | # If functions called internally include interaction with external
57 | # contracts, they also have to be considered interaction with
58 | # external contracts.
59 |
60 | # 1. Conditions
61 | # Check if auction endtime has been reached
62 | assert block.timestamp >= self.auctionEnd
63 | # Check if this function has already been called
64 | assert not self.ended
65 |
66 | # 2. Effects
67 | self.ended = True
68 |
69 | # 3. Interaction
70 | send(self.beneficiary, self.highestBid)
71 |
--------------------------------------------------------------------------------
/examples/crowdfund.vy:
--------------------------------------------------------------------------------
1 | # Setup private variables (only callable from within the contract)
2 | funders: {sender: address, value: wei_value}[int128]
3 | nextFunderIndex: int128
4 | beneficiary: address
5 | deadline: timestamp
6 | goal: wei_value
7 | refundIndex: int128
8 | timelimit: timedelta
9 |
10 |
11 | # Setup global variables
12 | @public
13 | def __init__(_beneficiary: address, _goal: wei_value, _timelimit: timedelta):
14 | self.beneficiary = _beneficiary
15 | self.deadline = block.timestamp + _timelimit
16 | self.timelimit = _timelimit
17 | self.goal = _goal
18 |
19 |
20 | # Participate in this crowdfunding campaign
21 | @public
22 | @payable
23 | def participate():
24 | assert block.timestamp < self.deadline
25 |
26 | nfi: int128 = self.nextFunderIndex
27 |
28 | self.funders[nfi] = {sender: msg.sender, value: msg.value}
29 | self.nextFunderIndex = nfi + 1
30 |
31 |
32 | # Enough money was raised! Send funds to the beneficiary
33 | @public
34 | def finalize():
35 | assert block.timestamp >= self.deadline and self.balance >= self.goal
36 |
37 | selfdestruct(self.beneficiary)
38 |
39 |
40 | # Not enough money was raised! Refund everyone (max 30 people at a time
41 | # to avoid gas limit issues)
42 | @public
43 | def refund():
44 | assert block.timestamp >= self.deadline and self.balance < self.goal
45 |
46 | ind: int128 = self.refundIndex
47 |
48 | for i in range(ind, ind + 30):
49 | if i >= self.nextFunderIndex:
50 | self.refundIndex = self.nextFunderIndex
51 | return
52 |
53 | send(self.funders[i].sender, self.funders[i].value)
54 | self.funders[i] = None
55 |
56 | self.refundIndex = ind + 30
57 |
--------------------------------------------------------------------------------
/examples/market_maker/on_chain_market_maker.vy:
--------------------------------------------------------------------------------
1 | units: {
2 | currency_value: "a currency"
3 | }
4 |
5 | totalEthQty: public(wei_value)
6 | totalTokenQty: public(uint256(currency_value))
7 | # Constant set in `initiate` that's used to calculate
8 | # the amount of ether/tokens that are exchanged
9 | invariant: public(uint256(wei * currency_value))
10 | token_address: address(ERC20)
11 | owner: public(address)
12 |
13 | # Sets the on chain market maker with its owner, intial token quantity,
14 | # and initial ether quantity
15 | @public
16 | @payable
17 | def initiate(token_addr: address, token_quantity: uint256(currency_value)):
18 | assert self.invariant == 0
19 | self.token_address = token_addr
20 | self.token_address.transferFrom(msg.sender, self, as_unitless_number(token_quantity))
21 | self.owner = msg.sender
22 | self.totalEthQty = msg.value
23 | self.totalTokenQty = token_quantity
24 | self.invariant = msg.value * token_quantity
25 | assert self.invariant > 0
26 |
27 | # Sells ether to the contract in exchange for tokens (minus a fee)
28 | @public
29 | @payable
30 | def ethToTokens():
31 | fee: wei_value = msg.value / 500
32 | eth_in_purchase: wei_value = msg.value - fee
33 | new_total_eth: wei_value = self.totalEthQty + eth_in_purchase
34 | new_total_tokens: uint256(currency_value) = self.invariant / new_total_eth
35 | self.token_address.transfer(msg.sender, as_unitless_number(self.totalTokenQty - new_total_tokens))
36 | self.totalEthQty = new_total_eth
37 | self.totalTokenQty = new_total_tokens
38 |
39 | # Sells tokens to the contract in exchange for ether
40 | @public
41 | def tokensToEth(sell_quantity: uint256(currency_value)):
42 | self.token_address.transferFrom(msg.sender, self, as_unitless_number(sell_quantity))
43 | new_total_tokens: uint256(currency_value) = self.totalTokenQty + sell_quantity
44 | new_total_eth: wei_value = self.invariant / new_total_tokens
45 | eth_to_send: wei_value = self.totalEthQty - new_total_eth
46 | send(msg.sender, eth_to_send)
47 | self.totalEthQty = new_total_eth
48 | self.totalTokenQty = new_total_tokens
49 |
50 | # Owner can withdraw their funds and destroy the market maker
51 | @public
52 | def ownerWithdraw():
53 | assert self.owner == msg.sender
54 | self.token_address.transfer(self.owner, as_unitless_number(self.totalTokenQty))
55 | selfdestruct(self.owner)
56 |
--------------------------------------------------------------------------------
/examples/name_registry/name_registry.vy:
--------------------------------------------------------------------------------
1 |
2 | registry: address[bytes[100]]
3 |
4 |
5 | @public
6 | def register(name: bytes[100], owner: address):
7 | assert self.registry[name] == ZERO_ADDRESS # check name has not been set yet.
8 | self.registry[name] = owner
9 |
10 |
11 | @public
12 | @constant
13 | def lookup(name: bytes[100]) -> address:
14 | return self.registry[name]
15 |
--------------------------------------------------------------------------------
/examples/safe_remote_purchase/safe_remote_purchase.vy:
--------------------------------------------------------------------------------
1 | #Safe Remote Purchase
2 | #Originally from
3 | #https://github.com/ethereum/solidity/blob/develop/docs/solidity-by-example.rst
4 | #ported to vyper and optimized
5 |
6 | #Rundown of the transaction:
7 | #1. Seller posts item for sale and posts safety deposit of double the item value.
8 | # Balance is 2*value.
9 | #(1.1. Seller can reclaim deposit and close the sale as long as nothing was purchased.)
10 | #2. Buyer purchases item (value) plus posts an additional safety deposit (Item value).
11 | # Balance is 4*value.
12 | #3. Seller ships item.
13 | #4. Buyer confirms receiving the item. Buyer's deposit (value) is returned.
14 | #Seller's deposit (2*value) + items value is returned. Balance is 0.
15 |
16 | value: public(wei_value) #Value of the item
17 | seller: public(address)
18 | buyer: public(address)
19 | unlocked: public(bool)
20 | #@constant
21 | #def unlocked() -> bool: #Is a refund possible for the seller?
22 | # return (self.balance == self.value*2)
23 |
24 | @public
25 | @payable
26 | def __init__():
27 | assert (msg.value % 2) == 0
28 | self.value = msg.value / 2 #The seller initializes the contract by
29 | #posting a safety deposit of 2*value of the item up for sale.
30 | self.seller = msg.sender
31 | self.unlocked = True
32 |
33 | @public
34 | def abort():
35 | assert self.unlocked #Is the contract still refundable?
36 | assert msg.sender == self.seller #Only the seller can refund
37 | # his deposit before any buyer purchases the item.
38 | selfdestruct(self.seller) #Refunds the seller and deletes the contract.
39 |
40 | @public
41 | @payable
42 | def purchase():
43 | assert self.unlocked #Is the contract still open (is the item still up for sale)?
44 | assert msg.value == (2 * self.value) #Is the deposit the correct value?
45 | self.buyer = msg.sender
46 | self.unlocked = False
47 |
48 | @public
49 | def received():
50 | assert not self.unlocked #Is the item already purchased and pending confirmation
51 | # from the buyer?
52 | assert msg.sender == self.buyer
53 | send(self.buyer, self.value) #Return the buyer's deposit (=value) to the buyer.
54 | selfdestruct(self.seller) #Return the seller's deposit (=2*value)
55 | # and the purchase price (=value) to the seller.
56 |
--------------------------------------------------------------------------------
/examples/tokens/ERC20.vy:
--------------------------------------------------------------------------------
1 | # Vyper Port of MyToken
2 | # THIS CONTRACT HAS NOT BEEN AUDITED!
3 | # ERC20 details at:
4 | # https://theethereum.wiki/w/index.php/ERC20_Token_Standard
5 | # https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
6 |
7 |
8 | # Events of the token.
9 | Transfer: event({_from: indexed(address), _to: indexed(address), _value: uint256})
10 | Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256})
11 |
12 |
13 | # Variables of the token.
14 | name: public(bytes32)
15 | symbol: public(bytes32)
16 | totalSupply: public(uint256)
17 | decimals: public(int128)
18 | balances: int128[address]
19 | allowed: int128[address][address]
20 |
21 |
22 | @public
23 | def __init__(_name: bytes32, _symbol: bytes32, _decimals: uint256, _initialSupply: uint256):
24 | self.name = _name
25 | self.symbol = _symbol
26 | self.decimals = _decimals
27 | self.totalSupply =_initialSupply * convert(10, 'uint256') ** _decimals
28 | self.balances[msg.sender] = convert(self.totalSupply, 'int128')
29 |
30 |
31 | # What is the balance of a particular account?
32 | @public
33 | @constant
34 | def balanceOf(_owner: address) -> uint256:
35 |
36 | return convert(self.balances[_owner], 'uint256')
37 |
38 |
39 | # Send `_value` tokens to `_to` from your account
40 | @public
41 | def transfer(_to: address, _amount: int128(uint256)) -> bool:
42 |
43 | if self.balances[msg.sender] >= _amount and \
44 | self.balances[_to] + _amount >= self.balances[_to]:
45 |
46 | self.balances[msg.sender] -= _amount # Subtract from the sender
47 | self.balances[_to] += _amount # Add the same to the recipient
48 | log.Transfer(msg.sender, _to, convert(_amount, 'uint256')) # log transfer event.
49 |
50 | return True
51 | else:
52 | return False
53 |
54 |
55 | # Transfer allowed tokens from a specific account to another.
56 | @public
57 | def transferFrom(_from: address, _to: address, _value: int128(uint256)) -> bool:
58 |
59 | if _value <= self.allowed[_from][msg.sender] and \
60 | _value <= self.balances[_from]:
61 |
62 | self.balances[_from] -= _value # decrease balance of from address.
63 | self.allowed[_from][msg.sender] -= _value # decrease allowance.
64 | self.balances[_to] += _value # incease balance of to address.
65 | log.Transfer(_from, _to, convert(_value, 'uint256')) # log transfer event.
66 |
67 | return True
68 | else:
69 | return False
70 |
71 |
72 | # Allow _spender to withdraw from your account, multiple times, up to the _value amount.
73 | # If this function is called again it overwrites the current allowance with _value.
74 | @public
75 | def approve(_spender: address, _amount: int128(uint256)) -> bool:
76 |
77 | self.allowed[msg.sender][_spender] = _amount
78 | log.Approval(msg.sender, _spender, convert(_amount, 'uint256'))
79 |
80 | return True
81 |
82 |
83 | # Get the allowence an address has to spend anothers' token.
84 | @public
85 | def allowance(_owner: address, _spender: address) -> uint256:
86 |
87 | return convert(self.allowed[_owner][_spender], 'uint256')
88 |
--------------------------------------------------------------------------------
/examples/tokens/ERC20_solidity_compatible/ERC20.vy:
--------------------------------------------------------------------------------
1 | # Solidity-Compatible EIP20/ERC20 Token
2 | # Implements https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
3 | # Author: Phil Daian
4 |
5 | # The use of the uint256 datatype as in this token is not
6 | # recommended, as it can pose security risks.
7 |
8 | # This token is intended as a proof of concept towards
9 | # language interoperability and not for production use.
10 |
11 | # Events issued by the contract
12 | Transfer: event({_from: indexed(address), _to: indexed(address), _value: uint256(wei)})
13 | Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256(wei)})
14 |
15 | balances: uint256(wei)[address]
16 | allowances: (uint256(wei)[address])[address]
17 | num_issued: uint256(wei)
18 |
19 | @public
20 | @payable
21 | def deposit():
22 | _value: uint256(wei) = msg.value
23 | _sender: address = msg.sender
24 | self.balances[_sender] = self.balances[_sender] + _value
25 | self.num_issued = self.num_issued + _value
26 | # Fire deposit event as transfer from 0x0
27 | log.Transfer(0x0000000000000000000000000000000000000000, _sender, _value)
28 |
29 | @public
30 | def withdraw(_value : uint256(wei)) -> bool:
31 | _sender: address = msg.sender
32 | # Make sure sufficient funds are present, op will not underflow supply
33 | # implicitly through overflow protection
34 | self.balances[_sender] = self.balances[_sender] - _value
35 | self.num_issued = self.num_issued - _value
36 | send(_sender, _value)
37 | # Fire withdraw event as transfer to 0x0
38 | log.Transfer(_sender, 0x0000000000000000000000000000000000000000, _value)
39 | return True
40 |
41 | @public
42 | @constant
43 | def totalSupply() -> uint256(wei):
44 | return self.num_issued
45 |
46 | @public
47 | @constant
48 | def balanceOf(_owner : address) -> uint256(wei):
49 | return self.balances[_owner]
50 |
51 | @public
52 | def transfer(_to : address, _value : uint256(wei)) -> bool:
53 | _sender: address = msg.sender
54 | # Make sure sufficient funds are present implicitly through overflow protection
55 | self.balances[_sender] = self.balances[_sender] - _value
56 | self.balances[_to] = self.balances[_to] + _value
57 | # Fire transfer event
58 | log.Transfer(_sender, _to, _value)
59 | return True
60 |
61 | @public
62 | def transferFrom(_from : address, _to : address, _value : uint256(wei)) -> bool:
63 | _sender: address = msg.sender
64 | allowance: uint256(wei) = self.allowances[_from][_sender]
65 | # Make sure sufficient funds/allowance are present implicitly through overflow protection
66 | self.balances[_from] = self.balances[_from] - _value
67 | self.balances[_to] = self.balances[_to] + _value
68 | self.allowances[_from][_sender] = allowance - _value
69 | # Fire transfer event
70 | log.Transfer(_from, _to, _value)
71 | return True
72 |
73 | @public
74 | def approve(_spender : address, _value : uint256(wei)) -> bool:
75 | _sender: address = msg.sender
76 | self.allowances[_sender][_spender] = _value
77 | # Fire approval event
78 | log.Approval(_sender, _spender, _value)
79 | return True
80 |
81 | @public
82 | @constant
83 | def allowance(_owner : address, _spender : address) -> uint256(wei):
84 | return self.allowances[_owner][_spender]
85 |
86 |
--------------------------------------------------------------------------------
/examples/tokens/ERC20_solidity_compatible/README.md:
--------------------------------------------------------------------------------
1 | The Solidity-Compatible ERC20
2 | -----------------------------
3 |
4 | The code in this example aims at the creation of an
5 | [ERC20](https://github.com/ethereum/EIPs/issues/20) token that is fully Solidity
6 | compatible, and exhibits identical behavior to a Solidity-based ERC20 token.
7 |
8 | ERC20 was chosen due to its popularity in the wider community and its handling of
9 | large quantities of funds. Unfortunately, the ERC20 specification is written with
10 | Solidity in mind, and includes Solidity-specific data types in the function
11 | definitions.
12 |
13 | **To achieve full Solidity compatibility, we use the low-level num256 datatype in
14 | Vyper. This is NOT recommended for contracts where either full Solidity compatibility
15 | is not required, or no other compelling usage for using num256 over num exists**.
16 | Notably, num256 is not overflow protected and may not support all the automatic
17 | security features of *num* as the language evolves. As the code of this token shows,
18 | the use of num256 over num also significantly complicates the contract code.
19 |
20 | **THIS TOKEN HAS NOT BEEN AUDITED AND IS NOT RECOMMENDED FOR PRODUCTION FUNDS**.
21 | While the authors have made every effort to ensure the security of the supplied code,
22 | funds loss is always a possibility, and both Vyper's compiler and language remain
23 | nascent and rapidly evolving.
24 |
25 | Testing
26 | -------
27 |
28 | This set of ERC20s includes a test suite that achieves:
29 |
30 | - 100% branch and statement coverage (manually verified).
31 | - Independent tests from two test authors.
32 | - Differential testing against two example Solidity tokens, written independently
33 | (available in the ``nonvyper`` tests subfolder and annotated with comments).
34 |
35 | To run the tests, a local installation of pyethereum, Solidity, and Vyper is required.
36 | After installing the dependencies, run ``python run_tests.py`` in the test directory corresponding
37 | to this example.
38 |
39 | Future Plans / TODO
40 | -------------------
41 |
42 | Interesting potential extensions of this token include:
43 |
44 | - [ERC223](https://github.com/ethereum/EIPs/issues/223) functionality and testing.
45 | - Full formal verification. This is underway using the [KEVM project](https://github.com/kframework/evm-semantics).
46 | - Examples of other common token usage patterns (owner-mintable tokens being one
47 | possible example).
48 |
--------------------------------------------------------------------------------
/examples/tokens/vypercoin.vy:
--------------------------------------------------------------------------------
1 | # Vyper Port of MyToken
2 | # THIS CONTRACT HAS NOT BEEN AUDITED!
3 | # ERC20 details at:
4 | # https://theethereum.wiki/w/index.php/ERC20_Token_Standard
5 | # https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
6 | # Events of the token.
7 | Transfer: event({_from: indexed(address), _to: indexed(address), _value: uint256})
8 | Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256})
9 |
10 |
11 | # Variables of the token.
12 | name: public(bytes32)
13 | symbol: public(bytes32)
14 | totalSupply: public(uint256)
15 | decimals: public(uint256)
16 | balances: uint256[address]
17 | allowed: uint256[address][address]
18 |
19 | @public
20 | def __init__(_name: bytes32, _symbol: bytes32, _decimals: uint256, _initialSupply: uint256):
21 |
22 | assert _initialSupply * 10 ** _decimals >= _initialSupply
23 | self.totalSupply =_initialSupply * 10 ** _decimals
24 | self.balances[msg.sender] = self.totalSupply
25 | self.name = _name
26 | self.symbol = _symbol
27 | self.decimals = _decimals
28 | log.Transfer(ZERO_ADDRESS, msg.sender, self.totalSupply)
29 |
30 |
31 | # What is the balance of a particular account?
32 | @public
33 | @constant
34 | def balanceOf(_owner: address) -> uint256:
35 |
36 | return self.balances[_owner]
37 |
38 |
39 | # Send `_value` tokens to `_to` from your account
40 | @public
41 | def transfer(_to: address, _amount: uint256) -> bool:
42 |
43 | assert self.balances[msg.sender] >= _amount
44 |
45 | self.balances[msg.sender] -= _amount # Subtract from the sender
46 | self.balances[_to] += _amount # Add the same to the recipient
47 | log.Transfer(msg.sender, _to, _amount) # log transfer event.
48 |
49 | return True
50 |
51 |
52 | # Transfer allowed tokens from a specific account to another.
53 | @public
54 | def transferFrom(_from: address, _to: address, _value: uint256) -> bool:
55 |
56 | assert _value <= self.allowed[_from][msg.sender]
57 | assert _value <= self.balances[_from]
58 |
59 | self.balances[_from] -= _value # decrease balance of from address.
60 | self.allowed[_from][msg.sender] -= _value # decrease allowance.
61 | self.balances[_to] += _value # increase balance of to address.
62 | log.Transfer(_from, _to, _value) # log transfer event.
63 |
64 | return True
65 |
66 |
67 | # Allow _spender to withdraw from your account, multiple times, up to the _value amount.
68 | # If this function is called again it overwrites the current allowance with _value.
69 | @public
70 | def approve(_spender: address, _amount: uint256) -> bool:
71 |
72 | self.allowed[msg.sender][_spender] = _amount
73 | log.Approval(msg.sender, _spender, _amount)
74 |
75 | return True
76 |
77 |
78 | # Get the allowance an address has to spend another's token.
79 | @public
80 | def allowance(_owner: address, _spender: address) -> uint256:
81 |
82 | return self.allowed[_owner][_spender]
83 |
--------------------------------------------------------------------------------
/examples/wallet/sign.js:
--------------------------------------------------------------------------------
1 | // Expects:
2 | // seq: big integer or number
3 | // to: address, in the form 0x46d241f4....
4 | // value: big integer or number
5 | // data: hex data
6 | function sign(seq, to, value, data, signingAddr) {
7 | var seqHex = web3.toHex(seq).substr(2);
8 | while (seqHex.length < 64)
9 | seqHex = "0" + seqHex;
10 | var valueHex = web3.toHex(value).substr(2);
11 | while (valueHex.length < 64)
12 | valueHex = "0" + valueHex;
13 | var concatData = "0x" + seqHex + "000000000000000000000000" + to.substr(2) + valueHex + data.substr(2);
14 | var hash = web3.sha3(concatData, {encoding: 'hex'});
15 | return web3.eth.sign(signingAddr, hash);
16 | }
17 |
--------------------------------------------------------------------------------
/examples/wallet/wallet.vy:
--------------------------------------------------------------------------------
1 | # An example of how you can do a wallet in Vyper.
2 | # Warning: NOT AUDITED. Do not use to store substantial quantities of funds.
3 |
4 | # A list of the owners addresses (there are a maximum of 5 owners)
5 | owners: public(address[5])
6 | # The number of owners required to approve a transaction
7 | threshold: int128
8 | # The number of transactions that have been approved
9 | seq: public(int128)
10 |
11 |
12 | @public
13 | def __init__(_owners: address[5], _threshold: int128):
14 | for i in range(5):
15 | if _owners[i] != ZERO_ADDRESS:
16 | self.owners[i] = _owners[i]
17 | self.threshold = _threshold
18 |
19 |
20 | @public
21 | def testEcrecover(h: bytes32, v:uint256, r:uint256, s:uint256) -> address:
22 | return ecrecover(h, v, r, s)
23 |
24 |
25 | # `@payable` allows functions to receive ether
26 | @public
27 | @payable
28 | def approve(_seq: int128, to: address, value: wei_value, data: bytes[4096], sigdata: uint256[3][5]) -> bytes[4096]:
29 | # Throws if the value sent to the contract is less than the sum of the value to be sent
30 | assert msg.value >= value
31 | # Every time the number of approvals starts at 0 (multiple signatures can be added through the sigdata argument)
32 | approvals: int128 = 0
33 | # Starts by combining:
34 | # 1) The number of transactions approved thus far.
35 | # 2) The address the transaction is going to be sent to (can be a contract or a user).
36 | # 3) The value in wei that will be sent with this transaction.
37 | # 4) The data to be sent with this transaction (usually data is used to deploy contracts or to call functions on contracts, but you can put whatever you want in it).
38 | # Takes the sha3 (keccak256) hash of the combination
39 | h: bytes32 = sha3(concat(convert(_seq, bytes32), convert(to, bytes32), convert(value, bytes32), data))
40 | # Then we combine the Ethereum Signed message with our previous hash
41 | # Owners will have to sign the below message
42 | h2: bytes32 = sha3(concat("\x19Ethereum Signed Message:\n32", h))
43 | # Verifies that the caller of approve has entered the correct transaction number
44 | assert self.seq == _seq
45 | # # Iterates through all the owners and verifies that there signatures,
46 | # # given as the sigdata argument are correct
47 | for i in range(5):
48 | if sigdata[i][0] != 0:
49 | # If an invalid signature is given for an owner then the contract throws
50 | assert ecrecover(h2, sigdata[i][0], sigdata[i][1], sigdata[i][2]) == self.owners[i]
51 | # For every valid signature increase the number of approvals by 1
52 | approvals += 1
53 | # Throw if the number of approvals is less then the number of approvals required (the threshold)
54 | assert approvals >= self.threshold
55 | # The transaction has been approved
56 | # Increase the number of approved transactions by 1
57 | self.seq += 1
58 | # Use raw_call to send the transaction
59 | return raw_call(to, data, outsize=4096, gas=3000000, value=value)
60 |
61 |
62 | @public
63 | @payable
64 | def __default__():
65 | pass
66 |
--------------------------------------------------------------------------------
/logo/vyper-logo-flat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/logo/vyper-logo-flat.png
--------------------------------------------------------------------------------
/logo/vyper-logo-flat.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/logo/vyper-logo-transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/logo/vyper-logo-transparent.png
--------------------------------------------------------------------------------
/logo/vyper-logo-transparent.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/logo/vyper-logo.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/logo/vyper-logo.ai
--------------------------------------------------------------------------------
/requirements-dev.txt:
--------------------------------------------------------------------------------
1 | bumpversion
--------------------------------------------------------------------------------
/requirements-docs.txt:
--------------------------------------------------------------------------------
1 | sphinx==1.6.3
2 | recommonmark==0.4.0
3 | sphinx_rtd_theme==0.2.4
4 |
--------------------------------------------------------------------------------
/scripts/fixed_address_creator.py:
--------------------------------------------------------------------------------
1 | from ethereum import transactions, utils
2 | import rlp
3 | from ethereum.slogging import LogRecorder, configure_logging, set_level
4 | config_string = ':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace,eth.vm.exit:trace,eth.pb.msg:trace,eth.pb.tx:debug'
5 | from vyper import optimizer, compile_lll
6 | from rlp_decoder import rlp_decoder_bytes
7 |
8 | def encode_vals(vals):
9 | o = b''
10 | for v in vals:
11 | if isinstance(v, int):
12 | o += utils.encode_int32(v)
13 | else:
14 | o += v
15 | return o
16 |
17 | # Run some tests first
18 |
19 | from ethereum.tools import tester as t
20 | t.gas_limit = 1000000
21 | chain = t.Chain()
22 | t.s = chain
23 |
24 | rlp_decoder_address = t.s.tx(to=b'', data=rlp_decoder_bytes)
25 | assert t.s.tx(sender=t.k0, to=rlp_decoder_address, data=rlp.encode([b'\x45', b'\x95'])) == encode_vals([96, 129, 162, 1, b"\x45", 1, b"\x95"])
26 | assert t.s.tx(sender=t.k0, to=rlp_decoder_address, data=rlp.encode([b'cow', b'dog']))== encode_vals([96, 131, 166, 3, b"cow", 3, b"dog"])
27 | assert t.s.tx(sender=t.k0, to=rlp_decoder_address, data=rlp.encode([]))== encode_vals([32])
28 | assert t.s.tx(sender=t.k0, to=rlp_decoder_address, data=rlp.encode([b'\x73' * 100, b'dog']))== encode_vals([96, 228, 263, 100, b"\x73" * 100, 3, b"dog"])
29 | assert t.s.tx(sender=t.k0, to=rlp_decoder_address, data=utils.decode_hex('f6943535353535353535353535353535353535353535a04747474747474747474747474747474747474747474747474747474747474747'))== encode_vals([96, 148, 212, 20, b'\x35' * 20, 32, b'\x47' * 32])
30 | print("Checks passed!")
31 |
32 | t.s.tx(sender=t.k0, to=rlp_decoder_address, data=rlp.encode([]))
33 | g1 = t.s.head_state.receipts[-1].gas_used - t.s.head_state.receipts[-2].gas_used - t.s.last_tx.intrinsic_gas_used
34 | t.s.tx(sender=t.k0, to=rlp_decoder_address, data=rlp.encode([b'\x03' * 500]))
35 | g2 = t.s.head_state.receipts[-1].gas_used - t.s.head_state.receipts[-2].gas_used - t.s.last_tx.intrinsic_gas_used
36 | t.s.tx(sender=t.k0, to=rlp_decoder_address, data=rlp.encode([b'\x03'] * 25))
37 | g3 = t.s.head_state.receipts[-1].gas_used - t.s.head_state.receipts[-2].gas_used - t.s.last_tx.intrinsic_gas_used
38 | t.s.tx(sender=t.k0, to=rlp_decoder_address, data=rlp.encode([b'\x03'] * 24 + [b'\x03' * 500]))
39 | g4 = t.s.head_state.receipts[-1].gas_used - t.s.head_state.receipts[-2].gas_used - t.s.last_tx.intrinsic_gas_used
40 |
41 | print("500 bytes increment: %d" % (g2 - g1))
42 | print("500 bytes increment: %d" % (g4 - g3))
43 | print("25 items increment: %d" % (g3 - g1))
44 | print("25 items increment: %d" % (g4 - g2))
45 |
46 |
47 | # Create transaction
48 | t = transactions.Transaction(0, 30 * 10**9, 2999999, '', 0, rlp_decoder_bytes)
49 | t.startgas = t.intrinsic_gas_used + 50000 + 200 * len(rlp_decoder_bytes)
50 | t.v = 27
51 | t.r = 45
52 | t.s = 79
53 | print("RLP decoder")
54 | print("Instructions for launching:")
55 | print('First send %d wei to %s' % (t.startgas * t.gasprice,
56 | utils.checksum_encode(t.sender)))
57 | print('Publish this tx to create the contract: 0x'+utils.encode_hex(rlp.encode(t)))
58 | print('This is the contract address: '+utils.checksum_encode(utils.mk_contract_address(t.sender, 0)))
59 |
--------------------------------------------------------------------------------
/scripts/forwarder.py:
--------------------------------------------------------------------------------
1 | from ethereum import utils
2 |
3 | def mk_forwarder(address):
4 | code = b'\x36\x60\x00\x60\x00\x37' # CALLDATACOPY 0 0 (CALLDATASIZE)
5 | code += b'\x61\x10\x00\x60\x00\x36\x60\x00' # 4096 0 CALLDATASIZE 0
6 | code += b'\x73' + utils.normalize_address(address) + b'\x5a' # address gas
7 | code += b'\xf4' # delegatecall
8 | code += b'\x15\x58\x57' # ISZERO PC JUMPI (fail if inner call fails)
9 | code += b'\x61\x10\x00\x60\x00\xf3' # 4096 0 RETURN
10 | return code
11 |
12 | def mk_wrapper(code):
13 | lencodepush = b'\x60' + utils.encode_int(len(code)) # length of code
14 | returner = lencodepush + b'\x60\x0c\x60\x00' # start from 12 in code, 0 in memory
15 | returner += b'\x39' # CODECOPY
16 | returner += lencodepush + b'\x60\x00' + b'\xf3' # return code
17 | assert len(returner) == 12
18 | return returner + code
19 |
20 | kode = """
21 | moose: num
22 | def increment_moose(i: num) -> num:
23 | self.moose += i
24 | return self.moose
25 | """
26 |
27 | def test():
28 | from ethereum.tools import tester2
29 | c = tester2.Chain()
30 | x = c.contract(kode, language='vyper', sender=tester2.k3)
31 | fwdcode = mk_forwarder(x.address)
32 | initcode = mk_wrapper(fwdcode)
33 | print('Forwarder code:', initcode)
34 | y = c.contract(initcode, language='evm')
35 | assert c.head_state.get_code(y) == fwdcode
36 | z = tester2.ABIContract(c, x.translator, y)
37 | assert z.increment_moose(3) == 3
38 | assert z.increment_moose(5) == 8
39 | print('Tests passed')
40 |
41 | if __name__ == '__main__':
42 | test()
43 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [bumpversion]
2 | current_version = 0.1.0-beta.4
3 | commit = True
4 | tag = True
5 |
6 | [bumpversion:file:setup.py]
7 | search = version = "{current_version}"
8 |
9 | [aliases]
10 | test = pytest
11 |
12 | [tool:pytest]
13 | addopts = --cov-report term --cov-report html --cov=vyper
14 | python_files = test_*.py
15 | testpaths = tests
16 |
17 | [flake8]
18 | exclude = docs
19 | ignore =
20 | E122
21 | E124
22 | E127
23 | E128
24 | E501
25 | E731
26 | W504
27 |
28 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from setuptools import setup, find_packages
4 |
5 |
6 | setup(
7 | name='vyper',
8 | # *IMPORTANT*: Don't manually change the version here. Use the 'bumpversion' utility.
9 | version='0.1.0-beta.4',
10 | description='Vyper Programming Language for Ethereum',
11 | long_description_markdown_filename='README.md',
12 | author='Vitalik Buterin',
13 | author_email='',
14 | url='https://github.com/ethereum/vyper',
15 | license="MIT",
16 | keywords='ethereum',
17 | include_package_data=True,
18 | packages=find_packages(exclude=('tests', 'docs')),
19 | python_requires='>=3.6',
20 | py_modules=['vyper'],
21 | install_requires=[
22 | 'pycryptodome>=3.5.1,<4',
23 | ],
24 | setup_requires=[
25 | 'pytest-runner'
26 | ],
27 | tests_require=[
28 | 'pytest',
29 | 'pytest-cov',
30 | 'py-evm==0.2.0a32',
31 | 'eth-tester[py-evm]==0.1.0b32',
32 | 'web3==4.4.1',
33 | ],
34 | scripts=[
35 | 'bin/vyper',
36 | 'bin/vyper-serve',
37 | 'bin/vyper-lll'
38 | ],
39 | classifiers=[
40 | 'Intended Audience :: Developers',
41 | 'License :: OSI Approved :: MIT License',
42 | 'Programming Language :: Python :: 3.6',
43 | ]
44 | )
45 |
--------------------------------------------------------------------------------
/snap/snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: vyper
2 | version: git
3 | summary: Experimental language for the Ethereum Virtual Machine
4 | description: |
5 | Vyper is an contract-oriented, pythonic programming language that targets the Ethereum Virtual Machine (EVM)
6 |
7 | grade: devel # must be 'stable' to release into candidate/stable channels
8 | confinement: devmode # use 'strict' once you have the right plugs and slots
9 |
10 | apps:
11 | vyper:
12 | command: vyper
13 |
14 | parts:
15 | vyper:
16 | source: .
17 | plugin: python
18 | python-version: python3
19 | after: [python]
20 | stage:
21 | - -usr/bin/python3
22 | python:
23 | source: https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tar.xz
24 | plugin: autotools
25 | configflags:
26 | - --prefix=/usr
27 | build-packages:
28 | - gcc
29 | - libreadline-dev
30 | - libncursesw5-dev
31 | - zlib1g-dev
32 | - libbz2-dev
33 | - liblzma-dev
34 | - libgdbm-dev
35 | - libdb-dev
36 | - libssl-dev
37 | - libexpat1-dev
38 | - libmpdec-dev
39 | - libbluetooth-dev
40 | - libsqlite3-dev
41 | - libffi-dev
42 | stage-packages:
43 | - libc6
44 | stage:
45 | - -usr/lib/python3.6/test
46 | - -usr/bin/pydoc3
47 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/tests/__init__.py
--------------------------------------------------------------------------------
/tests/compiler/LLL/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/tests/compiler/LLL/__init__.py
--------------------------------------------------------------------------------
/tests/compiler/LLL/test_compile_lll.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from vyper.parser.parser import LLLnode
4 | from vyper.parser.s_expressions import parse_s_exp
5 |
6 |
7 | fail_list = [
8 | [-2**255 - 3],
9 | [2**256 + 3],
10 | ['set', '_poz'],
11 | [['set', 'var_1', 0, 0]],
12 | ['with', 'var_1', 0, ['set', 1, 1]],
13 | ['break'], # invalid break
14 | ['continue'], # invalid continue
15 | ['invalidllelement']
16 | ]
17 |
18 |
19 | @pytest.mark.parametrize('bad_lll', fail_list)
20 | def test_lll_compile_fail(bad_lll, get_contract_from_lll, assert_compile_failed):
21 | assert_compile_failed(
22 | lambda: get_contract_from_lll(LLLnode.from_list(bad_lll)),
23 | Exception
24 | )
25 |
26 |
27 | valid_list = [
28 | ['pass'],
29 | ['clamplt', ['mload', 0], 300],
30 | ['clampgt', ['mload', 0], -1],
31 | ['uclampgt', 1, ['mload', 0]],
32 | ['uclampge', ['mload', 0], 0],
33 | ]
34 |
35 |
36 | @pytest.mark.parametrize('good_lll', valid_list)
37 | def test_compile_lll_good(good_lll, get_contract_from_lll):
38 | get_contract_from_lll(LLLnode.from_list(good_lll))
39 |
40 |
41 | def test_lll_from_s_expression(get_contract_from_lll):
42 | code = """
43 | (seq
44 | (return
45 | 0
46 | (lll ; just return 32 byte of calldata back
47 | (seq
48 | (calldatacopy 0 4 32)
49 | (return 0 32)
50 | stop
51 | )
52 | 0)))
53 | """
54 | abi = [{
55 | "name": "test",
56 | "outputs": [{
57 | "type": "int128",
58 | "name": "out"
59 | }],
60 | "inputs": [{
61 | "type": "int128",
62 | "name": "a"
63 | }],
64 | "constant": False,
65 | "payable": False,
66 | "type": "function",
67 | "gas": 394
68 | }]
69 |
70 | s_expressions = parse_s_exp(code)
71 | lll = LLLnode.from_list(s_expressions[0])
72 | c = get_contract_from_lll(lll, abi=abi)
73 | assert c.test(-123456) == -123456
74 |
--------------------------------------------------------------------------------
/tests/compiler/LLL/test_repeat.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | def test_repeat(get_contract_from_lll, assert_compile_failed):
4 | good_lll = ['repeat', 0, 0, 1, ['seq']]
5 | bad_lll_1 = ['repeat', 0, 0, 0, ['seq']]
6 | bad_lll_2 = ['repeat', 0, 0, -1, ['seq']]
7 | get_contract_from_lll(good_lll)
8 | assert_compile_failed(lambda: get_contract_from_lll(bad_lll_1), Exception)
9 | assert_compile_failed(lambda: get_contract_from_lll(bad_lll_2), Exception)
10 |
--------------------------------------------------------------------------------
/tests/compiler/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/tests/compiler/__init__.py
--------------------------------------------------------------------------------
/tests/compiler/test_bytecode_runtime.py:
--------------------------------------------------------------------------------
1 | from vyper import compiler
2 |
3 |
4 | def test_bytecode_runtime():
5 | code = """
6 | @public
7 | def a() -> bool:
8 | return True
9 | """
10 |
11 | bytecode = compiler.compile(code)
12 | bytecode_runtime = compiler.compile(code, bytecode_runtime=True)
13 |
14 | assert len(bytecode) > len(bytecode_runtime)
15 | assert bytecode_runtime in bytecode
16 |
--------------------------------------------------------------------------------
/tests/compiler/test_calldatacopy.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | def test_calldatacopy(get_contract_from_lll):
4 | lll = ['calldatacopy', 32, 0, ['calldatasize']]
5 | get_contract_from_lll(lll)
6 |
--------------------------------------------------------------------------------
/tests/compiler/test_pre_parser.py:
--------------------------------------------------------------------------------
1 | from vyper.exceptions import StructureException
2 | from pytest import raises
3 |
4 |
5 | def test_semicolon_prohibited(get_contract):
6 | code = """@public
7 | def test() -> int128:
8 | a: int128 = 1; b: int128 = 2
9 | return a + b
10 | """
11 |
12 | with raises(StructureException):
13 | get_contract(code)
14 |
15 |
16 | def test_valid_semicolons(get_contract):
17 | code = """
18 | @public
19 | def test() -> int128:
20 | a: int128 = 1
21 | b: int128 = 2
22 | s: bytes[300] = "this should not be a problem; because it is in a string"
23 | s = \"\"\"this should not be a problem; because it's in a string\"\"\"
24 | s = 'this should not be a problem;;; because it\\\'s in a string'
25 | s = '''this should not ; \'cause it\'s in a string'''
26 | s = "this should not be \\\"; because it's in a ;\\\"string;\\\";"
27 | return a + b
28 | """
29 | c = get_contract(code)
30 | assert c.test() == 3
31 |
32 |
33 | def test_external_contract_definition_alias(get_contract):
34 | contract_1 = """
35 | @public
36 | def bar() -> int128:
37 | return 1
38 | """
39 |
40 | contract_2 = """
41 | contract Bar():
42 | def bar() -> int128: modifying
43 |
44 | bar_contract: Bar
45 |
46 | @public
47 | def foo(contract_address: address) -> int128:
48 | self.bar_contract = contract_address
49 | return self.bar_contract.bar()
50 | """
51 |
52 | c1 = get_contract(contract_1)
53 | c2 = get_contract(contract_2)
54 | assert c2.foo(c1.address) == 1
55 |
56 |
57 | def test_version_pragma(get_contract):
58 | from vyper import __version__
59 | code = """
60 | # @version {}
61 |
62 | @public
63 | def test():
64 | pass
65 | """.format(__version__)
66 | assert get_contract(code)
67 |
68 |
69 | def test_version_empty_version(assert_compile_failed, get_contract):
70 | code = """
71 | #@version
72 |
73 | @public
74 | def test():
75 | pass
76 | """
77 | assert_compile_failed(lambda: get_contract(code))
78 |
79 |
80 | def test_version_empty_version_mismatch(assert_compile_failed, get_contract):
81 | code = """
82 | # @version 9.9.9
83 |
84 | @public
85 | def test():
86 | pass
87 | """
88 | assert_compile_failed(lambda: get_contract(code))
89 |
90 |
91 | def test_version_empty_invalid_version_string(assert_compile_failed, get_contract):
92 | code = """
93 | # @version hello
94 |
95 | @public
96 | def test():
97 | pass
98 | """
99 | assert_compile_failed(lambda: get_contract(code))
100 |
101 |
102 | def test_unbalanced_parens(assert_compile_failed, get_contract):
103 | code = """
104 | @public
105 | def foo():
106 | convert(
107 | """
108 |
109 | with raises(StructureException):
110 | get_contract(code)
111 |
--------------------------------------------------------------------------------
/tests/compiler/test_sha3_32.py:
--------------------------------------------------------------------------------
1 | from vyper.parser.parser_utils import LLLnode
2 | from vyper import compile_lll, optimizer
3 |
4 |
5 | def test_sha3_32():
6 | lll = ['sha3_32', 0]
7 | evm = ['PUSH1', 0, 'PUSH1', 192, 'MSTORE', 'PUSH1', 32, 'PUSH1', 192, 'SHA3']
8 | assert compile_lll.compile_to_assembly(LLLnode.from_list(lll)) == evm
9 | assert compile_lll.compile_to_assembly(optimizer.optimize(LLLnode.from_list(lll))) == evm
10 |
--------------------------------------------------------------------------------
/tests/examples/name_registry/test_name_registry.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | def test_name_registry(w3, get_contract, assert_tx_failed):
4 | a0, a1 = w3.eth.accounts[:2]
5 | with open('examples/name_registry/name_registry.vy') as f:
6 | code = f.read()
7 | c = get_contract(code)
8 | c.register(b'jacques', a0, transact={})
9 | assert c.lookup(b'jacques') == a0
10 | assert_tx_failed(lambda: c.register(b'jacques', a1))
11 |
--------------------------------------------------------------------------------
/tests/examples/tokens/ERC20_solidity_compatible/run_tests.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from test import erc20_tests_1
3 | from test import erc20_tests_2
4 |
5 |
6 | def prettyprint(message):
7 | print("~" * 80, "\n" + message, "\n" + "~" * 80)
8 |
9 |
10 | success = True
11 |
12 | # Run first test suite (Phil Daian) on each contract
13 | prettyprint("Running Solidity-compatible ERC20 tests, Suite 1")
14 | res = unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromModule(erc20_tests_1))
15 | success &= res.wasSuccessful()
16 | prettyprint("Finished Solidity-compatible ERC20 tests, Suite 1")
17 |
18 | # Run second test suite (Florian Tramer) on each contract
19 | prettyprint("Running Solidity-compatible ERC20 tests, Suite 2")
20 | res = unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromModule(erc20_tests_2))
21 | success &= res.wasSuccessful()
22 | prettyprint("Finished Solidity-compatible ERC20 tests, Suite 2")
23 |
24 | if not success:
25 | print("FAILED : Test failures encounting, exiting with error.")
26 | exit(1)
27 | else:
28 | print("All tests completed successfully.")
29 |
--------------------------------------------------------------------------------
/tests/examples/tokens/ERC20_solidity_compatible/test/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/tests/examples/tokens/ERC20_solidity_compatible/test/__init__.py
--------------------------------------------------------------------------------
/tests/examples/tokens/ERC20_solidity_compatible/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/tests/examples/tokens/ERC20_solidity_compatible/utils/__init__.py
--------------------------------------------------------------------------------
/tests/examples/tokens/ERC20_solidity_compatible/utils/pyethereum_test_utils.py:
--------------------------------------------------------------------------------
1 | """ Utility class for testing via pyethereum """
2 |
3 | from ethereum.tools import tester
4 | from ethereum import utils
5 |
6 | import os
7 | import unittest
8 |
9 |
10 | # Extract language from contract extension
11 | def extract_language(sourcefile):
12 | languages = {
13 | '.sol': 'solidity',
14 | '.vy': 'vyper',
15 | '.py': 'vyper' # hack to handle new .vy suggested Vyper extension
16 | }
17 | _, ext = os.path.splitext(sourcefile)
18 | language = languages[ext]
19 | return language
20 |
21 |
22 | def bytes_to_int(bytez):
23 | return int(utils.encode_hex(bytez), 16)
24 |
25 |
26 | def int_to_bytes(i):
27 | return int(i).to_bytes(32, byteorder='big')
28 |
29 |
30 | class PyEthereumTestCase(unittest.TestCase):
31 |
32 | t = None # ethereum.tools.tester module
33 | s = None # Chain object
34 | c = None # Main contract
35 | initial_state = None # Initial state of the chain
36 |
37 | @classmethod
38 | def setUpClass(cls):
39 | super(PyEthereumTestCase, cls).setUpClass()
40 |
41 | # Initialize tester, contract and expose relevant objects
42 | cls.t = tester
43 | cls.s = cls.t.Chain()
44 |
45 | cls.s.head_state.gas_limit = 10**80
46 | cls.s.head_state.set_balance(cls.t.a0, 10**80)
47 | cls.s.head_state.set_balance(cls.t.a1, 10**80)
48 | cls.s.head_state.set_balance(cls.t.a2, 10**80)
49 | cls.s.head_state.set_balance(cls.t.a3, 10**80)
50 | cls.initial_state = None
51 |
52 | def setUp(self):
53 | self.longMessage = True
54 | self.s.revert(self.initial_state)
55 | self.gas_used_before = self.s.head_state.gas_used
56 | self.refunds_before = self.s.head_state.refunds
57 |
58 | from ethereum.slogging import get_logger
59 | get_logger('eth.pb.tx')
60 | get_logger('eth.pb.msg')
61 |
62 | def tearDown(self):
63 | gas_used_after = self.s.head_state.gas_used
64 | print("Test used {} gas".format(gas_used_after - self.gas_used_before))
65 |
66 | def deploy_contract_from_file(self, contract_file, sender=None, value=0):
67 | with open(contract_file, 'r') as in_file:
68 | code = in_file.read()
69 |
70 | if sender is not None:
71 | return self.s.contract(code, language=extract_language(contract_file),
72 | sender=sender, value=value, startgas=10**20)
73 | else:
74 | return self.s.contract(code, language=extract_language(contract_file),
75 | value=value, startgas=10**20)
76 |
77 | def check_logs(self, topics, data):
78 | found = False
79 | for log_entry in self.s.head_state.receipts[-1].logs:
80 | if topics == log_entry.topics and data == log_entry.data:
81 | found = True
82 |
83 | self.assertTrue(found, self.s.head_state.receipts[-1].logs)
84 |
85 | def assert_tx_failed(self, function_to_test,
86 | exception=tester.TransactionFailed):
87 | """ Ensure that transaction fails, reverting state
88 | (to prevent gas exhaustion) """
89 | initial_state = self.s.snapshot()
90 | self.assertRaises(exception, function_to_test)
91 | self.s.revert(initial_state)
92 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/tests/parser/exceptions/__init__.py
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_constancy_exception.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import ConstancyViolationException
6 |
7 |
8 | fail_list = [
9 | """
10 | x: int128
11 | @public
12 | @constant
13 | def foo() -> int128:
14 | self.x = 5
15 | """,
16 | """
17 | @public
18 | @constant
19 | def foo() -> int128:
20 | send(0x1234567890123456789012345678901234567890, 5)
21 | """,
22 | """
23 | @public
24 | @constant
25 | def foo() -> int128:
26 | selfdestruct(0x1234567890123456789012345678901234567890)
27 | """,
28 | """
29 | x: timedelta
30 | y: int128
31 | @public
32 | @constant
33 | def foo() -> int128(sec):
34 | self.y = 9
35 | return 5
36 | """,
37 | """
38 | @public
39 | @constant
40 | def foo() -> int128:
41 | x = raw_call(0x1234567890123456789012345678901234567890, "cow", outsize=4, gas=595757, value=9)
42 | return 5
43 | """,
44 | """
45 | @public
46 | @constant
47 | def foo() -> int128:
48 | x = create_with_code_of(0x1234567890123456789012345678901234567890, value=9)
49 | return 5
50 | """,
51 | """
52 | @public
53 | def foo(x: int128):
54 | x = 5
55 | """,
56 | """
57 | f:int128
58 |
59 | @public
60 | def a (x:int128)->int128:
61 | self.f = 100
62 | return x+5
63 |
64 | @constant
65 | @public
66 | def b():
67 | p: int128 = self.a(10)
68 | """,
69 | """
70 | f:int128
71 |
72 | @public
73 | def a (x:int128):
74 | self.f = 100
75 |
76 | @constant
77 | @public
78 | def b():
79 | self.a(10)
80 | """
81 | ]
82 |
83 |
84 | @pytest.mark.parametrize('bad_code', fail_list)
85 | def test_constancy_violation_exception(bad_code):
86 | with raises(ConstancyViolationException):
87 | compiler.compile(bad_code)
88 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_function_declaration_exception.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import FunctionDeclarationException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo(x: int128, x: int128): pass
12 | """,
13 | """
14 | @public
15 | def foo(int128: int128):
16 | pass
17 | """,
18 | """
19 | @public
20 | def foo():
21 | x: int128
22 | @public
23 | def foo():
24 | y: int128
25 | """,
26 | """
27 | @public
28 | def foo():
29 | self.goo()
30 |
31 | @public
32 | def goo():
33 | self.foo()
34 | """,
35 | """
36 | foo: int128
37 |
38 | @public
39 | def foo():
40 | pass
41 | """,
42 | """
43 | x: int128
44 |
45 | @public
46 | def foo(x: int128): pass
47 | """,
48 | ]
49 |
50 |
51 | @pytest.mark.parametrize('bad_code', fail_list)
52 | def test_function_declaration_exception(bad_code):
53 | with raises(FunctionDeclarationException):
54 | compiler.compile(bad_code)
55 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_insufficient_arguments.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import StructureException
6 |
7 | fail_list = [
8 | """
9 | @public
10 | def foo() -> int128:
11 | return as_wei_value(10)
12 | """
13 | ]
14 |
15 |
16 | @pytest.mark.parametrize('bad_code', fail_list)
17 | def test_insufficient_arguments(bad_code):
18 | with raises(StructureException) as ex:
19 | compiler.compile(bad_code)
20 | assert "Not enough arguments for function: as_wei_value" in str(ex.value)
21 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_invalid_literal_exception.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import InvalidLiteralException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo():
12 | x = 0x12345678901234567890123456789012345678901
13 | """,
14 | """
15 | @public
16 | def foo():
17 | x = 0x01234567890123456789012345678901234567890
18 | """,
19 | """
20 | @public
21 | def foo():
22 | x = 0x123456789012345678901234567890123456789
23 | """,
24 | """
25 | @public
26 | def foo():
27 | x: int128 = -170141183460469231731687303715884105729 # -2**127 - 1
28 | """,
29 | """
30 | @public
31 | def foo():
32 | x: decimal = -170141183460469231731687303715884105728.
33 | """,
34 | """
35 | b: decimal
36 | @public
37 | def foo():
38 | self.b = 7.5178246872145875217495129745982164981654986129846
39 | """,
40 | """
41 | @public
42 | def foo():
43 | x = "these bytes are nо gооd because the o's are from the Russian alphabet"
44 | """,
45 | """
46 | @public
47 | def foo():
48 | x = "这个傻老外不懂中文"
49 | """,
50 | """
51 | @public
52 | def foo():
53 | x = raw_call(0x123456789012345678901234567890123456789, "cow", outsize=4)
54 | """,
55 | """
56 | @public
57 | def foo():
58 | x = create_with_code_of(0x123456789012345678901234567890123456789)
59 | """,
60 | """
61 | @public
62 | def foo():
63 | x = as_wei_value(5.1824, "babbage")
64 | """,
65 | """
66 | @public
67 | def foo():
68 | x = as_wei_value(0x05, "babbage")
69 | """,
70 | """
71 | @public
72 | def foo():
73 | x = as_wei_value(5, "vader")
74 | """,
75 | """
76 | @public
77 | def foo():
78 | send(0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae, 5)
79 | """,
80 | """
81 | @public
82 | def foo():
83 | x: uint256 = convert(821649876217461872458712528745872158745214187264875632587324658732648753245328764872135671285218762145, uint256)
84 | """,
85 | """
86 | @public
87 | def foo():
88 | x = convert(-1, uint256)
89 | """,
90 | """
91 | @public
92 | def foo():
93 | x = convert(3.1415, uint256)
94 | """,
95 | """
96 | # Test decimal limit.
97 | a:decimal
98 |
99 | @public
100 | def foo():
101 | self.a = 170141183460469231731687303715884105727.888
102 | """,
103 | """
104 | @public
105 | def foo():
106 | a: bytes[100] = "ѓtest"
107 | """,
108 | """
109 | @public
110 | def foo():
111 | a: bytes32 = sha3("ѓtest")
112 | """,
113 | """
114 | @public
115 | def overflow() -> uint256:
116 | return 2**256
117 | """,
118 | """
119 | @public
120 | def overflow2() -> uint256:
121 | a: uint256 = 2**256
122 | return a
123 | """
124 | ]
125 |
126 |
127 | @pytest.mark.parametrize('bad_code', fail_list)
128 | def test_invalid_literal_exception(bad_code):
129 | with raises(InvalidLiteralException):
130 | compiler.compile(bad_code)
131 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_invalid_payable.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import NonPayableViolationException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo():
12 | x = msg.value
13 | """
14 | ]
15 |
16 |
17 | @pytest.mark.parametrize('bad_code', fail_list)
18 | def test_variable_decleration_exception(bad_code):
19 | with raises(NonPayableViolationException):
20 | compiler.compile(bad_code)
21 |
22 |
23 | valid_list = [
24 | """
25 | x: int128
26 | @public
27 | @payable
28 | def foo() -> int128:
29 | self.x = 5
30 | return self.x
31 | """,
32 | """
33 | @public
34 | @payable
35 | def foo():
36 | x: wei_value = msg.value
37 | """
38 | ]
39 |
40 |
41 | @pytest.mark.parametrize('good_code', valid_list)
42 | def test_block_success(good_code):
43 | assert compiler.compile(good_code) is not None
44 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_invalid_same_variable_assignment.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import VariableDeclarationException
6 |
7 | fail_list = ["""
8 | @public
9 | def test1(b: uint256) -> uint256:
10 | a: uint256 = a + b
11 | return a
12 | """,
13 | """
14 | @public
15 | def test2(b: uint256, c: uint256) -> uint256:
16 | a: uint256 = a + b + c
17 | """,
18 | """
19 | @public
20 | def test3(b: uint256, c: uint256) -> uint256:
21 | a: uint256 = - a
22 | return a
23 | """,
24 | """
25 | @public
26 | def test4(b: bool) -> bool:
27 | a: bool = b or a
28 | return a
29 | """,
30 | """
31 | @public
32 | def test5(b: bool) -> bool:
33 | a: bool = a != b
34 | return a
35 | """,
36 | """
37 | @public
38 | def test6(b:bool, c: bool) -> bool:
39 | a: bool = (a and b) and c
40 | return a
41 | """
42 | ]
43 |
44 |
45 | @pytest.mark.parametrize('bad_code', fail_list)
46 | def test_invalid_type_exception(bad_code):
47 | with raises(VariableDeclarationException):
48 | compiler.compile(bad_code)
49 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_invalid_type_exception.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import InvalidTypeException
6 |
7 | fail_list = [
8 | """
9 | x: bat
10 | """,
11 | """
12 | x: 5
13 | """,
14 | """
15 | x: int128[int]
16 | """,
17 | """
18 | x: int128[-1]
19 | """,
20 | """
21 | x: int128[3.5]
22 | """,
23 | """
24 | x: {int128[5]: int128[7]}
25 | """,
26 | """
27 | x: [bar, baz]
28 | """,
29 | """
30 | x: [bar(int128), baz(baffle)]
31 | """,
32 | """
33 | x: {bar: int128, decimal: int128}
34 | """,
35 | """
36 | x: {bar: int128, 5: int128}
37 | """,
38 | """
39 | def foo(x): pass
40 | """,
41 | """
42 | b: {num: int128, address: address}
43 | """,
44 | """
45 | b: {num: int128, address: address}
46 | """,
47 | """
48 | b: int128[int128, decimal]
49 | """,
50 | """
51 | b: int128[int128: address]
52 | """,
53 | """
54 | x: int128[address[bool]]
55 | @public
56 | def foo() -> int128(wei / sec):
57 | pass
58 | """,
59 | """
60 | @public
61 | def foo() -> {cow: int128, dog: int128}:
62 | return {cow: 5, dog: 7}
63 | """,
64 | """
65 | x: wei(wei)
66 | """,
67 | """
68 | x: int128(address)
69 | """,
70 | """
71 | x: int128(wei and sec)
72 | """,
73 | """
74 | x: int128(2 ** 2)
75 | """,
76 | """
77 | x: int128(wei ** -1)
78 | """,
79 | """
80 | x: int128(wei >> 3)
81 | """,
82 | """
83 | x: bytes <= wei
84 | """,
85 | """
86 | x: string <= 33
87 | """,
88 | """
89 | x: bytes[1:3]
90 | """,
91 | """
92 | x: bytes[33.3]
93 | """,
94 | ]
95 |
96 |
97 | @pytest.mark.parametrize('bad_code', fail_list)
98 | def test_invalid_type_exception(bad_code):
99 | with raises(InvalidTypeException):
100 | compiler.compile(bad_code)
101 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_parser_exception_pos.py:
--------------------------------------------------------------------------------
1 | from pytest import raises
2 |
3 | from vyper.exceptions import ParserException
4 |
5 |
6 | def test_type_exception_pos():
7 | pos = (1, 2)
8 |
9 | with raises(ParserException) as e:
10 | raise ParserException('Fail!', pos)
11 |
12 | assert e.value.lineno == 1
13 | assert e.value.col_offset == 2
14 | assert str(e.value) == 'line 1:2 Fail!'
15 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_type_mismatch_exception.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 | fail_list = [
8 | """
9 | @public
10 | def test_func() -> int128:
11 | return (1, 2)
12 | """,
13 | ]
14 |
15 |
16 | @pytest.mark.parametrize('bad_code', fail_list)
17 | def test_type_mismatch_exception(bad_code):
18 | with raises(TypeMismatchException):
19 | compiler.compile(bad_code)
20 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_undef_function.py:
--------------------------------------------------------------------------------
1 | from pytest import raises
2 |
3 | from vyper import compiler
4 | from vyper.exceptions import StructureException
5 |
6 |
7 | def test_undef_toplevel():
8 | code = """
9 | @public
10 | def foo():
11 | x = bar(55)
12 | """
13 | with raises(StructureException) as ex:
14 | compiler.compile(code)
15 | assert "Not a top-level function: bar" in str(ex.value)
16 |
17 |
18 | def test_undef_suggestion():
19 | code = """
20 | @public
21 | def bar(x: int128) -> int128:
22 | return 3 * x
23 |
24 | @public
25 | def foo() -> int128:
26 | return bar(20)
27 | """
28 | with raises(StructureException) as ex:
29 | compiler.compile(code)
30 | assert "Not a top-level function: bar" in str(ex.value)
31 | assert "Did you mean self.bar?" in str(ex.value)
32 |
--------------------------------------------------------------------------------
/tests/parser/exceptions/test_variable_declaration_exception.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import VariableDeclarationException
6 |
7 |
8 | fail_list = [
9 | """
10 | x: int128
11 | x: int128
12 | """,
13 | """
14 | CALLDATACOPY: int128
15 | """,
16 | """
17 | int128: bytes[3]
18 | """,
19 | """
20 | sec: int128
21 | """,
22 | """
23 | @public
24 | def foo():
25 | BALANCE = 45
26 | """,
27 | """
28 | @public
29 | def foo():
30 | true = 3
31 | """,
32 | """
33 | x: wei_value
34 |
35 | @public
36 | def foo():
37 | send(0x1234567890123456789012345678901234567890, x)
38 | """,
39 | """
40 | @public
41 | def foo():
42 | x = 5
43 | x: int128
44 | """,
45 | """
46 | @public
47 | def foo():
48 | x: int128
49 | x: int128
50 | """,
51 | """
52 | @public
53 | def foo():
54 | int128 = 5
55 | """,
56 | """
57 | @public
58 | def foo():
59 | bork = zork
60 | """,
61 | """
62 | b: int128
63 | @public
64 | def foo():
65 | b = 7
66 | """,
67 | """
68 | x: int128
69 | @public
70 | def foo():
71 | x = 5
72 | """,
73 | ]
74 |
75 |
76 | @pytest.mark.parametrize('bad_code', fail_list)
77 | def test_variable_declaration_exception(bad_code):
78 | with raises(VariableDeclarationException):
79 | compiler.compile(bad_code)
80 |
--------------------------------------------------------------------------------
/tests/parser/features/arithmetic/test_modulo.py:
--------------------------------------------------------------------------------
1 | from vyper.exceptions import TypeMismatchException
2 | from decimal import Decimal
3 |
4 |
5 | def test_modulo(get_contract_with_gas_estimation):
6 | code = """
7 | @public
8 | def num_modulo_num() -> int128:
9 | return 1 % 2
10 |
11 | @public
12 | def decimal_modulo_decimal() -> decimal:
13 | return 1.5 % .33
14 |
15 | @public
16 | def decimal_modulo_num() -> decimal:
17 | return .5 % 1.0
18 |
19 |
20 | @public
21 | def num_modulo_decimal() -> decimal:
22 | return 1.5 % 1.0
23 | """
24 | c = get_contract_with_gas_estimation(code)
25 | assert c.num_modulo_num() == 1
26 | assert c.decimal_modulo_decimal() == Decimal('.18')
27 | assert c.decimal_modulo_num() == Decimal('.5')
28 | assert c.num_modulo_decimal() == Decimal('.5')
29 |
30 |
31 | def test_modulo_with_different_units(assert_compile_failed, get_contract_with_gas_estimation):
32 | code = """
33 | units: {
34 | currency_value: "a currency amount"
35 | }
36 | @public
37 | def foo(a: int128(currency_value), b: int128):
38 | x: int128 = a % b
39 | """
40 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code), TypeMismatchException)
41 |
42 |
43 | def test_modulo_with_positional_input(assert_compile_failed, get_contract_with_gas_estimation):
44 | code = """
45 | @public
46 | def foo(a: int128(sec, positional), b: int128):
47 | x: int128 = a % b
48 | """
49 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code), TypeMismatchException)
50 |
51 |
52 | def test_modulo_with_input_of_zero(assert_tx_failed, get_contract_with_gas_estimation):
53 | code = """
54 | @public
55 | def foo(a: decimal, b: decimal) -> decimal:
56 | return a % b
57 | """
58 | c = get_contract_with_gas_estimation(code)
59 | assert_tx_failed(lambda: c.foo(Decimal('1'), Decimal('0')))
60 |
--------------------------------------------------------------------------------
/tests/parser/features/decorators/test_constant.py:
--------------------------------------------------------------------------------
1 | from vyper.exceptions import StructureException
2 |
3 |
4 | def test_constant_test(get_contract_with_gas_estimation_for_constants):
5 | constant_test = """
6 | @public
7 | @constant
8 | def foo() -> int128:
9 | return 5
10 | """
11 |
12 | c = get_contract_with_gas_estimation_for_constants(constant_test)
13 | assert c.foo() == 5
14 |
15 | print("Passed constant function test")
16 |
17 |
18 | def test_invalid_constant_and_payable(get_contract_with_gas_estimation_for_constants, assert_compile_failed):
19 | code = """
20 | @public
21 | @payable
22 | @constant
23 | def foo() -> num:
24 | return 5
25 | """
26 | assert_compile_failed(lambda: get_contract_with_gas_estimation_for_constants(code), StructureException)
27 |
--------------------------------------------------------------------------------
/tests/parser/features/decorators/test_public.py:
--------------------------------------------------------------------------------
1 | from vyper.exceptions import StructureException
2 |
3 |
4 | def test_invalid_if_both_public_and_internal(assert_compile_failed, get_contract_with_gas_estimation):
5 | code = """
6 | @public
7 | @private
8 | def foo():
9 | x = 1
10 | """
11 |
12 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code), StructureException)
13 |
14 |
15 | def test_invalid_if_visibility_isnt_declared(assert_compile_failed, get_contract_with_gas_estimation):
16 | code = """
17 | def foo():
18 | x = 1
19 | """
20 |
21 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code), StructureException)
22 |
--------------------------------------------------------------------------------
/tests/parser/features/iteration/test_break.py:
--------------------------------------------------------------------------------
1 | from decimal import Decimal
2 |
3 |
4 | def test_break_test(get_contract_with_gas_estimation):
5 | break_test = """
6 | @public
7 | def log(n: decimal) -> int128:
8 | c: decimal = n * 1.0
9 | output: int128 = 0
10 | for i in range(400):
11 | c = c / 1.2589
12 | if c < 1.0:
13 | output = i
14 | break
15 | return output
16 | """
17 |
18 | c = get_contract_with_gas_estimation(break_test)
19 |
20 | assert c.log(Decimal('1')) == 0
21 | assert c.log(Decimal('2')) == 3
22 | assert c.log(Decimal('10')) == 10
23 | assert c.log(Decimal('200')) == 23
24 |
25 | print('Passed for-loop break test')
26 |
27 |
28 | def test_break_test_2(get_contract_with_gas_estimation):
29 | break_test_2 = """
30 | @public
31 | def log(n: decimal) -> int128:
32 | c: decimal = n * 1.0
33 | output: int128 = 0
34 | for i in range(40):
35 | if c < 10.0:
36 | output = i * 10
37 | break
38 | c = c / 10.0
39 | for i in range(10):
40 | c = c / 1.2589
41 | if c < 1.0:
42 | output = output + i
43 | break
44 | return output
45 | """
46 |
47 | c = get_contract_with_gas_estimation(break_test_2)
48 | assert c.log(Decimal('1')) == 0
49 | assert c.log(Decimal('2')) == 3
50 | assert c.log(Decimal('10')) == 10
51 | assert c.log(Decimal('200')) == 23
52 | assert c.log(Decimal('4000000')) == 66
53 | print('Passed for-loop break test 2')
54 |
55 |
56 | def test_break_test_3(get_contract_with_gas_estimation):
57 | break_test_3 = """
58 | @public
59 | def log(n: int128) -> int128:
60 | c: decimal = convert(n, decimal)
61 | output: int128 = 0
62 | for i in range(40):
63 | if c < 10.0:
64 | output = i * 10
65 | break
66 | c /= 10.0
67 | for i in range(10):
68 | c /= 1.2589
69 | if c < 1.0:
70 | output = output + i
71 | break
72 | return output
73 | """
74 |
75 | c = get_contract_with_gas_estimation(break_test_3)
76 | assert c.log(1) == 0
77 | assert c.log(2) == 3
78 | assert c.log(10) == 10
79 | assert c.log(200) == 23
80 | assert c.log(4000000) == 66
81 | print('Passed aug-assignment break composite test')
82 |
--------------------------------------------------------------------------------
/tests/parser/features/iteration/test_continue.py:
--------------------------------------------------------------------------------
1 | def test_continue1(get_contract_with_gas_estimation):
2 | code = """
3 | @public
4 | def foo() -> bool:
5 | for i in range(2):
6 | continue
7 | return False
8 | return True
9 | """
10 | c = get_contract_with_gas_estimation(code)
11 | assert c.foo()
12 |
13 |
14 | def test_continue2(get_contract_with_gas_estimation):
15 | code = """
16 | @public
17 | def foo() -> int128:
18 | x: int128 = 0
19 | for i in range(3):
20 | x += 1
21 | continue
22 | x -= 1
23 | return x
24 | """
25 | c = get_contract_with_gas_estimation(code)
26 | assert c.foo() == 3
27 |
28 |
29 | def test_continue3(get_contract_with_gas_estimation):
30 | code = """
31 | @public
32 | def foo() -> int128:
33 | x: int128 = 0
34 | for i in range(3):
35 | x += i
36 | continue
37 | return x
38 | """
39 | c = get_contract_with_gas_estimation(code)
40 | assert c.foo() == 3
41 |
42 |
43 | def test_continue4(get_contract_with_gas_estimation):
44 | code = """
45 | @public
46 | def foo() -> int128:
47 | x: int128 = 0
48 | for i in range(6):
49 | if i % 2 == 0:
50 | continue
51 | x += 1
52 | return x
53 | """
54 | c = get_contract_with_gas_estimation(code)
55 | assert c.foo() == 3
56 |
--------------------------------------------------------------------------------
/tests/parser/features/iteration/test_repeater.py:
--------------------------------------------------------------------------------
1 | def test_basic_repeater(get_contract_with_gas_estimation):
2 | basic_repeater = """
3 | @public
4 | def repeat(z: int128) -> int128:
5 | x: int128 = 0
6 | for i in range(6):
7 | x = x + z
8 | return(x)
9 | """
10 | c = get_contract_with_gas_estimation(basic_repeater)
11 | assert c.repeat(9) == 54
12 | print('Passed basic repeater test')
13 |
14 |
15 | def test_digit_reverser(get_contract_with_gas_estimation):
16 | digit_reverser = """
17 | @public
18 | def reverse_digits(x: int128) -> int128:
19 | dig: int128[6]
20 | z: int128 = x
21 | for i in range(6):
22 | dig[i] = z % 10
23 | z = z / 10
24 | o: int128 = 0
25 | for i in range(6):
26 | o = o * 10 + dig[i]
27 | return o
28 |
29 | """
30 |
31 | c = get_contract_with_gas_estimation(digit_reverser)
32 | assert c.reverse_digits(123456) == 654321
33 | print('Passed digit reverser test')
34 |
35 |
36 | def test_more_complex_repeater(get_contract_with_gas_estimation):
37 | more_complex_repeater = """
38 | @public
39 | def repeat() -> int128:
40 | out: int128 = 0
41 | for i in range(6):
42 | out = out * 10
43 | for j in range(4):
44 | out = out + j
45 | return(out)
46 | """
47 |
48 | c = get_contract_with_gas_estimation(more_complex_repeater)
49 | assert c.repeat() == 666666
50 |
51 | print('Passed complex repeater test')
52 |
53 |
54 | def test_offset_repeater(get_contract_with_gas_estimation):
55 | offset_repeater = """
56 | @public
57 | def sum() -> int128:
58 | out: int128 = 0
59 | for i in range(80, 121):
60 | out = out + i
61 | return(out)
62 | """
63 |
64 | c = get_contract_with_gas_estimation(offset_repeater)
65 | assert c.sum() == 4100
66 |
67 | print('Passed repeater with offset test')
68 |
69 |
70 | def test_offset_repeater_2(get_contract_with_gas_estimation):
71 | offset_repeater_2 = """
72 | @public
73 | def sum(frm: int128, to: int128) -> int128:
74 | out: int128 = 0
75 | for i in range(frm, frm + 101):
76 | if i == to:
77 | break
78 | out = out + i
79 | return(out)
80 | """
81 |
82 | c = get_contract_with_gas_estimation(offset_repeater_2)
83 | assert c.sum(100, 99999) == 15150
84 | assert c.sum(70, 131) == 6100
85 |
86 | print('Passed more complex repeater with offset test')
87 |
--------------------------------------------------------------------------------
/tests/parser/features/test_assert.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from vyper.exceptions import (
4 | StructureException
5 | )
6 | from eth_tester.exceptions import (
7 | TransactionFailed
8 | )
9 |
10 |
11 | def test_assert_refund(w3, get_contract_with_gas_estimation, assert_tx_failed):
12 | code = """
13 | @public
14 | def foo():
15 | assert 1 == 2
16 | """
17 | c = get_contract_with_gas_estimation(code)
18 | a0 = w3.eth.accounts[0]
19 | pre_balance = w3.eth.getBalance(a0)
20 | tx_hash = c.foo(transact={'from': a0, 'gas': 10**6, 'gasPrice': 10})
21 | assert w3.eth.getTransactionReceipt(tx_hash)['status'] == 0
22 | # More info on receipt status:
23 | # https://github.com/ethereum/EIPs/blob/master/EIPS/eip-658.md#specification.
24 | post_balance = w3.eth.getBalance(a0)
25 | # Checks for gas refund from revert
26 | # 10**5 is added to account for gas used before the transactions fails
27 | assert pre_balance > post_balance
28 |
29 |
30 | def test_assert_reason(w3, get_contract_with_gas_estimation, assert_tx_failed):
31 | code = """
32 | @public
33 | def test(a: int128) -> int128:
34 | assert a > 1, "larger than one please"
35 | return 1 + a
36 |
37 | @public
38 | def test2(a: int128, b: int128) -> int128:
39 | c: int128 = 11
40 | assert a > 1, "a is not large enough"
41 | assert b == 1, "b may only be 1"
42 | return a + b + c
43 | """
44 | c = get_contract_with_gas_estimation(code)
45 |
46 | assert c.test(2) == 3
47 | with pytest.raises(TransactionFailed) as e_info:
48 | c.test(0)
49 |
50 | assert e_info.value.args[0] == b'larger than one please'
51 | # a = 0, b = 1
52 | with pytest.raises(TransactionFailed) as e_info:
53 | c.test2(0, 1)
54 | assert e_info.value.args[0] == b'a is not large enough'
55 | # a = 1, b = 0
56 | with pytest.raises(TransactionFailed) as e_info:
57 | c.test2(2, 2)
58 | assert e_info.value.args[0] == b'b may only be 1'
59 | # return correct value
60 | assert c.test2(5, 1) == 17
61 |
62 |
63 | def test_assert_reason_empty(get_contract, assert_compile_failed):
64 | code = """
65 | @public
66 | def test(a: int128) -> int128:
67 | assert a > 1, ""
68 | return 1 + a
69 | """
70 | assert_compile_failed(lambda: get_contract(code), StructureException)
71 |
--------------------------------------------------------------------------------
/tests/parser/features/test_bytes_map_keys.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from vyper.exceptions import TypeMismatchException
3 |
4 |
5 | def test_basic_bytes_keys(w3, get_contract):
6 | code = """
7 | mapped_bytes: int128[bytes[5]]
8 |
9 | @public
10 | def set(k: bytes[5], v: int128):
11 | self.mapped_bytes[k] = v
12 |
13 | @public
14 | def get(k: bytes[5]) -> int128:
15 | return self.mapped_bytes[k]
16 | """
17 |
18 | c = get_contract(code)
19 |
20 | c.set(b"test", 54321, transact={})
21 |
22 | assert c.get(b"test") == 54321
23 |
24 |
25 | def test_basic_bytes_literal_key(get_contract):
26 | code = """
27 | mapped_bytes: int128[bytes[5]]
28 |
29 | @public
30 | def set(v: int128):
31 | self.mapped_bytes["test"] = v
32 |
33 | @public
34 | def get(k: bytes[5]) -> int128:
35 | return self.mapped_bytes[k]
36 | """
37 |
38 | c = get_contract(code)
39 |
40 | c.set(54321, transact={})
41 |
42 | assert c.get(b"test") == 54321
43 |
44 |
45 | def test_basic_long_bytes_as_keys(get_contract):
46 | code = """
47 | mapped_bytes: int128[bytes[34]]
48 |
49 | @public
50 | def set(k: bytes[34], v: int128):
51 | self.mapped_bytes[k] = v
52 |
53 | @public
54 | def get(k: bytes[34]) -> int128:
55 | return self.mapped_bytes[k]
56 | """
57 |
58 | c = get_contract(code)
59 |
60 | c.set(b"a" * 34, 6789, transact={'gas': 10**6})
61 |
62 | assert c.get(b"a" * 34) == 6789
63 |
64 |
65 | def test_mismatched_byte_length(get_contract):
66 | code = """
67 | mapped_bytes: int128[bytes[34]]
68 |
69 | @public
70 | def set(k: bytes[35], v: int128):
71 | self.mapped_bytes[k] = v
72 | """
73 |
74 | with pytest.raises(TypeMismatchException):
75 | get_contract(code)
76 |
77 |
78 | def test_extended_bytes_key_from_storage(get_contract):
79 | code = """
80 | a: int128[bytes[100000]]
81 |
82 | @public
83 | def __init__():
84 | self.a["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] = 1069
85 |
86 | @public
87 | def get_it1() -> int128:
88 | key: bytes[100000] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
89 | return self.a[key]
90 |
91 | @public
92 | def get_it2() -> int128:
93 | return self.a["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
94 |
95 | @public
96 | def get_it3(key: bytes[100000]) -> int128:
97 | return self.a[key]
98 | """
99 |
100 | c = get_contract(code)
101 |
102 | assert c.get_it2() == 1069
103 | assert c.get_it2() == 1069
104 | assert c.get_it3(b"a" * 33) == 1069
105 | assert c.get_it3(b"test") == 0
106 |
--------------------------------------------------------------------------------
/tests/parser/features/test_clampers.py:
--------------------------------------------------------------------------------
1 | def test_clamper_test_code(assert_tx_failed, get_contract_with_gas_estimation):
2 | clamper_test_code = """
3 | @public
4 | def foo(s: bytes[3]) -> bytes[3]:
5 | return s
6 | """
7 |
8 | c = get_contract_with_gas_estimation(clamper_test_code)
9 | assert c.foo(b"ca") == b"ca"
10 | assert c.foo(b"cat") == b"cat"
11 | assert_tx_failed(lambda: c.foo(b"cate"))
12 |
13 | print("Passed bytearray clamping test")
14 |
--------------------------------------------------------------------------------
/tests/parser/features/test_comments.py:
--------------------------------------------------------------------------------
1 | def test_comment_test(get_contract_with_gas_estimation):
2 | comment_test = """
3 | @public
4 | def foo() -> int128:
5 | # Returns 3
6 | return 3
7 | """
8 |
9 | c = get_contract_with_gas_estimation(comment_test)
10 | assert c.foo() == 3
11 | print('Passed comment test')
12 |
--------------------------------------------------------------------------------
/tests/parser/features/test_conditionals.py:
--------------------------------------------------------------------------------
1 | def test_conditional_return_code(get_contract_with_gas_estimation):
2 | conditional_return_code = """
3 | @public
4 | def foo(i: bool) -> int128:
5 | if i:
6 | return 5
7 | else:
8 | assert 2 != 0
9 | return 7
10 | return 11
11 | """
12 |
13 | c = get_contract_with_gas_estimation(conditional_return_code)
14 | assert c.foo(True) == 5
15 | assert c.foo(False) == 7
16 |
17 | print('Passed conditional return tests')
18 |
--------------------------------------------------------------------------------
/tests/parser/features/test_constructor.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from web3.exceptions import (
3 | ValidationError
4 | )
5 |
6 |
7 | def test_init_argument_test(get_contract_with_gas_estimation):
8 | init_argument_test = """
9 | moose: int128
10 |
11 | @public
12 | def __init__(_moose: int128):
13 | self.moose = _moose
14 |
15 | @public
16 | def returnMoose() -> int128:
17 | return self.moose
18 | """
19 |
20 | c = get_contract_with_gas_estimation(init_argument_test, *[5])
21 | assert c.returnMoose() == 5
22 | print('Passed init argument test')
23 |
24 |
25 | def test_constructor_advanced_code(get_contract_with_gas_estimation):
26 | constructor_advanced_code = """
27 | twox: int128
28 |
29 | @public
30 | def __init__(x: int128):
31 | self.twox = x * 2
32 |
33 | @public
34 | def get_twox() -> int128:
35 | return self.twox
36 | """
37 | c = get_contract_with_gas_estimation(constructor_advanced_code, *[5])
38 | assert c.get_twox() == 10
39 |
40 |
41 | def test_constructor_advanced_code2(get_contract_with_gas_estimation):
42 | constructor_advanced_code2 = """
43 | comb: int128
44 |
45 | @public
46 | def __init__(x: int128[2], y: bytes[3], z: int128):
47 | self.comb = x[0] * 1000 + x[1] * 100 + len(y) * 10 + z
48 |
49 | @public
50 | def get_comb() -> int128:
51 | return self.comb
52 | """
53 | c = get_contract_with_gas_estimation(constructor_advanced_code2, *[[5, 7], b"dog", 8])
54 | assert c.get_comb() == 5738
55 | print("Passed advanced init argument tests")
56 |
57 |
58 | def test_large_input_code(get_contract_with_gas_estimation):
59 | large_input_code = """
60 | @public
61 | def foo(x: int128) -> int128:
62 | return 3
63 | """
64 |
65 | c = get_contract_with_gas_estimation(large_input_code)
66 | c.foo(1274124)
67 | c.foo(2**120)
68 |
69 | with pytest.raises(ValidationError):
70 | c.foo(2**130)
71 |
72 |
73 | def test_large_input_code_2(w3, get_contract_with_gas_estimation):
74 | large_input_code_2 = """
75 | @public
76 | def __init__(x: int128):
77 | y: int128 = x
78 |
79 | @public
80 | def foo() -> int128:
81 | return 5
82 | """
83 |
84 | get_contract_with_gas_estimation(large_input_code_2, *[17])
85 |
86 | with pytest.raises(TypeError):
87 | get_contract_with_gas_estimation(large_input_code_2, *[2**130])
88 |
89 | print('Passed invalid input tests')
90 |
--------------------------------------------------------------------------------
/tests/parser/features/test_gas.py:
--------------------------------------------------------------------------------
1 | from vyper.parser.parser import parse_to_lll
2 | from vyper.parser import parser_utils
3 |
4 |
5 | def test_gas_call(get_contract_with_gas_estimation):
6 | gas_call = """
7 | @public
8 | def foo() -> uint256:
9 | return msg.gas
10 | """
11 |
12 | c = get_contract_with_gas_estimation(gas_call)
13 |
14 | assert c.foo(call={"gas": 50000}) < 50000
15 | assert c.foo(call={"gas": 50000}) > 25000
16 |
17 | print('Passed gas test')
18 |
19 |
20 | def test_gas_estimate_repr():
21 | code = """
22 | x: int128
23 |
24 | @public
25 | def __init__():
26 | self.x = 1
27 | """
28 | parser_utils.LLLnode.repr_show_gas = True
29 | out = parse_to_lll(code)
30 | assert '35303' in str(out)[:28]
31 | parser_utils.LLLnode.repr_show_gas = False
32 |
--------------------------------------------------------------------------------
/tests/parser/features/test_map_delete.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | def test_map_delete(get_contract_with_gas_estimation):
4 | code = """
5 | big_storage: bytes32[bytes32]
6 |
7 | @public
8 | def set(key: bytes32, value: bytes32):
9 | self.big_storage[key] = value
10 |
11 | @public
12 | def get(key: bytes32) -> bytes32:
13 | return self.big_storage[key]
14 |
15 | @public
16 | def delete(key: bytes32):
17 | del self.big_storage[key]
18 | """
19 |
20 | c = get_contract_with_gas_estimation(code)
21 |
22 | assert c.get(b"test") == b'\x00' * 32
23 | c.set(b"test", b"value", transact={})
24 | assert c.get(b"test")[:5] == b"value"
25 | c.delete(b"test", transact={})
26 | assert c.get(b"test") == b'\x00' * 32
27 |
28 |
29 | def test_map_delete_nested(get_contract_with_gas_estimation):
30 | code = """
31 | big_storage: bytes32[bytes32][bytes32]
32 |
33 | @public
34 | def set(key1: bytes32, key2: bytes32, value: bytes32):
35 | self.big_storage[key1][key2] = value
36 |
37 | @public
38 | def get(key1: bytes32, key2: bytes32) -> bytes32:
39 | return self.big_storage[key1][key2]
40 |
41 | @public
42 | def delete(key1: bytes32, key2: bytes32):
43 | del self.big_storage[key1][key2]
44 | """
45 |
46 | c = get_contract_with_gas_estimation(code)
47 |
48 | assert c.get(b"test1", b"test2") == b'\x00' * 32
49 | c.set(b"test1", b"test2", b"value", transact={})
50 | assert c.get(b"test1", b"test2")[:5] == b"value"
51 | c.delete(b"test1", b"test2", transact={})
52 | assert c.get(b"test1", b"test2") == b'\x00' * 32
53 |
54 |
55 | def test_map_delete_struct(get_contract_with_gas_estimation):
56 | code = """
57 | structmap: {
58 | a: int128,
59 | b: int128
60 | }[int128]
61 |
62 |
63 | @public
64 | def set():
65 | self.structmap[123] = {
66 | a: 333,
67 | b: 444
68 | }
69 |
70 | @public
71 | def get() -> (int128, int128):
72 | return self.structmap[123].a, self.structmap[123].b
73 |
74 | @public
75 | def delete():
76 | self.structmap[123] = None
77 | """
78 |
79 | c = get_contract_with_gas_estimation(code)
80 |
81 | assert c.get() == [0, 0]
82 | c.set(transact={})
83 | assert c.get() == [333, 444]
84 | c.delete(transact={})
85 | assert c.get() == [0, 0]
86 |
--------------------------------------------------------------------------------
/tests/parser/features/test_packing.py:
--------------------------------------------------------------------------------
1 | def test_packing_test(get_contract_with_gas_estimation):
2 | packing_test = """
3 | x: int128
4 | y: int128[5]
5 | z: {foo: int128[3], bar: {a: int128, b: int128}[2]}
6 | a: int128
7 |
8 | @public
9 | def foo() -> int128:
10 | self.x = 1
11 | self.y[0] = 2
12 | self.y[4] = 4
13 | self.z.foo[0] = 8
14 | self.z.foo[2] = 16
15 | self.z.bar[0].a = 32
16 | self.z.bar[0].b = 64
17 | self.z.bar[1].a = 128
18 | self.z.bar[1].b = 256
19 | self.a = 512
20 | return self.x + self.y[0] + self.y[4] + self.z.foo[0] + self.z.foo[2] + \
21 | self.z.bar[0].a + self.z.bar[0].b + self.z.bar[1].a + self.z.bar[1].b + self.a
22 |
23 | @public
24 | def fop() -> int128:
25 | _x: int128
26 | _y: int128[5]
27 | _z: {foo: int128[3], bar: {a: int128, b: int128}[2]}
28 | _a: int128
29 | _x = 1
30 | _y[0] = 2
31 | _y[4] = 4
32 | _z.foo[0] = 8
33 | _z.foo[2] = 16
34 | _z.bar[0].a = 32
35 | _z.bar[0].b = 64
36 | _z.bar[1].a = 128
37 | _z.bar[1].b = 256
38 | _a = 512
39 | return _x + _y[0] + _y[4] + _z.foo[0] + _z.foo[2] + \
40 | _z.bar[0].a + _z.bar[0].b + _z.bar[1].a + _z.bar[1].b + _a
41 | """
42 |
43 | c = get_contract_with_gas_estimation(packing_test)
44 | assert c.foo() == 1023, c.foo()
45 | assert c.fop() == 1023, c.fop()
46 | print('Passed packing test')
47 |
--------------------------------------------------------------------------------
/tests/parser/functions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/tests/parser/functions/__init__.py
--------------------------------------------------------------------------------
/tests/parser/functions/rlp/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/tests/parser/functions/rlp/__init__.py
--------------------------------------------------------------------------------
/tests/parser/functions/rlp/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import eth_tester
3 |
4 | from vyper import utils as vyper_utils
5 |
6 |
7 | @pytest.fixture(autouse=True)
8 | def patch_large_gas_limit(monkeypatch):
9 | monkeypatch.setattr(eth_tester.backends.pyevm.main, 'GENESIS_GAS_LIMIT', 10**9)
10 |
11 |
12 | @pytest.fixture
13 | def fake_tx(tester, w3):
14 | def fake_tx():
15 | tx_hex = "0xf9035b808506fc23ac0083045f788080b903486103305660006109ac5260006109cc527f0100000000000000000000000000000000000000000000000000000000000000600035046109ec526000610a0c5260006109005260c06109ec51101515585760f86109ec51101561006e5760bf6109ec510336141558576001610a0c52610098565b60013560f76109ec51036020035260005160f66109ec510301361415585760f66109ec5103610a0c525b61022060016064818352015b36610a0c511015156100b557610291565b7f0100000000000000000000000000000000000000000000000000000000000000610a0c5135046109ec526109cc5160206109ac51026040015260016109ac51016109ac5260806109ec51101561013b5760016109cc5161044001526001610a0c516109cc5161046001376001610a0c5101610a0c5260216109cc51016109cc52610281565b60b86109ec5110156101d15760806109ec51036109cc51610440015260806109ec51036001610a0c51016109cc51610460013760816109ec5114156101ac5760807f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350410151558575b607f6109ec5103610a0c5101610a0c5260606109ec51036109cc51016109cc52610280565b60c06109ec51101561027d576001610a0c51013560b76109ec510360200352600051610a2c526038610a2c5110157f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350402155857610a2c516109cc516104400152610a2c5160b66109ec5103610a0c51016109cc516104600137610a2c5160b66109ec5103610a0c510101610a0c526020610a2c51016109cc51016109cc5261027f565bfe5b5b5b81516001018083528114156100a4575b5050601f6109ac511115155857602060206109ac5102016109005260206109005103610a0c5261022060016064818352015b6000610a0c5112156102d45761030a565b61090051610a0c516040015101610a0c51610900516104400301526020610a0c5103610a0c5281516001018083528114156102c3575b50506109cc516109005101610420526109cc5161090051016109005161044003f35b61000461033003610004600039610004610330036000f31b2d4f"
16 | w3.eth.sendTransaction({'to': '0x39ba083c30fCe59883775Fc729bBE1f9dE4DEe11', 'value': 10**17})
17 | tx_hash = w3.eth.sendRawTransaction(tx_hex)
18 | receipt = w3.eth.getTransactionReceipt(tx_hash)
19 | contract_address = receipt.contractAddress
20 | assert vyper_utils.RLP_DECODER_ADDRESS == w3.toInt(hexstr=contract_address)
21 | return contract_address
22 | return fake_tx
23 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_bitwise.py:
--------------------------------------------------------------------------------
1 | def test_test_bitwise(get_contract_with_gas_estimation):
2 | test_bitwise = """
3 | @public
4 | def _bitwise_and(x: uint256, y: uint256) -> uint256:
5 | return bitwise_and(x, y)
6 |
7 | @public
8 | def _bitwise_or(x: uint256, y: uint256) -> uint256:
9 | return bitwise_or(x, y)
10 |
11 | @public
12 | def _bitwise_xor(x: uint256, y: uint256) -> uint256:
13 | return bitwise_xor(x, y)
14 |
15 | @public
16 | def _bitwise_not(x: uint256) -> uint256:
17 | return bitwise_not(x)
18 |
19 | @public
20 | def _shift(x: uint256, y: int128) -> uint256:
21 | return shift(x, y)
22 | """
23 |
24 | c = get_contract_with_gas_estimation(test_bitwise)
25 | x = 126416208461208640982146408124
26 | y = 7128468721412412459
27 | assert c._bitwise_and(x, y) == (x & y)
28 | assert c._bitwise_or(x, y) == (x | y)
29 | assert c._bitwise_xor(x, y) == (x ^ y)
30 | assert c._bitwise_not(x) == 2**256 - 1 - x
31 | assert c._shift(x, 3) == x * 8
32 | assert c._shift(x, 255) == 0
33 | assert c._shift(y, 255) == 2**255
34 | assert c._shift(x, 256) == 0
35 | assert c._shift(x, 0) == x
36 | assert c._shift(x, -1) == x // 2
37 | assert c._shift(x, -3) == x // 8
38 | assert c._shift(x, -256) == 0
39 |
40 | print("Passed bitwise operation tests")
41 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_block.py:
--------------------------------------------------------------------------------
1 | def test_block_number(get_contract_with_gas_estimation, w3):
2 | w3.testing.mine(1)
3 |
4 | block_number_code = """
5 | @public
6 | def block_number() -> uint256:
7 | return block.number
8 | """
9 | c = get_contract_with_gas_estimation(block_number_code)
10 | assert c.block_number() == 2
11 |
12 |
13 | def test_blockhash(get_contract_with_gas_estimation, w3):
14 | w3.testing.mine(1)
15 |
16 | block_number_code = """
17 | @public
18 | def prev() -> bytes32:
19 | return block.prevhash
20 |
21 | @public
22 | def previous_blockhash() -> bytes32:
23 | return blockhash(block.number - 1)
24 | """
25 | c = get_contract_with_gas_estimation(block_number_code)
26 | assert c.prev() == c.previous_blockhash()
27 |
28 |
29 | def test_negative_blockhash(assert_compile_failed, get_contract_with_gas_estimation):
30 | code = """
31 | @public
32 | def foo() -> bytes32:
33 | return blockhash(-1)
34 | """
35 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code))
36 |
37 |
38 | def test_too_old_blockhash(assert_tx_failed, get_contract_with_gas_estimation, w3):
39 | w3.testing.mine(257)
40 | code = """
41 | @public
42 | def get_50_blockhash() -> bytes32:
43 | return blockhash(block.number - 257)
44 | """
45 | c = get_contract_with_gas_estimation(code)
46 | assert_tx_failed(lambda: c.get_50_blockhash())
47 |
48 |
49 | def test_non_existing_blockhash(assert_tx_failed, get_contract_with_gas_estimation):
50 | code = """
51 | @public
52 | def get_future_blockhash() -> bytes32:
53 | return blockhash(block.number + 1)
54 | """
55 | c = get_contract_with_gas_estimation(code)
56 | assert_tx_failed(lambda: c.get_future_blockhash())
57 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_block_number.py:
--------------------------------------------------------------------------------
1 |
2 | def test_block_number(get_contract_with_gas_estimation, w3):
3 | block_number_code = """
4 | @public
5 | def block_number() -> uint256:
6 | return block.number
7 | """
8 | c = get_contract_with_gas_estimation(block_number_code)
9 |
10 | assert c.block_number() == 1
11 | w3.testing.mine(1)
12 | assert c.block_number() == 2
13 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_ceil.py:
--------------------------------------------------------------------------------
1 | from decimal import Decimal
2 |
3 |
4 | def test_ceil(get_contract_with_gas_estimation):
5 | code = """
6 | x: decimal
7 |
8 | @public
9 | def __init__():
10 | self.x = 504.0000000001
11 |
12 | @public
13 | def x_ceil() -> int128:
14 | return ceil(self.x)
15 |
16 | @public
17 | def foo() -> int128:
18 | return ceil(.9999999999)
19 |
20 | @public
21 | def fop() -> int128:
22 | return ceil(.0000000001)
23 |
24 | @public
25 | def foq() -> int128:
26 | return ceil(170141183460469231731687303715884105726.0000000002)
27 |
28 | @public
29 | def fos() -> int128:
30 | return ceil(0.0)
31 |
32 | @public
33 | def fou() -> int128:
34 | a: int128 = 305
35 | b: int128 = 100
36 | c: decimal = convert(a, decimal) / convert(b, decimal)
37 | return ceil(c)
38 | """
39 |
40 | c = get_contract_with_gas_estimation(code)
41 |
42 | assert c.x_ceil() == 505
43 | assert c.foo() == 1
44 | assert c.fop() == 1
45 | assert c.foq() == 170141183460469231731687303715884105727
46 | assert c.fos() == 0
47 | assert c.fou() == 4
48 |
49 |
50 | # ceil(x) should yeild the smallest integer greater than or equal to x
51 | def test_ceil_negative(get_contract_with_gas_estimation):
52 | code = """
53 | x: decimal
54 |
55 | @public
56 | def __init__():
57 | self.x = -504.0000000001
58 |
59 | @public
60 | def x_ceil() -> int128:
61 | return ceil(self.x)
62 |
63 | @public
64 | def foo() -> int128:
65 | return ceil(-11.01)
66 |
67 | @public
68 | def fop() -> int128:
69 | return ceil(-5.0)
70 |
71 | @public
72 | def foq() -> int128:
73 | return ceil(-.0000000001)
74 |
75 | @public
76 | def fos() -> int128:
77 | return ceil(-5472.9999999999)
78 |
79 | @public
80 | def fot() -> int128:
81 | return ceil(-170141183460469231731687303715884105727.0000000002)
82 |
83 | @public
84 | def fou() -> int128:
85 | a: decimal = -305.0
86 | b: decimal = 100.0
87 | c: decimal = a / b
88 | return ceil(c)
89 |
90 | @public
91 | def ceil_param(p: decimal) -> int128:
92 | return ceil(p)
93 | """
94 |
95 | c = get_contract_with_gas_estimation(code)
96 |
97 | assert c.x_ceil() == -504
98 | assert c.foo() == -11
99 | assert c.fop() == -5
100 | assert c.foq() == 0
101 | assert c.fos() == -5472
102 | assert c.fot() == -170141183460469231731687303715884105727
103 | assert c.fou() == -3
104 | assert c.ceil_param(Decimal('-0.5')) == 0
105 | assert c.ceil_param(Decimal('-7777777.7777777')) == -7777777
106 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_convert_int128.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | def test_convert_bytes32_to_num_overflow(assert_tx_failed, get_contract_with_gas_estimation):
4 | code = """
5 | @public
6 | def test1():
7 | y: bytes32 = 0x1000000000000000000000000000000000000000000000000000000000000000
8 | x: int128 = convert(y, int128)
9 | """
10 |
11 | c = get_contract_with_gas_estimation(code)
12 | assert_tx_failed(lambda: c.test1())
13 |
14 |
15 | def test_convert_address_to_num(assert_compile_failed, get_contract_with_gas_estimation):
16 | code = """
17 | @public
18 | def test2():
19 | x: int128 = convert(msg.sender, int128)
20 | """
21 |
22 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code), Exception)
23 |
24 |
25 | def test_convert_out_of_range(assert_compile_failed, get_contract_with_gas_estimation):
26 | code = """
27 | @public
28 | def test2():
29 | x: int128
30 | x = convert(340282366920938463463374607431768211459, int128)
31 | """
32 |
33 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code), Exception)
34 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_convert_uint256.py:
--------------------------------------------------------------------------------
1 |
2 | def test_convert_to_uint256_with_negative_num(assert_compile_failed, get_contract_with_gas_estimation):
3 | code = """
4 | @public
5 | def foo() -> uint256:
6 | return convert(1-2, uint256)
7 | """
8 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code), Exception)
9 |
10 |
11 | def test_convert_to_uint256_with_negative_input(assert_tx_failed, get_contract_with_gas_estimation):
12 | code = """
13 | @public
14 | def foo(x: int128) -> uint256:
15 | return convert(x, uint256)
16 | """
17 | c = get_contract_with_gas_estimation(code)
18 | assert_tx_failed(lambda: c.foo(-1))
19 |
20 |
21 | def test_convert_to_uint256_with_bytes32(get_contract_with_gas_estimation):
22 | code = """
23 | @public
24 | def foo() -> uint256:
25 | return convert(convert(-1, bytes32), uint256)
26 | """
27 |
28 | c = get_contract_with_gas_estimation(code)
29 | assert c.foo() == 2 ** 256 - 1
30 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_default_function.py:
--------------------------------------------------------------------------------
1 |
2 | def test_throw_on_sending(w3, assert_tx_failed, get_contract_with_gas_estimation):
3 | code = """
4 | x: public(int128)
5 |
6 | @public
7 | def __init__():
8 | self.x = 123
9 | """
10 | c = get_contract_with_gas_estimation(code)
11 |
12 | assert c.x() == 123
13 | assert w3.eth.getBalance(c.address) == 0
14 | assert_tx_failed(lambda: w3.eth.sendTransaction({'to': c.address, 'value': w3.toWei(0.1, 'ether')}))
15 | assert w3.eth.getBalance(c.address) == 0
16 |
17 |
18 | def test_basic_default(w3, get_logs, get_contract_with_gas_estimation):
19 | code = """
20 | Sent: event({sender: indexed(address)})
21 |
22 | @public
23 | @payable
24 | def __default__():
25 | log.Sent(msg.sender)
26 | """
27 | c = get_contract_with_gas_estimation(code)
28 |
29 | logs = get_logs(w3.eth.sendTransaction({'to': c.address, 'value': 10**17}), c, 'Sent')
30 | assert w3.eth.accounts[0] == logs[0].args.sender
31 | assert w3.eth.getBalance(c.address) == w3.toWei(0.1, 'ether')
32 |
33 |
34 | def test_basic_default_default_param_function(w3, get_logs, get_contract_with_gas_estimation):
35 | code = """
36 | Sent: event({sender: indexed(address)})
37 | @public
38 | @payable
39 | def fooBar(a: int128 = 12345) -> int128:
40 | log.Sent(ZERO_ADDRESS)
41 | return a
42 |
43 | @public
44 | @payable
45 | def __default__():
46 | log.Sent(msg.sender)
47 | """
48 | c = get_contract_with_gas_estimation(code)
49 |
50 | logs = get_logs(w3.eth.sendTransaction({'to': c.address, 'value': 10**17}), c, 'Sent')
51 | assert w3.eth.accounts[0] == logs[0].args.sender
52 | assert w3.eth.getBalance(c.address) == w3.toWei(0.1, 'ether')
53 |
54 |
55 | def test_basic_default_not_payable(w3, assert_tx_failed, get_contract_with_gas_estimation):
56 | code = """
57 | Sent: event({sender: indexed(address)})
58 |
59 | @public
60 | def __default__():
61 | log.Sent(msg.sender)
62 | """
63 | c = get_contract_with_gas_estimation(code)
64 |
65 | assert_tx_failed(lambda: w3.eth.sendTransaction({'to': c.address, 'value': 10**17}))
66 |
67 |
68 | def test_multi_arg_default(assert_compile_failed, get_contract_with_gas_estimation):
69 | code = """
70 | @payable
71 | @public
72 | def __default__(arg1: int128):
73 | pass
74 | """
75 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code))
76 |
77 |
78 | def test_always_public(assert_compile_failed, get_contract_with_gas_estimation):
79 | code = """
80 | @private
81 | def __default__():
82 | pass
83 | """
84 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code))
85 |
86 |
87 | def test_always_public_2(assert_compile_failed, get_contract_with_gas_estimation):
88 | code = """
89 | Sent: event({sender: indexed(address)})
90 |
91 | def __default__():
92 | log.Sent(msg.sender)
93 | """
94 | assert_compile_failed(lambda: get_contract_with_gas_estimation(code))
95 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_ec.py:
--------------------------------------------------------------------------------
1 | G1 = [1, 2]
2 |
3 | G1_times_two = [
4 | 1368015179489954701390400359078579693043519447331113978918064868415326638035,
5 | 9918110051302171585080402603319702774565515993150576347155970296011118125764
6 | ]
7 |
8 | G1_times_three = [
9 | 3353031288059533942658390886683067124040920775575537747144343083137631628272,
10 | 19321533766552368860946552437480515441416830039777911637913418824951667761761
11 | ]
12 |
13 | negative_G1 = [
14 | 1,
15 | 21888242871839275222246405745257275088696311157297823662689037894645226208581
16 | ]
17 |
18 | curve_order = 21888242871839275222246405745257275088548364400416034343698204186575808495617
19 |
20 |
21 | def test_ecadd(get_contract_with_gas_estimation):
22 | ecadder = """
23 | x3: uint256[2]
24 | y3: uint256[2]
25 |
26 | @public
27 | def _ecadd(x: uint256[2], y: uint256[2]) -> uint256[2]:
28 | return ecadd(x, y)
29 |
30 | @public
31 | def _ecadd2(x: uint256[2], y: uint256[2]) -> uint256[2]:
32 | x2: uint256[2] = x
33 | y2: uint256[2] = [y[0], y[1]]
34 | return ecadd(x2, y2)
35 |
36 | @public
37 | def _ecadd3(x: uint256[2], y: uint256[2]) -> uint256[2]:
38 | self.x3 = x
39 | self.y3 = [y[0], y[1]]
40 | return ecadd(self.x3, self.y3)
41 |
42 | """
43 | c = get_contract_with_gas_estimation(ecadder)
44 |
45 | assert c._ecadd(G1, G1) == G1_times_two
46 | assert c._ecadd2(G1, G1_times_two) == G1_times_three
47 | assert c._ecadd3(G1, [0, 0]) == G1
48 | assert c._ecadd3(G1, negative_G1) == [0, 0]
49 |
50 |
51 | def test_ecmul(get_contract_with_gas_estimation):
52 | ecmuller = """
53 | x3: uint256[2]
54 | y3: uint256
55 |
56 | @public
57 | def _ecmul(x: uint256[2], y: uint256) -> uint256[2]:
58 | return ecmul(x, y)
59 |
60 | @public
61 | def _ecmul2(x: uint256[2], y: uint256) -> uint256[2]:
62 | x2: uint256[2] = x
63 | y2: uint256 = y
64 | return ecmul(x2, y2)
65 |
66 | @public
67 | def _ecmul3(x: uint256[2], y: uint256) -> uint256[2]:
68 | self.x3 = x
69 | self.y3 = y
70 | return ecmul(self.x3, self.y3)
71 |
72 | """
73 | c = get_contract_with_gas_estimation(ecmuller)
74 |
75 | assert c._ecmul(G1, 0) == [0, 0]
76 | assert c._ecmul(G1, 1) == G1
77 | assert c._ecmul(G1, 3) == G1_times_three
78 | assert c._ecmul(G1, curve_order - 1) == negative_G1
79 | assert c._ecmul(G1, curve_order) == [0, 0]
80 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_ecrecover.py:
--------------------------------------------------------------------------------
1 | from eth_account import Account
2 |
3 |
4 | def test_ecrecover_test(get_contract_with_gas_estimation):
5 | ecrecover_test = """
6 | @public
7 | def test_ecrecover(h: bytes32, v:uint256, r:uint256, s:uint256) -> address:
8 | return ecrecover(h, v, r, s)
9 |
10 | @public
11 | def test_ecrecover2() -> address:
12 | return ecrecover(0x3535353535353535353535353535353535353535353535353535353535353535,
13 | convert(28, uint256),
14 | convert(63198938615202175987747926399054383453528475999185923188997970550032613358815, uint256),
15 | convert(6577251522710269046055727877571505144084475024240851440410274049870970796685, uint256))
16 | """
17 |
18 | c = get_contract_with_gas_estimation(ecrecover_test)
19 |
20 | h = b'\x35' * 32
21 | local_account = Account.privateKeyToAccount(b'\x46' * 32)
22 | sig = local_account.signHash(h)
23 |
24 | assert c.test_ecrecover(h, sig.v, sig.r, sig.s) == local_account.address
25 | assert c.test_ecrecover2() == local_account.address
26 |
27 | print("Passed ecrecover test")
28 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_extract32.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | def test_extract32_extraction(assert_tx_failed, get_contract_with_gas_estimation):
4 | extract32_code = """
5 | y: bytes[100]
6 | @public
7 | def extrakt32(inp: bytes[100], index: int128) -> bytes32:
8 | return extract32(inp, index)
9 |
10 | @public
11 | def extrakt32_mem(inp: bytes[100], index: int128) -> bytes32:
12 | x: bytes[100] = inp
13 | return extract32(x, index)
14 |
15 | @public
16 | def extrakt32_storage(index: int128, inp: bytes[100]) -> bytes32:
17 | self.y = inp
18 | return extract32(self.y, index)
19 | """
20 |
21 | c = get_contract_with_gas_estimation(extract32_code)
22 | test_cases = (
23 | (b"c" * 31, 0),
24 | (b"c" * 32, 0),
25 | (b"c" * 32, -1),
26 | (b"c" * 33, 0),
27 | (b"c" * 33, 1),
28 | (b"c" * 33, 2),
29 | (b"cow" * 30, 0),
30 | (b"cow" * 30, 1),
31 | (b"cow" * 30, 31),
32 | (b"cow" * 30, 32),
33 | (b"cow" * 30, 33),
34 | (b"cow" * 30, 34),
35 | (b"cow" * 30, 58),
36 | (b"cow" * 30, 59),
37 | )
38 |
39 | for S, i in test_cases:
40 | expected_result = S[i: i + 32] if 0 <= i <= len(S) - 32 else None
41 | if expected_result is None:
42 | assert_tx_failed(lambda: c.extrakt32(S, i))
43 | else:
44 | assert c.extrakt32(S, i) == expected_result
45 | assert c.extrakt32_mem(S, i) == expected_result
46 | assert c.extrakt32_storage(i, S) == expected_result
47 |
48 | print("Passed bytes32 extraction test")
49 |
50 |
51 | def test_extract32_code(assert_tx_failed, get_contract_with_gas_estimation):
52 | extract32_code = """
53 | @public
54 | def foo(inp: bytes[32]) -> int128:
55 | return extract32(inp, 0, type=int128)
56 |
57 | @public
58 | def bar(inp: bytes[32]) -> uint256:
59 | return extract32(inp, 0, type=uint256)
60 |
61 | @public
62 | def baz(inp: bytes[32]) -> bytes32:
63 | return extract32(inp, 0, type=bytes32)
64 |
65 | @public
66 | def fop(inp: bytes[32]) -> bytes32:
67 | return extract32(inp, 0)
68 |
69 | @public
70 | def foq(inp: bytes[32]) -> address:
71 | return extract32(inp, 0, type=address)
72 | """
73 |
74 | c = get_contract_with_gas_estimation(extract32_code)
75 | assert c.foo(b"\x00" * 30 + b"\x01\x01") == 257
76 | assert c.bar(b"\x00" * 30 + b"\x01\x01") == 257
77 |
78 | assert_tx_failed(lambda: c.foo(b"\x80" + b"\x00" * 30))
79 |
80 | assert c.bar(b"\x80" + b"\x00" * 31) == 2**255
81 |
82 | assert c.baz(b"crow" * 8) == b"crow" * 8
83 | assert c.fop(b"crow" * 8) == b"crow" * 8
84 | assert c.foq(b"\x00" * 12 + b"3" * 20) == "0x" + "3" * 40
85 |
86 | assert_tx_failed(lambda: c.foq(b"crow" * 8))
87 |
88 | print('Passed extract32 test')
89 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_floor.py:
--------------------------------------------------------------------------------
1 | from decimal import Decimal
2 |
3 |
4 | def test_floor(get_contract_with_gas_estimation):
5 | code = """
6 | x: decimal
7 |
8 | @public
9 | def __init__():
10 | self.x = 504.0000000001
11 |
12 | @public
13 | def x_floor() -> int128:
14 | return floor(self.x)
15 |
16 | @public
17 | def foo() -> int128:
18 | return floor(1.9999999999)
19 |
20 | @public
21 | def fop() -> int128:
22 | return floor(1.0000000001)
23 |
24 | @public
25 | def foq() -> int128:
26 | return floor(170141183460469231731687303715884105726.0000000002)
27 |
28 | @public
29 | def fos() -> int128:
30 | return floor(0.0)
31 |
32 | @public
33 | def fot() -> int128:
34 | return floor(0.0000000001)
35 |
36 | @public
37 | def fou() -> int128:
38 | a: decimal = 305.0
39 | b: decimal = 100.0
40 | c: decimal = a / b
41 | return floor(c)
42 | """
43 | c = get_contract_with_gas_estimation(code)
44 | assert c.x_floor() == 504
45 | assert c.foo() == 1
46 | assert c.fop() == 1
47 | assert c.foq() == 170141183460469231731687303715884105726
48 | assert c.fos() == 0
49 | assert c.fot() == 0
50 | assert c.fou() == 3
51 |
52 |
53 | def test_floor_negative(get_contract_with_gas_estimation):
54 | code = """
55 | x: decimal
56 |
57 | @public
58 | def __init__():
59 | self.x = -504.0000000001
60 |
61 | @public
62 | def x_floor() -> int128:
63 | return floor(self.x)
64 |
65 | @public
66 | def foo() -> int128:
67 | a: int128 = -65
68 | b: decimal = convert(a, decimal) / 10.0
69 | return floor(b)
70 |
71 | @public
72 | def fop() -> int128:
73 | return floor(-27.0)
74 |
75 | @public
76 | def foq() -> int128:
77 | return floor(-9000.0000000001)
78 |
79 | @public
80 | def fos() -> int128:
81 | return floor(-0.0000000001)
82 |
83 | @public
84 | def fot() -> int128:
85 | return floor(-170141183460469231731687303715884105727.0000000002)
86 |
87 | @public
88 | def fou() -> int128:
89 | a: decimal = -305.0
90 | b: decimal = 100.0
91 | c: decimal = a / b
92 | return floor(c)
93 |
94 | @public
95 | def floor_param(p: decimal) -> int128:
96 | return floor(p)
97 | """
98 |
99 | c = get_contract_with_gas_estimation(code)
100 |
101 | assert c.x_floor() == -505
102 | assert c.foo() == -7
103 | assert c.fop() == -27
104 | assert c.foq() == -9001
105 | assert c.fos() == -1
106 | assert c.fot() == -170141183460469231731687303715884105728
107 | assert c.fou() == -4
108 | assert c.floor_param(Decimal('-5.6')) == -6
109 | assert c.floor_param(Decimal('-0.0000000001')) == -1
110 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_is_contract.py:
--------------------------------------------------------------------------------
1 | def test_is_contract(w3, get_contract_with_gas_estimation):
2 | contract_1 = """
3 | @public
4 | def foo(arg1: address) -> bool:
5 | result: bool = arg1.is_contract
6 | return result
7 | """
8 |
9 | contract_2 = """
10 | @public
11 | def foo(arg1: address) -> bool:
12 | return arg1.is_contract
13 | """
14 | a0, a1 = w3.eth.accounts[:2]
15 | c1 = get_contract_with_gas_estimation(contract_1)
16 | c2 = get_contract_with_gas_estimation(contract_2)
17 |
18 | assert c1.foo(c1.address) is True
19 | assert c1.foo(c2.address) is True
20 | assert c1.foo(a1) is False
21 | assert c1.foo(a0) is False
22 | assert c2.foo(c1.address) is True
23 | assert c2.foo(c2.address) is True
24 | assert c2.foo(a1) is False
25 | assert c2.foo(a0) is False
26 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_length.py:
--------------------------------------------------------------------------------
1 | def test_test_length(get_contract_with_gas_estimation):
2 | test_length = """
3 | y: bytes[10]
4 |
5 | @public
6 | def foo(inp: bytes[10]) -> int128:
7 | x: bytes[5] = slice(inp, start=1, len=5)
8 | self.y = slice(inp, start=2, len=4)
9 | return len(inp) * 100 + len(x) * 10 + len(self.y)
10 | """
11 |
12 | c = get_contract_with_gas_estimation(test_length)
13 | assert c.foo(b"badminton") == 954, c.foo(b"badminton")
14 | print('Passed length test')
15 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_method_id.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | def test_method_id_test(get_contract_with_gas_estimation):
4 | method_id_test = """
5 | @public
6 | def double(x: int128) -> int128:
7 | return x * 2
8 |
9 | @public
10 | def returnten() -> int128:
11 | ans: bytes[32] = raw_call(self, concat(method_id("double(int128)", bytes[4]), convert(5, bytes32)), gas=50000, outsize=32)
12 | return convert(convert(ans, bytes32), int128)
13 | """
14 | c = get_contract_with_gas_estimation(method_id_test)
15 | assert c.returnten() == 10
16 | print("Passed method ID test")
17 |
18 |
19 | def test_method_id_bytes32(get_contract):
20 | code = """
21 | @public
22 | def sig() -> bytes32:
23 | return method_id('transfer(address,uint256)', bytes32)
24 | """
25 | c = get_contract(code)
26 | sig = c.sig()
27 |
28 | assert len(sig) == 32
29 | assert sig[-4:] == b"\xa9\x05\x9c\xbb"
30 |
31 |
32 | def test_method_id_bytes4(get_contract):
33 | code = """
34 | @public
35 | def sig() -> bytes[4]:
36 | return method_id('transfer(address,uint256)', bytes[4])
37 | """
38 | c = get_contract(code)
39 | sig = c.sig()
40 |
41 | # assert len(sig) == 4
42 | assert sig == b"\xa9\x05\x9c\xbb"
43 |
44 |
45 | def test_method_id_invalid_space(get_contract, assert_compile_failed):
46 | code = """
47 | @public
48 | def sig() -> bytes32:
49 | return method_id('transfer(address, uint256)', bytes32)
50 | """
51 | assert_compile_failed(lambda: get_contract(code))
52 |
53 |
54 | def test_method_id_invalid_type(get_contract, assert_compile_failed):
55 | code = """
56 | @public
57 | def sig() -> int128:
58 | return method_id('transfer(address,uint256)', int128)
59 | """
60 | assert_compile_failed(lambda: get_contract(code))
61 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_only_init_abi.py:
--------------------------------------------------------------------------------
1 | from vyper.compiler import mk_full_signature
2 |
3 |
4 | def test_only_init_function():
5 | code = """
6 | x: int128
7 |
8 | @public
9 | def __init__():
10 | self.x = 1
11 | """
12 | code_init_empty = """
13 | x: int128
14 |
15 | @public
16 | def __init__():
17 | pass
18 | """
19 |
20 | empty_sig = [{
21 | 'name': '__init__',
22 | 'outputs': [],
23 | 'inputs': [],
24 | 'constant': False,
25 | 'payable': False,
26 | 'type': 'constructor'
27 | }]
28 |
29 | assert mk_full_signature(code) == empty_sig
30 | assert mk_full_signature(code_init_empty) == empty_sig
31 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_send.py:
--------------------------------------------------------------------------------
1 | def test_send(assert_tx_failed, get_contract):
2 | send_test = """
3 | @public
4 | def foo():
5 | send(msg.sender, self.balance + 1)
6 |
7 | @public
8 | def fop():
9 | send(msg.sender, 10)
10 | """
11 | c = get_contract(send_test, value=10)
12 | assert_tx_failed(lambda: c.foo(transact={}))
13 | c.fop(transact={})
14 | assert_tx_failed(lambda: c.fop(transact={}))
15 |
16 |
17 | def test_payable_tx_fail(assert_tx_failed, get_contract, w3):
18 | code = """
19 | @public
20 | def pay_me() -> bool:
21 | return True
22 | """
23 | c = get_contract(code)
24 | assert_tx_failed(lambda: c.pay_me(transact={'value': w3.toWei(0.1, 'ether')}))
25 |
26 |
27 | def test_default_gas(get_contract, w3):
28 | """ Tests to verify that send to default function will send limited gas (2300), but raw_call can send more."""
29 |
30 | sender_code = """
31 | @public
32 | def test_send(receiver: address):
33 | send(receiver, 1)
34 |
35 | @public
36 | def test_call(receiver: address):
37 | raw_call(receiver, "", gas=50000, outsize=0, value=1)
38 | """
39 |
40 | # default function writes variable, this requires more gas than send can pass
41 | receiver_code = """
42 | last_sender: public(address)
43 |
44 | @public
45 | @payable
46 | def __default__():
47 | self.last_sender = msg.sender
48 | """
49 |
50 | sender = get_contract(sender_code, value=1)
51 | receiver = get_contract(receiver_code)
52 |
53 | sender.test_send(receiver.address, transact={'gas': 100000})
54 |
55 | # no value transfer hapenned, variable was not changed
56 | assert receiver.last_sender() is None
57 | assert w3.eth.getBalance(sender.address) == 1
58 | assert w3.eth.getBalance(receiver.address) == 0
59 |
60 | sender.test_call(receiver.address, transact={'gas': 100000})
61 |
62 | # value transfer hapenned, variable was changed
63 | assert receiver.last_sender() == sender.address
64 | assert w3.eth.getBalance(sender.address) == 0
65 | assert w3.eth.getBalance(receiver.address) == 1
66 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_sha3.py:
--------------------------------------------------------------------------------
1 | def test_hash_code(get_contract_with_gas_estimation, keccak):
2 | hash_code = """
3 | @public
4 | def foo(inp: bytes[100]) -> bytes32:
5 | return sha3(inp)
6 |
7 | @public
8 | def bar() -> bytes32:
9 | return sha3("inp")
10 | """
11 |
12 | c = get_contract_with_gas_estimation(hash_code)
13 | for inp in (b"", b"cow", b"s" * 31, b"\xff" * 32, b"\n" * 33, b"g" * 64, b"h" * 65):
14 | assert '0x' + c.foo(inp).hex() == keccak(inp).hex()
15 |
16 | assert '0x' + c.bar().hex() == keccak(b"inp").hex()
17 |
18 |
19 | def test_hash_code2(get_contract_with_gas_estimation):
20 | hash_code2 = """
21 | @public
22 | def foo(inp: bytes[100]) -> bool:
23 | return sha3(inp) == sha3("badminton")
24 | """
25 | c = get_contract_with_gas_estimation(hash_code2)
26 | assert c.foo(b"badminto") is False
27 | assert c.foo(b"badminton") is True
28 |
29 |
30 | def test_hash_code3(get_contract_with_gas_estimation):
31 | hash_code3 = """
32 | test: bytes[100]
33 |
34 | @public
35 | def set_test(inp: bytes[100]):
36 | self.test = inp
37 |
38 | @public
39 | def tryy(inp: bytes[100]) -> bool:
40 | return sha3(inp) == sha3(self.test)
41 |
42 | @public
43 | def trymem(inp: bytes[100]) -> bool:
44 | x: bytes[100] = self.test
45 | return sha3(inp) == sha3(x)
46 |
47 | @public
48 | def try32(inp: bytes32) -> bool:
49 | return sha3(inp) == sha3(self.test)
50 | """
51 | c = get_contract_with_gas_estimation(hash_code3)
52 | c.set_test(b"", transact={})
53 | assert c.tryy(b"") is True
54 | assert c.trymem(b"") is True
55 | assert c.tryy(b"cow") is False
56 | c.set_test(b"cow", transact={})
57 | assert c.tryy(b"") is False
58 | assert c.tryy(b"cow") is True
59 | c.set_test(b"\x35" * 32, transact={})
60 | assert c.tryy(b"\x35" * 32) is True
61 | assert c.trymem(b"\x35" * 32) is True
62 | assert c.try32(b"\x35" * 32) is True
63 | assert c.tryy(b"\x35" * 33) is False
64 | c.set_test(b"\x35" * 33, transact={})
65 | assert c.tryy(b"\x35" * 32) is False
66 | assert c.trymem(b"\x35" * 32) is False
67 | assert c.try32(b"\x35" * 32) is False
68 | assert c.tryy(b"\x35" * 33) is True
69 |
70 | print("Passed SHA3 hash test")
71 |
--------------------------------------------------------------------------------
/tests/parser/functions/test_slice.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | def test_test_slice(get_contract_with_gas_estimation):
4 | test_slice = """
5 |
6 | @public
7 | def foo(inp1: bytes[10]) -> bytes[3]:
8 | x: int128 = 5
9 | s: bytes[3] = slice(inp1, start=3, len=3)
10 | y: int128 = 7
11 | return s
12 |
13 | @public
14 | def bar(inp1: bytes[10]) -> int128:
15 | x: int128 = 5
16 | s: bytes[3] = slice(inp1, start=3, len=3)
17 | y: int128 = 7
18 | return x * y
19 | """
20 |
21 | c = get_contract_with_gas_estimation(test_slice)
22 | x = c.foo(b"badminton")
23 | assert x == b"min", x
24 |
25 | assert c.bar(b"badminton") == 35
26 |
27 | print('Passed slice test')
28 |
29 |
30 | def test_test_slice2(get_contract_with_gas_estimation):
31 | test_slice2 = """
32 | @public
33 | def slice_tower_test(inp1: bytes[50]) -> bytes[50]:
34 | inp: bytes[50] = inp1
35 | for i in range(1, 11):
36 | inp = slice(inp, start=1, len=30 - i * 2)
37 | return inp
38 | """
39 | c = get_contract_with_gas_estimation(test_slice2)
40 | x = c.slice_tower_test(b"abcdefghijklmnopqrstuvwxyz1234")
41 | assert x == b"klmnopqrst", x
42 |
43 | print('Passed advanced slice test')
44 |
45 |
46 | def test_test_slice3(get_contract_with_gas_estimation):
47 | test_slice3 = """
48 | x: int128
49 | s: bytes[50]
50 | y: int128
51 | @public
52 | def foo(inp1: bytes[50]) -> bytes[50]:
53 | self.x = 5
54 | self.s = slice(inp1, start=3, len=3)
55 | self.y = 7
56 | return self.s
57 |
58 | @public
59 | def bar(inp1: bytes[50]) -> int128:
60 | self.x = 5
61 | self.s = slice(inp1, start=3, len=3)
62 | self.y = 7
63 | return self.x * self.y
64 | """
65 |
66 | c = get_contract_with_gas_estimation(test_slice3)
67 | x = c.foo(b"badminton")
68 | assert x == b"min", x
69 |
70 | assert c.bar(b"badminton") == 35
71 |
72 | print('Passed storage slice test')
73 |
74 |
75 | def test_test_slice4(get_contract_with_gas_estimation, assert_tx_failed):
76 | test_slice4 = """
77 | @public
78 | def foo(inp: bytes[10], start: int128, _len: int128) -> bytes[10]:
79 | return slice(inp, start=start, len=_len)
80 | """
81 |
82 | c = get_contract_with_gas_estimation(test_slice4)
83 | assert c.foo(b"badminton", 3, 3) == b"min"
84 | assert c.foo(b"badminton", 0, 9) == b"badminton"
85 | assert c.foo(b"badminton", 1, 8) == b"adminton"
86 | assert c.foo(b"badminton", 1, 7) == b"adminto"
87 | assert c.foo(b"badminton", 1, 0) == b""
88 | assert c.foo(b"badminton", 9, 0) == b""
89 |
90 | assert_tx_failed(lambda: c.foo(b"badminton", 0, 10))
91 | assert_tx_failed(lambda: c.foo(b"badminton", 1, 9))
92 | assert_tx_failed(lambda: c.foo(b"badminton", 9, 1))
93 | assert_tx_failed(lambda: c.foo(b"badminton", 10, 0))
94 |
95 | print('Passed slice edge case test')
96 |
97 |
98 | def test_slice_at_end(get_contract):
99 | code = """
100 | @public
101 | def ret10_slice() -> bytes[10]:
102 | b: bytes[32] = concat(convert(65, bytes32), '')
103 | c: bytes[10] = slice(b, start=31, len=1)
104 | return c
105 | """
106 |
107 | c = get_contract(code)
108 | assert c.ret10_slice() == b'A'
109 |
--------------------------------------------------------------------------------
/tests/parser/globals/test_getters.py:
--------------------------------------------------------------------------------
1 | def test_state_accessor(get_contract_with_gas_estimation_for_constants):
2 | state_accessor = """
3 | y: int128[int128]
4 |
5 | @public
6 | def oo():
7 | self.y[3] = 5
8 |
9 | @public
10 | def foo() -> int128:
11 | return self.y[3]
12 |
13 | """
14 |
15 | c = get_contract_with_gas_estimation_for_constants(state_accessor)
16 | c.oo(transact={})
17 | assert c.foo() == 5
18 | print('Passed basic state accessor test')
19 |
20 |
21 | def test_getter_code(get_contract_with_gas_estimation_for_constants):
22 | getter_code = """
23 | x: public(wei_value)
24 | y: public(int128[5])
25 | z: public(bytes[100])
26 | w: public({
27 | a: wei_value,
28 | b: int128[7],
29 | c: bytes[100],
30 | d: int128[address],
31 | e: int128[3][3],
32 | f: timestamp,
33 | g: wei_value
34 | }[int128])
35 |
36 | @public
37 | def __init__():
38 | self.x = as_wei_value(7, "wei")
39 | self.y[1] = 9
40 | self.z = "cow"
41 | self.w[1].a = 11
42 | self.w[1].b[2] = 13
43 | self.w[1].c = "horse"
44 | self.w[1].d[0x1234567890123456789012345678901234567890] = 15
45 | self.w[2].e[1][2] = 17
46 | self.w[3].f = 750
47 | self.w[3].g = 751
48 | """
49 |
50 | c = get_contract_with_gas_estimation_for_constants(getter_code)
51 | assert c.x() == 7
52 | assert c.y(1) == 9
53 | assert c.z() == b"cow"
54 | assert c.w__a(1) == 11
55 | assert c.w__b(1, 2) == 13
56 | assert c.w__c(1) == b"horse"
57 | assert c.w__d(1, "0x1234567890123456789012345678901234567890") == 15
58 | assert c.w__e(2, 1, 2) == 17
59 | assert c.w__f(3) == 750
60 | assert c.w__g(3) == 751
61 |
62 | print('Passed getter tests')
63 |
--------------------------------------------------------------------------------
/tests/parser/globals/test_globals.py:
--------------------------------------------------------------------------------
1 | from pytest import raises
2 | from vyper.exceptions import VariableDeclarationException
3 |
4 |
5 | def test_permanent_variables_test(get_contract_with_gas_estimation):
6 | permanent_variables_test = """
7 | var: {a: int128, b: int128}
8 |
9 | @public
10 | def __init__(a: int128, b: int128):
11 | self.var.a = a
12 | self.var.b = b
13 |
14 | @public
15 | def returnMoose() -> int128:
16 | return self.var.a * 10 + self.var.b
17 | """
18 |
19 | c = get_contract_with_gas_estimation(permanent_variables_test, *[5, 7])
20 | assert c.returnMoose() == 57
21 | print('Passed init argument and variable member test')
22 |
23 |
24 | def test_missing_global(get_contract):
25 | code = """
26 | @public
27 | def a() -> int128:
28 | return self.b
29 | """
30 |
31 | with raises(VariableDeclarationException):
32 | get_contract(code)
33 |
--------------------------------------------------------------------------------
/tests/parser/integration/test_basics.py:
--------------------------------------------------------------------------------
1 | def test_null_code(get_contract_with_gas_estimation):
2 | null_code = """
3 | @public
4 | def foo():
5 | pass
6 | """
7 | c = get_contract_with_gas_estimation(null_code)
8 | c.foo()
9 | print('Successfully executed a null function')
10 |
11 |
12 | def test_basic_code(get_contract_with_gas_estimation):
13 | basic_code = """
14 | @public
15 | def foo(x: int128) -> int128:
16 | return x * 2
17 |
18 | """
19 | c = get_contract_with_gas_estimation(basic_code)
20 | assert c.foo(9) == 18
21 | print('Passed basic code test')
22 |
23 |
24 | def test_selfcall_code_3(get_contract_with_gas_estimation, keccak):
25 | selfcall_code_3 = """
26 | @public
27 | def _hashy2(x: bytes[100]) -> bytes32:
28 | return sha3(x)
29 |
30 | @public
31 | def return_hash_of_cow_x_30() -> bytes32:
32 | return self._hashy2("cowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcowcow")
33 |
34 | @public
35 | def _len(x: bytes[100]) -> int128:
36 | return len(x)
37 |
38 | @public
39 | def returnten() -> int128:
40 | return self._len("badminton!")
41 | """
42 |
43 | c = get_contract_with_gas_estimation(selfcall_code_3)
44 | assert c.return_hash_of_cow_x_30() == keccak(b'cow' * 30)
45 | assert c.returnten() == 10
46 |
47 | print("Passed single variable-size argument self-call test")
48 |
--------------------------------------------------------------------------------
/tests/parser/integration/test_escrow.py:
--------------------------------------------------------------------------------
1 | # from ethereum.tools import tester
2 |
3 |
4 | def test_arbitration_code(w3, get_contract_with_gas_estimation, assert_tx_failed):
5 | arbitration_code = """
6 | buyer: address
7 | seller: address
8 | arbitrator: address
9 |
10 | @public
11 | def setup(_seller: address, _arbitrator: address):
12 | if self.buyer == ZERO_ADDRESS:
13 | self.buyer = msg.sender
14 | self.seller = _seller
15 | self.arbitrator = _arbitrator
16 |
17 | @public
18 | def finalize():
19 | assert msg.sender == self.buyer or msg.sender == self.arbitrator
20 | send(self.seller, self.balance)
21 |
22 | @public
23 | def refund():
24 | assert msg.sender == self.seller or msg.sender == self.arbitrator
25 | send(self.buyer, self.balance)
26 |
27 | """
28 | a0, a1, a2 = w3.eth.accounts[:3]
29 | c = get_contract_with_gas_estimation(arbitration_code, value=1)
30 | c.setup(a1, a2, transact={})
31 | assert_tx_failed(lambda: c.finalize(transact={'from': a1}))
32 | c.finalize(transact={})
33 |
34 | print('Passed escrow test')
35 |
36 |
37 | def test_arbitration_code_with_init(w3, assert_tx_failed, get_contract_with_gas_estimation):
38 | arbitration_code_with_init = """
39 | buyer: address
40 | seller: address
41 | arbitrator: address
42 |
43 | @public
44 | @payable
45 | def __init__(_seller: address, _arbitrator: address):
46 | if self.buyer == ZERO_ADDRESS:
47 | self.buyer = msg.sender
48 | self.seller = _seller
49 | self.arbitrator = _arbitrator
50 |
51 | @public
52 | def finalize():
53 | assert msg.sender == self.buyer or msg.sender == self.arbitrator
54 | send(self.seller, self.balance)
55 |
56 | @public
57 | def refund():
58 | assert msg.sender == self.seller or msg.sender == self.arbitrator
59 | send(self.buyer, self.balance)
60 | """
61 | a0, a1, a2 = w3.eth.accounts[:3]
62 | c = get_contract_with_gas_estimation(arbitration_code_with_init, *[a1, a2], value=1)
63 | assert_tx_failed(lambda: c.finalize(transact={'from': a1}))
64 | c.finalize(transact={'from': a0})
65 |
66 | print('Passed escrow test with initializer')
67 |
--------------------------------------------------------------------------------
/tests/parser/syntax/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/tests/parser/syntax/__init__.py
--------------------------------------------------------------------------------
/tests/parser/syntax/test_ann_assign.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import (
6 | VariableDeclarationException,
7 | TypeMismatchException,
8 | StructureException
9 | )
10 |
11 |
12 | fail_list = [
13 | """
14 | @public
15 | def test():
16 | a = 1
17 | """,
18 | """
19 | @public
20 | def test():
21 | a = 33.33
22 | """,
23 | """
24 | @public
25 | def test():
26 | a = "test string"
27 | """,
28 | ("""
29 | @public
30 | def test():
31 | a: int128 = 33.33
32 | """, TypeMismatchException),
33 | ("""
34 | @private
35 | def do_stuff() -> bool:
36 | return True
37 |
38 | @public
39 | def test():
40 | a: bool = self.do_stuff() or self.do_stuff()
41 | """, StructureException),
42 | ("""
43 | @private
44 | def do_stuff() -> bool:
45 | return True
46 |
47 | @public
48 | def test():
49 | a: bool = False or self.do_stuff()
50 | """, StructureException),
51 | ("""
52 | @public
53 | def data() -> int128:
54 | s: int128[5] = [1, 2, 3, 4, 5, 6]
55 | """, TypeMismatchException),
56 | ("""
57 | @public
58 | def foo() -> int128:
59 | struct: {a: int128, b: decimal} = {a: 1.2, b: 1}
60 | return struct.a
61 | """, TypeMismatchException),
62 | ("""
63 | @public
64 | def foo() -> int128:
65 | struct: {a: int128, b: decimal} = {b: 1.2, c: 1, d: 33, e: 55}
66 | return struct.a
67 | """, TypeMismatchException)
68 | ]
69 |
70 |
71 | @pytest.mark.parametrize('bad_code', fail_list)
72 | def test_as_wei_fail(bad_code):
73 | if isinstance(bad_code, tuple):
74 | with raises(bad_code[1]):
75 | compiler.compile(bad_code[0])
76 | else:
77 | with raises(VariableDeclarationException):
78 | compiler.compile(bad_code)
79 |
80 |
81 | valid_list = [
82 | """
83 | @public
84 | def test():
85 | a: int128 = 1
86 | """,
87 | """
88 | @private
89 | def do_stuff() -> bool:
90 | return True
91 |
92 | @public
93 | def test():
94 | a: bool = self.do_stuff()
95 | """
96 | ]
97 |
98 |
99 | @pytest.mark.parametrize('good_code', valid_list)
100 | def test_ann_assign_success(good_code):
101 | assert compiler.compile(good_code) is not None
102 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_as_uint256.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def convert2(inp: uint256) -> address:
12 | return convert(inp, bytes32)
13 | """,
14 | """
15 | @public
16 | def modtest(x: uint256, y: int128) -> uint256:
17 | return x % y
18 | """
19 | ]
20 |
21 |
22 | @pytest.mark.parametrize('bad_code', fail_list)
23 | def test_as_wei_fail(bad_code):
24 |
25 | with raises(TypeMismatchException):
26 | compiler.compile(bad_code)
27 |
28 |
29 | valid_list = [
30 | """
31 | @public
32 | def convert1(inp: bytes32) -> uint256:
33 | return convert(inp, uint256)
34 | """,
35 | """
36 | @public
37 | def convert1(inp: bytes32) -> uint256:
38 | return convert(inp, uint256)
39 | """,
40 | """
41 | @public
42 | def convert2(inp: uint256) -> bytes32:
43 | return convert(inp, bytes32)
44 | """
45 | ]
46 |
47 |
48 | @pytest.mark.parametrize('good_code', valid_list)
49 | def test_as_wei_success(good_code):
50 | assert compiler.compile(good_code) is not None
51 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_as_wei_value.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo():
12 | x: int128(wei) = as_wei_value(5, szabo)
13 | """,
14 | """
15 | @public
16 | def foo() -> int128(wei):
17 | x: int128(wei) = 45
18 | return x.balance
19 | """
20 | ]
21 |
22 |
23 | @pytest.mark.parametrize('bad_code', fail_list)
24 | def test_as_wei_fail(bad_code):
25 | with raises(TypeMismatchException):
26 | compiler.compile(bad_code)
27 |
28 |
29 | valid_list = [
30 | """
31 | @public
32 | def foo():
33 | x: uint256(wei) = as_wei_value(5, "finney") + as_wei_value(2, "babbage") + as_wei_value(8, "shannon")
34 | """,
35 | """
36 | @public
37 | def foo():
38 | z: int128 = 2 + 3
39 | x: uint256(wei) = as_wei_value(2 + 3, "finney")
40 | """,
41 | """
42 | @public
43 | def foo():
44 | x: uint256(wei) = as_wei_value(5.182, "babbage")
45 | """,
46 | """
47 | @public
48 | def foo() -> uint256(wei):
49 | x: address = 0x1234567890123456789012345678901234567890
50 | return x.balance
51 | """
52 | ]
53 |
54 |
55 | @pytest.mark.parametrize('good_code', valid_list)
56 | def test_as_wei_success(good_code):
57 | assert compiler.compile(good_code) is not None
58 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_blockscope.py:
--------------------------------------------------------------------------------
1 |
2 | import pytest
3 | from pytest import raises
4 |
5 | from vyper import compiler
6 | from vyper.exceptions import VariableDeclarationException
7 |
8 |
9 | fail_list = [
10 | """
11 | @public
12 | def foo(choice: bool):
13 | if (choice):
14 | a = 1
15 | a += 1
16 | """,
17 | """
18 | @public
19 | def foo(choice: bool):
20 | if (choice):
21 | a = 0
22 | else:
23 | a = 1
24 | a += 1
25 | """,
26 | """
27 | @public
28 | def foo(choice: bool):
29 | if (choice):
30 | a = 0
31 | else:
32 | a += 1
33 | """,
34 | """
35 | @public
36 | def foo(choice: bool):
37 |
38 | for i in range(4):
39 | a = 0
40 | a += 1
41 | """,
42 | """
43 | @public
44 | def foo(choice: bool):
45 |
46 | for i in range(4):
47 | a = 0
48 | a += 1
49 | """,
50 | """
51 | a: int128
52 |
53 | @public
54 | def foo():
55 | a = 5
56 | """,
57 | ]
58 |
59 |
60 | @pytest.mark.parametrize('bad_code', fail_list)
61 | def test_fail_(bad_code):
62 |
63 | with raises(VariableDeclarationException):
64 | compiler.compile(bad_code)
65 |
66 |
67 | valid_list = [
68 | """
69 | @public
70 | def foo(choice: bool, choice2: bool):
71 | if (choice):
72 | a: int128 = 11
73 | if choice2 and a > 1:
74 | a -= 1 # should be visible here.
75 | """
76 | ]
77 |
78 |
79 | @pytest.mark.parametrize('good_code', valid_list)
80 | def test_valid_blockscope(good_code):
81 | assert compiler.compile(good_code) is not None
82 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_bool.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo():
12 | x: bool = True
13 | x = 5
14 | """,
15 | ("""
16 | @public
17 | def foo():
18 | True = 3
19 | """, SyntaxError),
20 | """
21 | @public
22 | def foo():
23 | x: bool = True
24 | x = 129
25 | """,
26 | """
27 | @public
28 | def foo() -> bool:
29 | return (1 == 2) <= (1 == 1)
30 | """,
31 | """
32 | @public
33 | def foo() -> bool:
34 | return (1 == 2) or 3
35 | """,
36 | """
37 | @public
38 | def foo() -> bool:
39 | return 1.0 == 1
40 | """,
41 | """
42 | @public
43 | def foo() -> bool:
44 | a: address
45 | return a == 1
46 | """,
47 | """
48 | @public
49 | def foo(a: address) -> bool:
50 | return not a
51 | """,
52 | """
53 | @public
54 | def foo() -> bool:
55 | b: int128
56 | return not b
57 | """,
58 | """
59 | @public
60 | def foo() -> bool:
61 | b: uint256
62 | return not b
63 | """,
64 | """
65 | @public
66 | def foo() -> bool:
67 | b: uint256
68 | return not b
69 | """,
70 | """
71 | @public
72 | def test(a: address) -> bool:
73 | assert(a)
74 | return True
75 | """
76 | ]
77 |
78 |
79 | @pytest.mark.parametrize('bad_code', fail_list)
80 | def test_bool_fail(bad_code):
81 |
82 | if isinstance(bad_code, tuple):
83 | with raises(bad_code[1]):
84 | compiler.compile(bad_code[0])
85 | else:
86 | with raises(TypeMismatchException):
87 | compiler.compile(bad_code)
88 |
89 |
90 | valid_list = [
91 | """
92 | @public
93 | def foo():
94 | x: bool = True
95 | z: bool = x and False
96 | """,
97 | """
98 | @public
99 | def foo():
100 | x: bool = True
101 | z: bool = x and False
102 | """,
103 | """
104 | @public
105 | def foo():
106 | x: bool = True
107 | x = False
108 | """,
109 | """
110 | @public
111 | def foo() -> bool:
112 | return 1 == 1
113 | """,
114 | """
115 | @public
116 | def foo() -> bool:
117 | return 1 != 1
118 | """,
119 | """
120 | @public
121 | def foo() -> bool:
122 | return 1 > 1
123 | """,
124 | """
125 | @public
126 | def foo() -> bool:
127 | return 2 >= 1
128 | """,
129 | """
130 | @public
131 | def foo() -> bool:
132 | return 1 < 1
133 | """,
134 | """
135 | @public
136 | def foo() -> bool:
137 | return 1 <= 1
138 | """,
139 | """
140 | @public
141 | def foo2(a: address) -> bool:
142 | return a != ZERO_ADDRESS
143 | """
144 | ]
145 |
146 |
147 | @pytest.mark.parametrize('good_code', valid_list)
148 | def test_bool_success(good_code):
149 | assert compiler.compile(good_code) is not None
150 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_byte_string.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from vyper import compiler
4 |
5 |
6 | valid_list = [
7 | """
8 | @public
9 | def foo() -> bytes[10]:
10 | return "badminton"
11 | """,
12 | """
13 | @public
14 | def foo():
15 | x: bytes[11] = "¡très bien!"
16 | """
17 | ]
18 |
19 |
20 | @pytest.mark.parametrize('good_code', valid_list)
21 | def test_byte_string_success(good_code):
22 | assert compiler.compile(good_code) is not None
23 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_bytes.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import (
6 | TypeMismatchException,
7 | InvalidLiteralException
8 | )
9 |
10 | fail_list = [
11 | """
12 | @public
13 | def baa():
14 | x: bytes[50]
15 | y: bytes[50]
16 | z = x + y
17 | """,
18 | """
19 | @public
20 | def baa():
21 | x: bytes[50]
22 | y: int128
23 | y = x
24 | """,
25 | """
26 | @public
27 | def baa():
28 | x: bytes[50]
29 | y: int128
30 | x = y
31 | """,
32 | """
33 | @public
34 | def baa():
35 | x: bytes[50]
36 | y: bytes[60]
37 | x = y
38 | """,
39 | """
40 | @public
41 | def foo(x: bytes[100]) -> bytes[75]:
42 | return x
43 | """,
44 | """
45 | @public
46 | def foo(x: bytes[100]) -> int128:
47 | return x
48 | """,
49 | """
50 | @public
51 | def foo(x: int128) -> bytes[75]:
52 | return x
53 | """,
54 | """
55 | @public
56 | def foo() -> bytes[10]:
57 | x: bytes[10] = '0x1234567890123456789012345678901234567890'
58 | x = 0x1234567890123456789012345678901234567890
59 | """,
60 | """
61 | @public
62 | def foo() -> bytes[10]:
63 | return "badmintonzz"
64 | """,
65 | ("""
66 | @public
67 | def test() -> bytes[1]:
68 | a: bytes[1] = 0b0000001 # needs mutliple of 8 bits.
69 | return a
70 | """, InvalidLiteralException)
71 | ]
72 |
73 |
74 | @pytest.mark.parametrize('bad_code', fail_list)
75 | def test_bytes_fail(bad_code):
76 | if isinstance(bad_code, tuple):
77 | with raises(bad_code[1]):
78 | compiler.compile(bad_code[0])
79 | else:
80 | with raises(TypeMismatchException):
81 | compiler.compile(bad_code)
82 |
83 |
84 | valid_list = [
85 | """
86 | @public
87 | def foo(x: bytes[100]) -> bytes[100]:
88 | return x
89 | """,
90 | """
91 | @public
92 | def foo(x: bytes[100]) -> bytes[150]:
93 | return x
94 | """,
95 | """
96 | @public
97 | def convert2(inp: uint256) -> bytes32:
98 | return convert(inp, bytes32)
99 | """,
100 | """
101 | @public
102 | def baa():
103 | x: bytes[50]
104 | """
105 | ]
106 |
107 |
108 | @pytest.mark.parametrize('good_code', valid_list)
109 | def test_bytes_success(good_code):
110 | assert compiler.compile(good_code) is not None
111 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_code_size.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo() -> int128:
12 | x: int128 = 45
13 | return x.codesize
14 | """,
15 | """
16 | @public
17 | def foo() -> int128(wei):
18 | x: address = 0x1234567890123456789012345678901234567890
19 | return x.codesize
20 | """
21 | ]
22 |
23 |
24 | @pytest.mark.parametrize('bad_code', fail_list)
25 | def test_block_fail(bad_code):
26 |
27 | with raises(TypeMismatchException):
28 | compiler.compile(bad_code)
29 |
30 |
31 | valid_list = [
32 | """
33 | @public
34 | def foo() -> int128:
35 | x: address = 0x1234567890123456789012345678901234567890
36 | return x.codesize
37 | """
38 | ]
39 |
40 |
41 | @pytest.mark.parametrize('good_code', valid_list)
42 | def test_block_success(good_code):
43 | assert compiler.compile(good_code) is not None
44 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_concat.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from pytest import raises
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def cat(i1: bytes[10], i2: bytes[30]) -> bytes[40]:
12 | return concat(i1, i2, i1, i1)
13 | """,
14 | """
15 | @public
16 | def cat(i1: bytes[10], i2: bytes[30]) -> bytes[40]:
17 | return concat(i1, 5)
18 | """,
19 | """
20 | @public
21 | def sandwich(inp: bytes[100], inp2: bytes32) -> bytes[163]:
22 | return concat(inp2, inp, inp2)
23 | """,
24 | """
25 | y: bytes[10]
26 |
27 | @public
28 | def krazykonkat(z: bytes[10]) -> bytes[24]:
29 | x: bytes[10] = "cow"
30 | self.y = "horse"
31 | return concat(x, " ", self.y, " ", z)
32 | """,
33 | """
34 | @public
35 | def cat_list(y: int128) -> bytes[40]:
36 | x: int128[1] = [y]
37 | return concat("test", y)
38 | """,
39 | ]
40 |
41 |
42 | @pytest.mark.parametrize('bad_code', fail_list)
43 | def test_block_fail(bad_code):
44 |
45 | with raises(TypeMismatchException):
46 | compiler.compile(bad_code)
47 |
48 |
49 | valid_list = [
50 | """
51 | @public
52 | def cat(i1: bytes[10], i2: bytes[30]) -> bytes[40]:
53 | return concat(i1, i2)
54 | """,
55 | """
56 | @public
57 | def cat(i1: bytes[10], i2: bytes[30]) -> bytes[40]:
58 | return concat(i1, i1, i1, i1)
59 | """,
60 | """
61 | @public
62 | def cat(i1: bytes[10], i2: bytes[30]) -> bytes[40]:
63 | return concat(i1, i1)
64 | """,
65 | """
66 | @public
67 | def sandwich(inp: bytes[100], inp2: bytes32) -> bytes[165]:
68 | return concat(inp2, inp, inp2)
69 | """,
70 | """
71 | y: bytes[10]
72 |
73 | @public
74 | def krazykonkat(z: bytes[10]) -> bytes[25]:
75 | x: bytes[3] = "cow"
76 | self.y = "horse"
77 | return concat(x, " ", self.y, " ", z)
78 | """
79 | ]
80 |
81 |
82 | @pytest.mark.parametrize('good_code', valid_list)
83 | def test_block_success(good_code):
84 | assert compiler.compile(good_code) is not None
85 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_constants.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import (
6 | StructureException,
7 | TypeMismatchException,
8 | VariableDeclarationException,
9 | )
10 |
11 |
12 | fail_list = [
13 | # no value
14 | """
15 | VAL: constant(uint256)
16 | """,
17 | # too many args
18 | """
19 | VAL: constant(uint256, int128) = 12
20 | """,
21 | # invalid type
22 | ("""
23 | VAL: constant(uint256) = "test"
24 | """, TypeMismatchException),
25 | # invalid range
26 | ("""
27 | VAL: constant(uint256) = -1
28 | """, TypeMismatchException),
29 | # reserverd keyword
30 | ("""
31 | wei: constant(uint256) = 1
32 | """, VariableDeclarationException),
33 | # duplicate constant name
34 | ("""
35 | VAL: constant(uint256) = 11
36 | VAL: constant(uint256) = 11
37 | """, VariableDeclarationException),
38 | # bytearray too long.
39 | ("""
40 | VAL: constant(bytes[4]) = "testtest"
41 | """, TypeMismatchException),
42 | # global with same name
43 | ("""
44 | VAL: constant(bytes[4]) = "t"
45 | VAL: uint256
46 | """, VariableDeclarationException)
47 | ]
48 |
49 |
50 | @pytest.mark.parametrize('bad_code', fail_list)
51 | def test_as_wei_fail(bad_code):
52 | if isinstance(bad_code, tuple):
53 | with raises(bad_code[1]):
54 | compiler.compile(bad_code[0])
55 | else:
56 | with raises(StructureException):
57 | compiler.compile(bad_code)
58 |
59 |
60 | valid_list = [
61 | """
62 | VAL: constant(uint256) = 123
63 | """,
64 | """
65 | VAL: constant(int128) = -123
66 | @public
67 | def test() -> int128:
68 | return 1 * VAL
69 | """
70 | ]
71 |
72 |
73 | @pytest.mark.parametrize('good_code', valid_list)
74 | def test_as_wei_success(good_code):
75 | assert compiler.compile(good_code) is not None
76 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_create_with_code_of.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 |
6 |
7 | fail_list = [
8 | """
9 | @public
10 | def foo():
11 | x: address = create_with_code_of(0x1234567890123456789012345678901234567890, value=4, value=9)
12 | """
13 | ]
14 |
15 |
16 | @pytest.mark.parametrize('bad_code', fail_list)
17 | def test_type_mismatch_exception(bad_code):
18 | with raises(SyntaxError):
19 | compiler.compile(bad_code)
20 |
21 |
22 | valid_list = [
23 | """
24 | @public
25 | def foo():
26 | x: address = create_with_code_of(0x1234567890123456789012345678901234567890)
27 | """,
28 | """
29 | @public
30 | def foo():
31 | x: address = create_with_code_of(0x1234567890123456789012345678901234567890, value=as_wei_value(9, "wei"))
32 | """,
33 | """
34 | @public
35 | def foo():
36 | x: address = create_with_code_of(0x1234567890123456789012345678901234567890, value=9)
37 | """
38 | ]
39 |
40 |
41 | @pytest.mark.parametrize('good_code', valid_list)
42 | def test_rlp_success(good_code):
43 | assert compiler.compile(good_code) is not None
44 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_custom_units.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import (
6 | VariableDeclarationException,
7 | InvalidTypeException
8 | )
9 |
10 |
11 | fail_list = [
12 | """
13 | units: 1
14 | """,
15 | """
16 | units: {
17 | "cm": "centimeter"
18 | }
19 | """,
20 | """
21 | units: {
22 | "cm": 1
23 | }
24 | """,
25 | """
26 | units: {
27 | cm: "centimeter"
28 | }
29 | units: {
30 | km: "kilometer"
31 | }
32 | """,
33 | """
34 | units: {
35 | wei: "wei"
36 | }
37 | """,
38 | """
39 | units: {
40 | cm: 123
41 | }
42 | """,
43 | """
44 | units: {
45 | cm: "centimeter",
46 | cm: "kilometer"
47 | }
48 | """,
49 | ("""
50 | units: {
51 | cm: "centimeter",
52 | }
53 | @public
54 | def test():
55 | a: int128(km)
56 | """, InvalidTypeException),
57 | """
58 | units: {
59 | cm: "centimeter",
60 | }
61 | @public
62 | def test():
63 | cm: int128
64 | """,
65 | ("""
66 | units: {
67 | cm: "centimeter",
68 | }
69 | a: int128(km)
70 | """, InvalidTypeException),
71 | """
72 | units: {
73 | cm: "centimeter",
74 | }
75 | cm: bytes[5]
76 | """,
77 | """
78 | @public
79 | def test():
80 | units: bytes[4]
81 | """
82 | ]
83 |
84 |
85 | @pytest.mark.parametrize('bad_code', fail_list)
86 | def test_custom_units_fail(bad_code):
87 | if isinstance(bad_code, tuple):
88 | with raises(bad_code[1]):
89 | compiler.compile(bad_code[0])
90 | else:
91 | with raises(VariableDeclarationException):
92 | compiler.compile(bad_code)
93 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_extract32.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 | fail_list = [
8 | """
9 | @public
10 | def foo() -> uint256:
11 | return extract32("cowcowcowcowcowccowcowcowcowcowccowcowcowcowcowccowcowcowcowcowc", 0)
12 | """
13 | ]
14 |
15 |
16 | @pytest.mark.parametrize('bad_code', fail_list)
17 | def test_extract32_fail(bad_code):
18 |
19 | with raises(TypeMismatchException):
20 | compiler.compile(bad_code)
21 |
22 |
23 | valid_list = [
24 | """
25 | @public
26 | def foo() -> uint256:
27 | return extract32("cowcowcowcowcowccowcowcowcowcowccowcowcowcowcowccowcowcowcowcowc", 0, type=uint256)
28 | """,
29 | """
30 | x: bytes[100]
31 | @public
32 | def foo() -> uint256:
33 | self.x = "cowcowcowcowcowccowcowcowcowcowccowcowcowcowcowccowcowcowcowcowc"
34 | return extract32(self.x, 0, type=uint256)
35 | """,
36 | """
37 | x: bytes[100]
38 | @public
39 | def foo() -> uint256:
40 | self.x = "cowcowcowcowcowccowcowcowcowcowccowcowcowcowcowccowcowcowcowcowc"
41 | return extract32(self.x, 1, type=uint256)
42 | """
43 | ]
44 |
45 |
46 | @pytest.mark.parametrize('good_code', valid_list)
47 | def test_extract32_success(good_code):
48 | assert compiler.compile(good_code) is not None
49 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_for_range.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from vyper import compiler
4 |
5 | valid_list = [
6 | """
7 | @public
8 | def foo():
9 | for i in range(10):
10 | pass
11 | """,
12 | """
13 | @public
14 | def foo():
15 | for i in range(10, 20):
16 | pass
17 | """,
18 | """
19 | @public
20 | def foo():
21 | x: int128 = 5
22 | for i in range(x, x + 10):
23 | pass
24 | """
25 | ]
26 |
27 |
28 | @pytest.mark.parametrize('good_code', valid_list)
29 | def test_range_success(good_code):
30 | assert compiler.compile(good_code) is not None
31 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_functions_call.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import StructureException
6 |
7 | fail_list = [
8 | """
9 | @public
10 | def foo() -> uint256:
11 | doesnotexist(2, uint256)
12 | return convert(2, uint256)
13 | """,
14 | """
15 | @public
16 | def foo() -> uint256:
17 | convert(2, uint256)
18 | return convert(2, uint256)
19 |
20 | """
21 | ]
22 |
23 |
24 | @pytest.mark.parametrize('bad_code', fail_list)
25 | def test_raw_call_fail(bad_code):
26 |
27 | if isinstance(bad_code, tuple):
28 | with raises(bad_code[1]):
29 | compiler.compile(bad_code[0])
30 | else:
31 | with raises(StructureException):
32 | compiler.compile(bad_code)
33 |
34 |
35 | valid_list = [
36 | """
37 | @public
38 | def foo() -> uint256:
39 | return convert(2, uint256)
40 | """
41 | ]
42 |
43 |
44 | @pytest.mark.parametrize('good_code', valid_list)
45 | def test_raw_call_success(good_code):
46 | assert compiler.compile(good_code) is not None
47 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_len.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo(inp: int128) -> int128:
12 | return len(inp)
13 | """,
14 | """
15 | @public
16 | def foo(inp: int128) -> address:
17 | return len(inp)
18 | """
19 | ]
20 |
21 |
22 | @pytest.mark.parametrize('bad_code', fail_list)
23 | def test_block_fail(bad_code):
24 |
25 | if isinstance(bad_code, tuple):
26 | with raises(bad_code[1]):
27 | compiler.compile(bad_code[0])
28 | else:
29 | with raises(TypeMismatchException):
30 | compiler.compile(bad_code)
31 |
32 |
33 | valid_list = [
34 | """
35 | @public
36 | def foo(inp: bytes[10]) -> int128:
37 | return len(inp)
38 | """
39 | ]
40 |
41 |
42 | @pytest.mark.parametrize('good_code', valid_list)
43 | def test_list_success(good_code):
44 | assert compiler.compile(good_code) is not None
45 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_logging.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | Bar: event({_value: int128[4]})
11 | x: decimal[4]
12 |
13 | @public
14 | def foo():
15 | log.Bar(self.x)
16 | """,
17 | """
18 | Bar: event({_value: int128[4]})
19 |
20 | @public
21 | def foo():
22 | x: decimal[4]
23 | log.Bar(x)
24 | """
25 | ]
26 |
27 |
28 | @pytest.mark.parametrize('bad_code', fail_list)
29 | def test_logging_fail(bad_code):
30 |
31 | if isinstance(bad_code, tuple):
32 | with raises(bad_code[1]):
33 | compiler.compile(bad_code[0])
34 | else:
35 | with raises(TypeMismatchException):
36 | compiler.compile(bad_code)
37 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_minmax.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo():
12 | y = min(7, 0x1234567890123456789012345678901234567890)
13 | """
14 | ]
15 |
16 |
17 | @pytest.mark.parametrize('bad_code', fail_list)
18 | def test_block_fail(bad_code):
19 |
20 | with raises(TypeMismatchException):
21 | compiler.compile(bad_code)
22 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_missing_return.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import FunctionDeclarationException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo() -> int128:
12 | pass
13 | """,
14 | ]
15 |
16 |
17 | @pytest.mark.parametrize('bad_code', fail_list)
18 | def test_missing_return(bad_code):
19 | with raises(FunctionDeclarationException):
20 | compiler.compile(bad_code)
21 |
22 |
23 | valid_list = [
24 | """
25 | @public
26 | def foo() -> int128:
27 | return 123
28 | """,
29 | """
30 | @public
31 | def foo() -> int128:
32 | if False:
33 | return 123
34 | """, # For the time being this is valid code, even though it should not be.
35 | ]
36 |
37 |
38 | @pytest.mark.parametrize('good_code', valid_list)
39 | def test_return_success(good_code):
40 | assert compiler.compile(good_code) is not None
41 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_nested_list.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException, StructureException
6 |
7 |
8 | fail_list = [
9 | """
10 | bar: int128[3][3]
11 | @public
12 | def foo():
13 | self.bar = [[1, 2], [3, 4, 5], [6, 7, 8]]
14 | """,
15 | """
16 | bar: int128[3][3]
17 | @public
18 | def foo():
19 | self.bar = [[1, 2, 3], [4, 5, 6], [7.0, 8.0, 9.0]]
20 | """,
21 | """
22 | @public
23 | def foo() -> int128[2]:
24 | return [[1,2],[3,4]]
25 | """,
26 | """
27 | @public
28 | def foo() -> int128[2][2]:
29 | return [1,2]
30 | """,
31 | """
32 | y: address[2][2]
33 |
34 | @public
35 | def foo(x: int128[2][2]) -> int128:
36 | self.y = x
37 | """,
38 | ("""
39 | bar: int128[3][3]
40 |
41 | @public
42 | def foo() -> int128[3]:
43 | self.bar = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
44 | for x in self.bar:
45 | if x == [4, 5, 6]:
46 | return x
47 | """, StructureException)
48 | ]
49 |
50 |
51 | @pytest.mark.parametrize('bad_code', fail_list)
52 | def test_nested_list_fail(bad_code):
53 |
54 | if isinstance(bad_code, tuple):
55 | with raises(bad_code[1]):
56 | compiler.compile(bad_code[0])
57 | else:
58 | with raises(TypeMismatchException):
59 | compiler.compile(bad_code)
60 |
61 |
62 | valid_list = [
63 | """
64 | bar: int128[3][3]
65 | @public
66 | def foo():
67 | self.bar = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
68 | """,
69 | """
70 | bar: decimal[3][3]
71 | @public
72 | def foo():
73 | self.bar = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
74 | """
75 | ]
76 |
77 |
78 | @pytest.mark.parametrize('good_code', valid_list)
79 | def test_nested_list_sucess(good_code):
80 | assert compiler.compile(good_code) is not None
81 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_public.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from vyper import compiler
4 |
5 |
6 | valid_list = [
7 | """
8 | x: public(int128)
9 | """,
10 | """
11 | x: public(int128(wei / sec))
12 | y: public(int128(wei / sec ** 2))
13 | z: public(int128(1 / sec))
14 |
15 | @public
16 | def foo() -> int128(sec ** 2):
17 | return self.x / self.y / self.z
18 | """
19 | ]
20 |
21 |
22 | @pytest.mark.parametrize('good_code', valid_list)
23 | def test_public_success(good_code):
24 | assert compiler.compile(good_code) is not None
25 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_raw_call.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | ("""
10 | @public
11 | def foo():
12 | x: bytes[9] = raw_call(0x1234567890123456789012345678901234567890, "cow", outsize=4, outsize=9)
13 | """, SyntaxError),
14 | """
15 | @public
16 | def foo():
17 | raw_log(["cow"], "dog")
18 | """,
19 | """
20 | @public
21 | def foo():
22 | raw_log([], 0x1234567890123456789012345678901234567890)
23 | """
24 | ]
25 |
26 |
27 | @pytest.mark.parametrize('bad_code', fail_list)
28 | def test_raw_call_fail(bad_code):
29 |
30 | if isinstance(bad_code, tuple):
31 | with raises(bad_code[1]):
32 | compiler.compile(bad_code[0])
33 | else:
34 | with raises(TypeMismatchException):
35 | compiler.compile(bad_code)
36 |
37 |
38 | valid_list = [
39 | """
40 | @public
41 | def foo():
42 | x: bytes[9] = raw_call(0x1234567890123456789012345678901234567890, "cow", outsize=4, gas=595757)
43 | """,
44 | """
45 | @public
46 | def foo():
47 | x: bytes[9] = raw_call(0x1234567890123456789012345678901234567890, "cow", outsize=4, gas=595757, value=as_wei_value(9, "wei"))
48 | """,
49 | """
50 | @public
51 | def foo():
52 | x: bytes[9] = raw_call(0x1234567890123456789012345678901234567890, "cow", outsize=4, gas=595757, value=9)
53 | """
54 | ]
55 |
56 |
57 | @pytest.mark.parametrize('good_code', valid_list)
58 | def test_raw_call_success(good_code):
59 | assert compiler.compile(good_code) is not None
60 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_return_tuple.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import StructureException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def unmatched_tupl_length() -> (bytes[8], int128, bytes[8]):
12 | return "test", 123
13 | """
14 | ]
15 |
16 |
17 | @pytest.mark.parametrize('bad_code', fail_list)
18 | def test_tuple_return_fail(bad_code):
19 |
20 | with raises(StructureException):
21 | compiler.compile(bad_code)
22 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_rlplist.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException, StructureException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo() -> address:
12 | x = RLPList('\xf6\x9455555555555555555555\xa0GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG', [address, bytes32])
13 | return x[1]
14 | """,
15 | """
16 | @public
17 | def foo() -> address:
18 | x = RLPList('\xf6\x9455555555555555555555\xa0GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG', [address, bytes32])
19 | return x[2]
20 | """,
21 | """
22 | @public
23 | def foo() -> bytes[500]:
24 | x = RLPList('\xe1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', [bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes])
25 | return x[1]
26 | """,
27 | ("""
28 | @public
29 | def foo() -> bytes[500]:
30 | x: int128 = 1
31 | return RLPList('\xe0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
32 | """, StructureException),
33 | """
34 | @public
35 | def foo() -> bytes[500]:
36 | x: int128[3] = [1, 2, 3]
37 | return RLPList(x, [bytes])
38 | """,
39 | """
40 | @public
41 | def foo() -> bytes[500]:
42 | x: bytes[500] = '\xe1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
43 | a: int128 = 1
44 | return RLPList(x, a)
45 | """,
46 | """
47 | @public
48 | def foo() -> bytes[500]:
49 | x: bytes[500] = '\xe1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
50 | return RLPList(x, [])
51 | """,
52 | """
53 | @public
54 | def foo() -> bytes32:
55 | x = RLPList('\xe1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', [address, int128[2]])
56 | return x[1]
57 | """,
58 | """
59 | @public
60 | def foo() -> bytes32:
61 | x = RLPList('\xe1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', [decimal])
62 | return x[1]
63 | """,
64 | """
65 | @public
66 | def foo() -> bytes32:
67 | x = RLPList('\xe1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', [int128(wei)])
68 | return x[1]
69 | """
70 | ]
71 |
72 |
73 | @pytest.mark.parametrize('bad_code', fail_list)
74 | def test_rlplist_fail(bad_code):
75 |
76 | if isinstance(bad_code, tuple):
77 | with raises(bad_code[1]):
78 | compiler.compile(bad_code[0])
79 | else:
80 | with raises(TypeMismatchException):
81 | compiler.compile(bad_code)
82 |
83 |
84 | valid_list = [
85 | """
86 | @public
87 | def foo() -> bytes[500]:
88 | x = RLPList('\xe0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', [bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes, bytes])
89 | return x[1]
90 | """,
91 | """
92 | @public
93 | def foo() -> address:
94 | x = RLPList('\xf6\x9455555555555555555555\xa0GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG', [address, bytes32])
95 | return x[0]
96 | """,
97 | """
98 | @public
99 | def foo() -> bytes32:
100 | x = RLPList('\xf6\x9455555555555555555555\xa0GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG', [address, bytes32])
101 | return x[1]
102 | """
103 | ]
104 |
105 |
106 | @pytest.mark.parametrize('good_code', valid_list)
107 | def test_rlplist_success(good_code):
108 | assert compiler.compile(good_code) is not None
109 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_selfdestruct.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo():
12 | selfdestruct(7)
13 | """
14 | ]
15 |
16 |
17 | @pytest.mark.parametrize('bad_code', fail_list)
18 | def test_block_fail(bad_code):
19 |
20 | with raises(TypeMismatchException):
21 | compiler.compile(bad_code)
22 |
23 |
24 | valid_list = [
25 | """
26 | @public
27 | def foo():
28 | selfdestruct(0x1234567890123456789012345678901234567890)
29 | """
30 | ]
31 |
32 |
33 | @pytest.mark.parametrize('good_code', valid_list)
34 | def test_block_success(good_code):
35 | assert compiler.compile(good_code) is not None
36 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_send.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo():
12 | send(1, 2)
13 | """,
14 | """
15 | @public
16 | def foo():
17 | send(1, 2)
18 | """,
19 | """
20 | @public
21 | def foo():
22 | send(0x1234567890123456789012345678901234567890, 2.5)
23 | """,
24 | """
25 | @public
26 | def foo():
27 | send(0x1234567890123456789012345678901234567890, 0x1234567890123456789012345678901234567890)
28 | """,
29 | """
30 | x: int128
31 |
32 | @public
33 | def foo():
34 | send(0x1234567890123456789012345678901234567890, self.x)
35 | """,
36 | """
37 | x: wei_value
38 |
39 | @public
40 | def foo():
41 | send(0x1234567890123456789012345678901234567890, self.x + 1.5)
42 | """,
43 | """
44 | x: decimal
45 |
46 | @public
47 | def foo():
48 | send(0x1234567890123456789012345678901234567890, self.x)
49 | """
50 | ]
51 |
52 |
53 | @pytest.mark.parametrize('bad_code', fail_list)
54 | def test_send_fail(bad_code):
55 | with raises(TypeMismatchException):
56 | compiler.compile(bad_code)
57 |
58 |
59 | valid_list = [
60 | """
61 | x: wei_value
62 |
63 | @public
64 | def foo():
65 | send(0x1234567890123456789012345678901234567890, self.x + 1)
66 | """,
67 | """
68 | x: decimal
69 |
70 | @public
71 | def foo():
72 | send(0x1234567890123456789012345678901234567890, as_wei_value(floor(self.x), "wei"))
73 | """,
74 | """
75 | x: wei_value
76 |
77 | @public
78 | def foo():
79 | send(0x1234567890123456789012345678901234567890, self.x)
80 | """,
81 | """
82 | @public
83 | def foo():
84 | send(0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe, 5)
85 | """
86 | ]
87 |
88 |
89 | @pytest.mark.parametrize('good_code', valid_list)
90 | def test_block_success(good_code):
91 | assert compiler.compile(good_code) is not None
92 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_sha3.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo():
12 | x: bytes32 = sha3(3)
13 | """
14 | ]
15 |
16 |
17 | @pytest.mark.parametrize('bad_code', fail_list)
18 | def test_block_fail(bad_code):
19 | with raises(TypeMismatchException):
20 | compiler.compile(bad_code)
21 |
22 |
23 | valid_list = [
24 | """
25 | @public
26 | def foo():
27 | x: bytes32 = sha3("moose")
28 | """,
29 | """
30 | @public
31 | def foo():
32 | x: bytes32 = sha3(0x1234567890123456789012345678901234567890123456789012345678901234)
33 | """
34 | ]
35 |
36 |
37 | @pytest.mark.parametrize('good_code', valid_list)
38 | def test_block_success(good_code):
39 | assert compiler.compile(good_code) is not None
40 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_slice.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 |
8 | fail_list = [
9 | """
10 | @public
11 | def foo(inp: bytes[10]) -> bytes[2]:
12 | return slice(inp, start=2, len=3)
13 | """,
14 | """
15 | @public
16 | def foo(inp: int128) -> bytes[3]:
17 | return slice(inp, start=2, len=3)
18 | """,
19 | """
20 | @public
21 | def foo(inp: bytes[10]) -> bytes[3]:
22 | return slice(inp, start=4.0, len=3)
23 | """
24 | ]
25 |
26 |
27 | @pytest.mark.parametrize('bad_code', fail_list)
28 | def test_slice_fail(bad_code):
29 |
30 | with raises(TypeMismatchException):
31 | compiler.compile(bad_code)
32 |
33 |
34 | valid_list = [
35 | """
36 | @public
37 | def foo(inp: bytes[10]) -> bytes[3]:
38 | return slice(inp, start=2, len=3)
39 | """,
40 | """
41 | @public
42 | def foo(inp: bytes[10]) -> bytes[4]:
43 | return slice(inp, start=2, len=3)
44 | """,
45 | """
46 | @public
47 | def foo() -> bytes[10]:
48 | return slice("badmintonzzz", start=1, len=10)
49 | """
50 | ]
51 |
52 |
53 | @pytest.mark.parametrize('good_code', valid_list)
54 | def test_slice_success(good_code):
55 | assert compiler.compile(good_code) is not None
56 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_tuple_assign.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import (
6 | VariableDeclarationException,
7 | TypeMismatchException
8 | )
9 |
10 | fail_list = [
11 | ("""
12 | @public
13 | def test():
14 | a: int128
15 | b: int128
16 | c: int128
17 | a, b, c = 1, 2, 3
18 | """, VariableDeclarationException),
19 | """
20 | @public
21 | def out_literals() -> (int128, int128, bytes[10]):
22 | return 1, 2, "3333"
23 |
24 | @public
25 | def test() -> (int128, address, bytes[10]):
26 | a: int128
27 | b: int128
28 | a, b, b = self.out_literals() # incorrect bytes type
29 | return a, b, c
30 | """,
31 | """
32 | @public
33 | def out_literals() -> (int128, int128, bytes[10]):
34 | return 1, 2, "3333"
35 |
36 | @public
37 | def test() -> (int128, address, bytes[10]):
38 | a: int128
39 | b: address
40 | a, b = self.out_literals() # tuple count mismatch
41 | return
42 | """,
43 | """
44 | @public
45 | def out_literals() -> (int128, int128, int128):
46 | return 1, 2, 3
47 |
48 | @public
49 | def test() -> (int128, int128, bytes[10]):
50 | a: int128
51 | b: int128
52 | c: bytes[10]
53 | a, b, c = self.out_literals()
54 | return a, b, c
55 | """,
56 | """
57 | @public
58 | def out_literals() -> (int128, int128, bytes[100]):
59 | return 1, 2, "test"
60 |
61 | @public
62 | def test():
63 | a: int128
64 | b: int128
65 | c: bytes[1]
66 | a, b, c = self.out_literals()
67 | """,
68 | ]
69 |
70 |
71 | @pytest.mark.parametrize('bad_code', fail_list)
72 | def test_tuple_assign_fail(bad_code):
73 | if isinstance(bad_code, tuple):
74 | with raises(bad_code[1]):
75 | compiler.compile(bad_code[0])
76 | else:
77 | with raises(TypeMismatchException):
78 | compiler.compile(bad_code)
79 |
--------------------------------------------------------------------------------
/tests/parser/syntax/test_unit_exponents.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import TypeMismatchException
6 |
7 | fail_list = [
8 | """
9 | @public
10 | def baa() -> decimal:
11 | return 2.0 ** 2
12 | """,
13 | """
14 | @public
15 | def foo(a: int128):
16 | b:int128(sec)
17 | c:int128(sec**2)
18 | c = b ** a
19 | """
20 | ]
21 |
22 |
23 | @pytest.mark.parametrize('bad_code', fail_list)
24 | def test_exponent_fail(bad_code):
25 |
26 | with raises(TypeMismatchException):
27 | compiler.compile(bad_code)
28 |
29 |
30 | valid_list = [
31 | """
32 | @public
33 | def foo():
34 | a : int128(wei)
35 | b : int128(wei**2)
36 | a = 2
37 | b = a**2
38 | """,
39 | ]
40 |
41 |
42 | @pytest.mark.parametrize('good_code', valid_list)
43 | def test_exponent_success(good_code):
44 | assert compiler.compile(good_code) is not None
45 |
--------------------------------------------------------------------------------
/tests/parser/syntax/utils/test_event_names.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import EventDeclarationException
6 |
7 | fail_list = [
8 | """
9 | Âssign: event({variable: int128})
10 |
11 | @public
12 | def foo(i: int128) -> int128:
13 | temp_var : int128 = i
14 | log.Âssign(temp_var)
15 | return temp_var
16 | """,
17 | """
18 | int128: event({variable: int128})
19 |
20 | @public
21 | def foo(i: int128) -> int128:
22 | temp_var : int128 = i
23 | log.int128(temp_var)
24 | return temp_var
25 | """,
26 | """
27 | decimal: event({variable: int128})
28 |
29 | @public
30 | def foo(i: int128) -> int128:
31 | temp_var : int128 = i
32 | log.decimal(temp_var)
33 | return temp_var
34 | """,
35 | """
36 | wei: event({variable: int128})
37 |
38 | @public
39 | def foo(i: int128) -> int128:
40 | temp_var : int128 = i
41 | log.wei(temp_var)
42 | return temp_var
43 | """,
44 | """
45 | false: event({variable: int128})
46 |
47 | @public
48 | def foo(i: int128) -> int128:
49 | temp_var : int128 = i
50 | log.false(temp_var)
51 | return temp_var
52 | """,
53 | ]
54 |
55 |
56 | @pytest.mark.parametrize('bad_code', fail_list)
57 | def test_varname_validity_fail(bad_code):
58 | with raises(EventDeclarationException):
59 | compiler.compile(bad_code)
60 |
61 |
62 | valid_list = [
63 | """
64 | Assigned: event({variable: int128})
65 |
66 | @public
67 | def foo(i: int128) -> int128:
68 | variable : int128 = i
69 | log.Assigned(variable)
70 | return variable
71 | """,
72 | """
73 | _Assign: event({variable: int128})
74 |
75 | @public
76 | def foo(i: int128) -> int128:
77 | variable : int128 = i
78 | log._Assign(variable)
79 | return variable
80 | """,
81 | """
82 | Assigned1: event({variable: int128})
83 |
84 | @public
85 | def foo(i: int128) -> int128:
86 | variable : int128 = i
87 | log.Assigned1(variable)
88 | return variable
89 | """,
90 | ]
91 |
92 |
93 | @pytest.mark.parametrize('good_code', valid_list)
94 | def test_varname_validity_success(good_code):
95 | assert compiler.compile(good_code) is not None
96 |
--------------------------------------------------------------------------------
/tests/parser/syntax/utils/test_function_names.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import FunctionDeclarationException
6 |
7 | fail_list = [
8 | """
9 | @public
10 | def ő1qwerty(i: int128) -> int128:
11 | temp_var : int128 = i
12 | return temp_var
13 | """,
14 | """
15 | @public
16 | def int128(i: int128) -> int128:
17 | temp_var : int128 = i
18 | return temp_var
19 | """,
20 | """
21 | @public
22 | def decimal(i: int128) -> int128:
23 | temp_var : int128 = i
24 | return temp_var
25 | """,
26 | """
27 | @public
28 | def wei(i: int128) -> int128:
29 | temp_var : int128 = i
30 | return temp_var
31 | """,
32 | """
33 | @public
34 | def false(i: int128) -> int128:
35 | temp_var : int128 = i
36 | return temp_var
37 | """,
38 | ]
39 |
40 |
41 | @pytest.mark.parametrize('bad_code', fail_list)
42 | def test_varname_validity_fail(bad_code):
43 | with raises(FunctionDeclarationException):
44 | compiler.compile(bad_code)
45 |
46 |
47 | valid_list = [
48 | """
49 | @public
50 | def func(i: int128) -> int128:
51 | variable : int128 = i
52 | return variable
53 | """,
54 | """
55 | @public
56 | def func_to_do_math(i: int128) -> int128:
57 | var_123 : int128 = i
58 | return var_123
59 | """,
60 | """
61 | @public
62 | def first1(i: int128) -> int128:
63 | _var123 : int128 = i
64 | return _var123
65 | """,
66 | ]
67 |
68 |
69 | @pytest.mark.parametrize('good_code', valid_list)
70 | def test_varname_validity_success(good_code):
71 | assert compiler.compile(good_code) is not None
72 |
--------------------------------------------------------------------------------
/tests/parser/syntax/utils/test_variable_names.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import VariableDeclarationException
6 |
7 | fail_list = [
8 | """
9 | @public
10 | def foo(i: int128) -> int128:
11 | varő : int128 = i
12 | return varő
13 | """,
14 | """
15 | @public
16 | def foo(i: int128) -> int128:
17 | int128 : int128 = i
18 | return int128
19 | """,
20 | """
21 | @public
22 | def foo(i: int128) -> int128:
23 | decimal : int128 = i
24 | return decimal
25 | """,
26 | """
27 | @public
28 | def foo(i: int128) -> int128:
29 | wei : int128 = i
30 | return wei
31 | """,
32 | """
33 | @public
34 | def foo(i: int128) -> int128:
35 | false : int128 = i
36 | return false
37 | """,
38 | ]
39 |
40 |
41 | @pytest.mark.parametrize('bad_code', fail_list)
42 | def test_varname_validity_fail(bad_code):
43 | with raises(VariableDeclarationException):
44 | compiler.compile(bad_code)
45 |
46 |
47 | valid_list = [
48 | """
49 | @public
50 | def foo(i: int128) -> int128:
51 | variable : int128 = i
52 | return variable
53 | """,
54 | """
55 | @public
56 | def foo(i: int128) -> int128:
57 | var_123 : int128 = i
58 | return var_123
59 | """,
60 | """
61 | @public
62 | def foo(i: int128) -> int128:
63 | _var123 : int128 = i
64 | return _var123
65 | """,
66 | ]
67 |
68 |
69 | @pytest.mark.parametrize('good_code', valid_list)
70 | def test_varname_validity_success(good_code):
71 | assert compiler.compile(good_code) is not None
72 |
--------------------------------------------------------------------------------
/tests/parser/types/numbers/test_custom_units.py:
--------------------------------------------------------------------------------
1 | from decimal import Decimal
2 |
3 |
4 | def test_custom_units(get_contract_with_gas_estimation):
5 | code = """
6 | units: {
7 | cm: "centimeter",
8 | km: "kilometer"
9 | }
10 |
11 | # global storage
12 | a: int128(cm)
13 |
14 |
15 | @public
16 | def test() -> int128(km):
17 | b: int128(km)
18 | b = 100
19 | return b
20 | """
21 |
22 | c = get_contract_with_gas_estimation(code)
23 |
24 | assert c.test() == 100
25 |
26 |
27 | def test_custom_units_struct(get_contract_with_gas_estimation):
28 | code = """
29 | units: {
30 | cm: "centimer"
31 | }
32 |
33 | astruct: {
34 | value1: int128(cm)
35 | }
36 |
37 | @public
38 | def test() -> int128(cm):
39 | self.astruct.value1 = 101
40 | return self.astruct.value1
41 | """
42 |
43 | c = get_contract_with_gas_estimation(code)
44 |
45 | assert c.test() == 101
46 |
47 |
48 | def test_custom_units_public(get_contract_with_gas_estimation):
49 | code = """
50 | units: {
51 | mm: "millimeter"
52 | }
53 |
54 | a: int128(mm)
55 | b: public(int128(mm))
56 |
57 |
58 | @public
59 | def test() -> int128(mm):
60 | self.a = 111
61 | return self.a
62 | """
63 |
64 | c = get_contract_with_gas_estimation(code)
65 |
66 | assert c.test() == 111
67 |
68 |
69 | def test_custom_units_events_and_func(get_contract_with_gas_estimation):
70 | code = """
71 | units: {
72 | stock: "how much stock there is",
73 | token: "amount of token"
74 | }
75 |
76 |
77 | Transfer: event({_from: indexed(address), _to: indexed(address), _value: uint256(stock)})
78 |
79 | @public
80 | def initiate(token_addr: address, token_quantity: uint256(token)):
81 | pass
82 | """
83 |
84 | assert get_contract_with_gas_estimation(code)
85 |
86 |
87 | def test_ms(get_contract_with_gas_estimation):
88 | code = """
89 | units: {
90 | m: "Meter",
91 | s: "Second"
92 | }
93 |
94 |
95 | @public
96 | def velocity(d: decimal(m), t: decimal(s)) -> decimal(m/s):
97 | return d / t
98 | """
99 | c = get_contract_with_gas_estimation(code)
100 |
101 | assert c.velocity(15, 10) == Decimal('1.5')
102 | assert c.velocity(12, 4) == Decimal('3')
103 |
--------------------------------------------------------------------------------
/tests/parser/types/test_node_types.py:
--------------------------------------------------------------------------------
1 | from pytest import raises
2 |
3 | from vyper.types import (
4 | BaseType,
5 | ByteArrayType,
6 | ListType,
7 | MappingType,
8 | NullType,
9 | StructType,
10 | TupleType,
11 | canonicalize_type,
12 | get_size_of_type,
13 | )
14 |
15 |
16 | def test_null_type():
17 | node1 = NullType()
18 | node2 = NullType()
19 |
20 | assert node1 == node2
21 |
22 |
23 | def test_bytearray_node_type():
24 |
25 | node1 = ByteArrayType(12)
26 | node2 = ByteArrayType(12)
27 |
28 | assert node1 == node2
29 |
30 | node3 = ByteArrayType(13)
31 | node4 = BaseType('int128')
32 |
33 | assert node1 != node3
34 | assert node1 != node4
35 |
36 |
37 | def test_mapping_node_types():
38 |
39 | with raises(Exception):
40 | MappingType(int, int)
41 |
42 | node1 = MappingType(BaseType('int128'), BaseType('int128'))
43 | node2 = MappingType(BaseType('int128'), BaseType('int128'))
44 | assert node1 == node2
45 | assert str(node1) == "int128[int128]"
46 |
47 |
48 | def test_tuple_node_types():
49 | node1 = TupleType([BaseType('int128'), BaseType('decimal')])
50 | node2 = TupleType([BaseType('int128'), BaseType('decimal')])
51 |
52 | assert node1 == node2
53 | assert str(node1) == "(int128, decimal)"
54 |
55 |
56 | def test_canonicalize_type():
57 | # Non-basetype not allowed
58 | with raises(Exception):
59 | canonicalize_type(int)
60 | # List of byte arrays not allowed
61 | a = ListType(ByteArrayType(12), 2)
62 | with raises(Exception):
63 | canonicalize_type(a)
64 | # Test ABI format of multiple args.
65 | c = TupleType([BaseType('int128'), BaseType('address')])
66 | assert canonicalize_type(c) == "(int128,address)"
67 |
68 |
69 | def test_get_size_of_type():
70 | assert get_size_of_type(BaseType('int128')) == 1
71 | assert get_size_of_type(ByteArrayType(12)) == 3
72 | assert get_size_of_type(ByteArrayType(33)) == 4
73 | assert get_size_of_type(ListType(BaseType('int128'), 10)) == 10
74 |
75 | _tuple = TupleType([BaseType('int128'), BaseType('decimal')])
76 | assert get_size_of_type(_tuple) == 2
77 |
78 | _struct = StructType({
79 | 'a': BaseType('int128'),
80 | 'b': BaseType('decimal')
81 | })
82 | assert get_size_of_type(_struct) == 2
83 |
84 | # Don't allow unknow types.
85 | with raises(Exception):
86 | get_size_of_type(int)
87 |
88 | # Maps are not supported for function arguments or outputs
89 | with raises(Exception):
90 | get_size_of_type(MappingType(BaseType('int128'), BaseType('int128')))
91 |
--------------------------------------------------------------------------------
/tests/parser/types/test_string_literal.py:
--------------------------------------------------------------------------------
1 | def test_string_literal_code(get_contract_with_gas_estimation):
2 | string_literal_code = """
3 | @public
4 | def foo() -> bytes[5]:
5 | return "horse"
6 |
7 | @public
8 | def bar() -> bytes[10]:
9 | return concat("b", "a", "d", "m", "i", "", "nton")
10 |
11 | @public
12 | def baz() -> bytes[40]:
13 | return concat("0123456789012345678901234567890", "12")
14 |
15 | @public
16 | def baz2() -> bytes[40]:
17 | return concat("01234567890123456789012345678901", "12")
18 |
19 | @public
20 | def baz3() -> bytes[40]:
21 | return concat("0123456789012345678901234567890", "1")
22 |
23 | @public
24 | def baz4() -> bytes[100]:
25 | return concat("01234567890123456789012345678901234567890123456789",
26 | "01234567890123456789012345678901234567890123456789")
27 | """
28 |
29 | c = get_contract_with_gas_estimation(string_literal_code)
30 | assert c.foo() == b"horse"
31 | assert c.bar() == b"badminton"
32 | assert c.baz() == b"012345678901234567890123456789012"
33 | assert c.baz2() == b"0123456789012345678901234567890112"
34 | assert c.baz3() == b"01234567890123456789012345678901"
35 | assert c.baz4() == b"0123456789" * 10
36 |
37 | print("Passed string literal test")
38 |
39 |
40 | def test_string_literal_splicing_fuzz(get_contract_with_gas_estimation):
41 | for i in range(95, 96, 97):
42 | kode = """
43 | moo: bytes[100]
44 |
45 | @public
46 | def foo(s: int128, L: int128) -> bytes[100]:
47 | x: int128 = 27
48 | r: bytes[100] = slice("%s", start=s, len=L)
49 | y: int128 = 37
50 | if x * y == 999:
51 | return r
52 |
53 | @public
54 | def bar(s: int128, L: int128) -> bytes[100]:
55 | self.moo = "%s"
56 | x: int128 = 27
57 | r: bytes[100] = slice(self.moo, start=s, len=L)
58 | y: int128 = 37
59 | if x * y == 999:
60 | return r
61 |
62 | @public
63 | def baz(s: int128, L: int128) -> bytes[100]:
64 | x: int128 = 27
65 | self.moo = slice("%s", start=s, len=L)
66 | y: int128 = 37
67 | if x * y == 999:
68 | return self.moo
69 | """ % (("c" * i), ("c" * i), ("c" * i))
70 |
71 | c = get_contract_with_gas_estimation(kode)
72 | for e in range(63, 64, 65):
73 | for _s in range(31, 32, 33):
74 | o1 = c.foo(_s, e - _s)
75 | o2 = c.bar(_s, e - _s)
76 | o3 = c.baz(_s, e - _s)
77 | assert o1 == o2 == o3 == b"c" * (e - _s), (i, _s, e - _s, o1, o2, o3)
78 |
79 | print("Passed string literal splicing fuzz-test")
80 |
--------------------------------------------------------------------------------
/tests/parser/types/test_variable_naming.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from pytest import raises
3 |
4 | from vyper import compiler
5 | from vyper.exceptions import FunctionDeclarationException
6 |
7 | fail_list = [
8 | """
9 | @public
10 | def foo(max: int128) -> int128:
11 | return max
12 | """,
13 | """
14 | @public
15 | def foo(len: int128, sha3: int128) -> int128:
16 | return len+sha3
17 | """
18 | ]
19 |
20 |
21 | @pytest.mark.parametrize('bad_code', fail_list)
22 | def test_variable_naming_fail(bad_code):
23 |
24 | with raises(FunctionDeclarationException):
25 | compiler.compile(bad_code)
26 |
--------------------------------------------------------------------------------
/tests/parser/types/value/test_as_wei_value.py:
--------------------------------------------------------------------------------
1 | def test_test_wei(get_contract_with_gas_estimation):
2 | test_wei = """
3 | @public
4 | def return_2_finney() -> wei_value:
5 | return as_wei_value(2, "finney")
6 |
7 | @public
8 | def return_3_finney() -> wei_value:
9 | return as_wei_value(2 + 1, "finney")
10 |
11 | @public
12 | def return_2p5_ether() -> wei_value:
13 | return as_wei_value(2.5, "ether")
14 |
15 | @public
16 | def return_3p5_ether() -> wei_value:
17 | return as_wei_value(2.5 + 1.0, "ether")
18 |
19 | @public
20 | def return_2pow64_wei() -> wei_value:
21 | return as_wei_value(18446744.073709551616, "szabo")
22 | """
23 |
24 | c = get_contract_with_gas_estimation(test_wei)
25 |
26 | assert c.return_2_finney() == 2 * 10**15
27 | assert c.return_3_finney() == 3 * 10**15, c.return_3_finney()
28 | assert c.return_2p5_ether() == 2.5 * 10**18
29 | assert c.return_3p5_ether() == 3.5 * 10**18
30 | assert c.return_2pow64_wei() == 2**64
31 |
32 | print("Passed wei value literals test")
33 |
--------------------------------------------------------------------------------
/vyper/__init__.py:
--------------------------------------------------------------------------------
1 | import sys as _sys
2 | import pkg_resources as _pkg_resources
3 |
4 |
5 | if (_sys.version_info.major, _sys.version_info.minor) < (3, 6):
6 | # Can't be tested, as our test harness is using python3.6.
7 | raise Exception("Requires python3.6+") # pragma: no cover
8 |
9 |
10 | try:
11 | __version__ = _pkg_resources.get_distribution('vyper').version
12 | except _pkg_resources.DistributionNotFound:
13 | __version__ = '0.0.0development'
14 |
--------------------------------------------------------------------------------
/vyper/compiler.py:
--------------------------------------------------------------------------------
1 | from vyper.parser import parser
2 | from vyper import compile_lll
3 | from vyper import optimizer
4 |
5 |
6 | def compile(code, *args, **kwargs):
7 | lll = optimizer.optimize(parser.parse_tree_to_lll(parser.parse(code), code, runtime_only=kwargs.get('bytecode_runtime', False)))
8 | asm = compile_lll.compile_to_assembly(lll)
9 |
10 | def find_nested_opcode(asm_list, key):
11 | if key in asm_list:
12 | return True
13 | else:
14 | sublists = [sub for sub in asm_list if isinstance(sub, list)]
15 | return any([find_nested_opcode(x, key) for x in sublists])
16 |
17 | if find_nested_opcode(asm, 'DEBUG'):
18 | print('Please note this code contains DEBUG opcode.')
19 | print('This will only work in a support EVM. This FAIL on any other nodes.')
20 |
21 | c, line_number_map = compile_lll.assembly_to_evm(asm)
22 | return c
23 |
24 |
25 | def gas_estimate(origcode, *args, **kwargs):
26 | o = {}
27 | code = optimizer.optimize(parser.parse_to_lll(origcode))
28 |
29 | # Extract the stuff inside the LLL bracket
30 | if code.value == 'seq':
31 | if len(code.args) > 0 and code.args[-1].value == 'return':
32 | code = code.args[-1].args[1].args[0]
33 |
34 | assert code.value == 'seq'
35 | for arg in code.args:
36 | if hasattr(arg, 'func_name'):
37 | o[arg.func_name] = arg.total_gas
38 | return o
39 |
40 |
41 | def mk_full_signature(code, *args, **kwargs):
42 | abi = parser.mk_full_signature(parser.parse(code))
43 | # Add gas estimates for each function to ABI
44 | gas_estimates = gas_estimate(code)
45 | for idx, func in enumerate(abi):
46 | func_name = func['name'].split('(')[0]
47 | # Skip __init__, has no estimate
48 | if func_name in gas_estimates and func_name != '__init__':
49 | abi[idx]['gas'] = gas_estimates[func_name]
50 | return abi
51 |
--------------------------------------------------------------------------------
/vyper/exceptions.py:
--------------------------------------------------------------------------------
1 | # Attempts to display the line and column of violating code.
2 | class ParserException(Exception):
3 | def __init__(self, message='Error Message not found.', item=None):
4 | self.message = message
5 | self.lineno = None
6 | self.col_offset = None
7 |
8 | if isinstance(item, tuple): # is a position.
9 | self.lineno, self.col_offset = item
10 | elif item and hasattr(item, 'lineno'):
11 | self.set_err_pos(item.lineno, item.col_offset)
12 | if hasattr(item, 'source_code'):
13 | self.source_code = item.source_code.splitlines()
14 |
15 | def set_err_pos(self, lineno, col_offset):
16 | if not self.lineno:
17 | self.lineno = lineno
18 |
19 | if not self.col_offset:
20 | self.col_offset = col_offset
21 |
22 | def __str__(self):
23 | output = self.message
24 |
25 | if self.lineno and hasattr(self, 'source_code'):
26 |
27 | output = 'line %d: %s\n%s' % (
28 | self.lineno,
29 | output,
30 | self.source_code[self.lineno - 1]
31 | )
32 |
33 | if self.col_offset:
34 | col = '-' * self.col_offset + '^'
35 | output += '\n' + col
36 |
37 | elif self.lineno is not None and self.col_offset is not None:
38 | output = 'line %d:%d %s' % (
39 | self.lineno,
40 | self.col_offset,
41 | output
42 | )
43 |
44 | return output
45 |
46 |
47 | class VariableDeclarationException(ParserException):
48 | pass
49 |
50 |
51 | class StructureException(ParserException):
52 | pass
53 |
54 |
55 | class ConstancyViolationException(ParserException):
56 | pass
57 |
58 |
59 | class NonPayableViolationException(ParserException):
60 | pass
61 |
62 |
63 | class InvalidLiteralException(ParserException):
64 | pass
65 |
66 |
67 | class InvalidTypeException(ParserException):
68 | pass
69 |
70 |
71 | class TypeMismatchException(ParserException):
72 | pass
73 |
74 |
75 | class FunctionDeclarationException(ParserException):
76 | pass
77 |
78 |
79 | class EventDeclarationException(ParserException):
80 | pass
81 |
--------------------------------------------------------------------------------
/vyper/functions/__init__.py:
--------------------------------------------------------------------------------
1 | from .functions import * # noqa: F401,F403
2 |
--------------------------------------------------------------------------------
/vyper/parser/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/vyper/parser/__init__.py
--------------------------------------------------------------------------------
/vyper/parser/pre_parser.py:
--------------------------------------------------------------------------------
1 | import io
2 | import re
3 | from tokenize import (
4 | COMMENT,
5 | NAME,
6 | OP,
7 | TokenError,
8 | TokenInfo,
9 | tokenize,
10 | untokenize,
11 | )
12 | from vyper.exceptions import StructureException
13 | from vyper import __version__
14 |
15 |
16 | def _parser_version_str(version_str):
17 | version_regex = re.compile(r'^(\d+\.)?(\d+\.)?(\w*)$')
18 | if None in version_regex.match(version_str).groups():
19 | raise Exception('Could not parse given version: %s' % version_str)
20 | return version_regex.match(version_str).groups()
21 |
22 |
23 | # Do a version check.
24 | def parse_version_pragma(version_str):
25 | version_arr = version_str.split('@version')
26 |
27 | file_version = version_arr[1].strip()
28 | file_major, file_minor, file_patch = _parser_version_str(file_version)
29 | compiler_major, compiler_minor, compiler_patch = _parser_version_str(__version__)
30 |
31 | if (file_major, file_minor) != (compiler_major, compiler_minor):
32 | raise Exception('Given version "{}" is not compatible with the compiler ({}): '.format(
33 | file_version, __version__
34 | ))
35 |
36 |
37 | # Minor pre-parser checks.
38 | def pre_parse(code):
39 | result = []
40 |
41 | try:
42 | g = tokenize(io.BytesIO(code.encode('utf-8')).readline)
43 | for token in g:
44 | # Alias contract definition to class definition.
45 | if token.type == COMMENT and "@version" in token.string:
46 | parse_version_pragma(token.string[1:])
47 | if (token.type, token.string, token.start[1]) == (NAME, "contract", 0):
48 | token = TokenInfo(token.type, "class", token.start, token.end, token.line)
49 | # Prevent semi-colon line statements.
50 | elif (token.type, token.string) == (OP, ";"):
51 | raise StructureException("Semi-colon statements not allowed.", token.start)
52 |
53 | result.append(token)
54 | except TokenError as e:
55 | raise StructureException(e.args[0], e.args[1]) from e
56 |
57 | return untokenize(result).decode('utf-8')
58 |
--------------------------------------------------------------------------------
/vyper/parser/s_expressions.py:
--------------------------------------------------------------------------------
1 | # Adapted from https://en.wikipedia.org/wiki/S-expression#Parsing
2 |
3 |
4 | def parse_literal(word):
5 | try:
6 | return int(word)
7 | except ValueError:
8 | return word
9 |
10 |
11 | def parse_s_exp(string):
12 | sexp = [[]]
13 | word = ''
14 | in_str = False
15 | in_comment = False
16 | for char in string:
17 | if in_comment:
18 | if char is '\n': # comment ends at the end of a line
19 | in_comment = False
20 | continue
21 | if char is ';': # start of comment
22 | in_comment = True
23 | continue
24 | if char is '(' and not in_str:
25 | sexp.append([])
26 | elif char is ')' and not in_str:
27 | if word:
28 | sexp[-1].append(parse_literal(word))
29 | word = ''
30 | temp = sexp.pop()
31 | sexp[-1].append(temp)
32 | elif char in (' ', '\n', '\t') and not in_str:
33 | if word:
34 | sexp[-1].append(parse_literal(word))
35 | word = ''
36 | elif char is '\"':
37 | in_str = not in_str
38 | else:
39 | word += char
40 | return sexp[0]
41 |
--------------------------------------------------------------------------------
/vyper/premade_contracts.py:
--------------------------------------------------------------------------------
1 | import ast
2 |
3 | erc20 = """
4 | class ERC20():
5 | def name() -> bytes32: constant
6 | def symbol() -> bytes32: constant
7 | def decimals() -> uint256: constant
8 | def balanceOf(_owner: address) -> uint256: constant
9 | def totalSupply() -> uint256: constant
10 | def transfer(_to: address, _amount: uint256) -> bool: modifying
11 | def transferFrom(_from: address, _to: address, _value: uint256) -> bool: modifying
12 | def approve(_spender: address, _amount: uint256) -> bool: modifying
13 | def allowance(_owner: address, _spender: address) -> uint256: modifying
14 | """
15 |
16 |
17 | def prepare_code(code):
18 | return ast.parse(code).body[0]
19 |
20 |
21 | premade_contracts = {
22 | "ERC20": prepare_code(erc20)
23 | }
24 |
--------------------------------------------------------------------------------
/vyper/server.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/vyper/server.py
--------------------------------------------------------------------------------
/vyper/signatures/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDouble/vyper/c756c02f41d8c12ee5fef49c691e25d46ee35550/vyper/signatures/__init__.py
--------------------------------------------------------------------------------
/vyper/types/__init__.py:
--------------------------------------------------------------------------------
1 | from .types import * # noqa F401, F403
2 |
--------------------------------------------------------------------------------