Skip to content

Commit

Permalink
Merge branch 'master' into fix/copy-bytes-perf
Browse files Browse the repository at this point in the history
  • Loading branch information
charles-cooper authored Jan 5, 2025
2 parents 7a8b147 + 4507d2a commit d0e2eca
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 60 deletions.
23 changes: 20 additions & 3 deletions docs/compiling-a-contract.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Online Compilers
Try VyperLang!
-----------------

`Try VyperLang! <https://try.vyperlang.org>`_ is a JupterHub instance hosted by the Vyper team as a sandbox for developing and testing contracts in Vyper. It requires github for login, and supports deployment via the browser.
`Try VyperLang! <https://try.vyperlang.org>`_ is a JupyterHub instance hosted by the Vyper team as a sandbox for developing and testing contracts in Vyper. It requires github for login, and supports deployment via the browser.

Remix IDE
---------
Expand Down Expand Up @@ -203,7 +203,7 @@ The following is a list of supported EVM versions, and changes in the compiler i
Integrity Hash
==============

To help tooling detect whether two builds are the same, Vyper provides the ``-f integrity`` output, which outputs the integrity hash of a contract. The integrity hash is recursively defined as the sha256 of the source code with the integrity hashes of its dependencies (imports).
To help tooling detect whether two builds are the same, Vyper provides the ``-f integrity`` output, which outputs the integrity hash of a contract. The integrity hash is recursively defined as the sha256 of the source code with the integrity hashes of its dependencies (imports) and storage layout overrides (if provided).

.. _vyper-archives:

Expand All @@ -219,15 +219,17 @@ A Vyper archive is a compileable bundle of input sources and settings. Technical
├── compilation_targets
├── compiler_version
├── integrity
├── settings.json
├── searchpaths
└── settings.json
└── storage_layout.json [OPTIONAL]

* ``cli_settings.txt`` is a text representation of the settings that were used on the compilation run that generated this archive.
* ``compilation_targets`` is a newline separated list of compilation targets. Currently only one compilation is supported
* ``compiler_version`` is a text representation of the compiler version used to generate this archive
* ``integrity`` is the :ref:`integrity hash <integrity-hash>` of the input contract
* ``searchpaths`` is a newline-separated list of the search paths used on this compilation run
* ``settings.json`` is a json representation of the settings used on this compilation run. It is 1:1 with ``cli_settings.txt``, but both are provided as they are convenient for different workflows (typically, manually vs automated).
* ``storage_layout.json`` is a json representation of the storage layout overrides to be used on this compilation run. It is optional.

A Vyper archive file can be produced by requesting the ``-f archive`` output format. The compiler can also produce the archive in base64 encoded form using the ``--base64`` flag. The Vyper compiler can accept both ``.vyz`` and base64-encoded Vyper archives directly as input.

Expand Down Expand Up @@ -281,6 +283,14 @@ The following example describes the expected input format of ``vyper-json``. (Co
}
},
// Optional
// Storage layout overrides for the contracts that are compiled
"storage_layout_overrides": {
"contracts/foo.vy": {
"a": {"type": "uint256", "slot": 1, "n_slots": 1},
"b": {"type": "uint256", "slot": 0, "n_slots": 1},
}
},
// Optional
"settings": {
"evmVersion": "cancun", // EVM version to compile for. Can be london, paris, shanghai or cancun (default).
// optional, optimization mode
Expand Down Expand Up @@ -364,6 +374,13 @@ The following example describes the output format of ``vyper-json``. Comments ar
"formattedMessage": "line 5:11 Unsupported type conversion: int128 to bool"
}
],
// Optional: not present if there are no storage layout overrides
"storage_layout_overrides": {
"contracts/foo.vy": {
"a": {"type": "uint256", "slot": 1, "n_slots": 1},
"b": {"type": "uint256", "slot": 0, "n_slots": 1},
}
},
// This contains the file-level outputs. Can be limited/filtered by the outputSelection settings.
"sources": {
"source_file.vy": {
Expand Down
9 changes: 6 additions & 3 deletions tests/functional/syntax/test_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ def foo():
)

file_input = input_bundle.load_file("top.vy")
with pytest.raises(ModuleNotFound):
with pytest.raises(ModuleNotFound) as e:
compiler.compile_from_file_input(file_input, input_bundle=input_bundle)
assert "lib0.vy:" in str(e.value)


def test_implicitly_relative_import_crashes_2(make_input_bundle):
Expand All @@ -44,8 +45,9 @@ def foo():
)

file_input = input_bundle.load_file("top.vy")
with pytest.raises(ModuleNotFound):
with pytest.raises(ModuleNotFound) as e:
compiler.compile_from_file_input(file_input, input_bundle=input_bundle)
assert "lib0.vy:" in str(e.value)


def test_relative_import_searches_only_current_path(make_input_bundle):
Expand All @@ -70,8 +72,9 @@ def foo():
input_bundle = make_input_bundle({"top.vy": top, "a.vy": a, "subdir/b.vy": b})
file_input = input_bundle.load_file("top.vy")

with pytest.raises(ModuleNotFound):
with pytest.raises(ModuleNotFound) as e:
compiler.compile_from_file_input(file_input, input_bundle=input_bundle)
assert "b.vy:" in str(e.value)


def test_absolute_import_within_relative_import(make_input_bundle):
Expand Down
15 changes: 10 additions & 5 deletions tests/functional/syntax/test_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,26 +411,31 @@ def foobar():
assert compiler.compile_code(code, input_bundle=input_bundle) is not None


def test_builtins_not_found():
def test_builtins_not_found(make_input_bundle):
code = """
from vyper.interfaces import foobar
"""
input_bundle = make_input_bundle({"code.vy": code})
file_input = input_bundle.load_file("code.vy")
with pytest.raises(ModuleNotFound) as e:
compiler.compile_code(code)

compiler.compile_from_file_input(file_input, input_bundle=input_bundle)
assert e.value._message == "vyper.interfaces.foobar"
assert e.value._hint == "try renaming `vyper.interfaces` to `ethereum.ercs`"
assert "code.vy:" in str(e.value)


@pytest.mark.parametrize("erc", ("ERC20", "ERC721", "ERC4626"))
def test_builtins_not_found2(erc):
def test_builtins_not_found2(erc, make_input_bundle):
code = f"""
from ethereum.ercs import {erc}
"""
input_bundle = make_input_bundle({"code.vy": code})
file_input = input_bundle.load_file("code.vy")
with pytest.raises(ModuleNotFound) as e:
compiler.compile_code(code)
compiler.compile_from_file_input(file_input, input_bundle=input_bundle)
assert e.value._message == f"ethereum.ercs.{erc}"
assert e.value._hint == f"try renaming `{erc}` to `I{erc}`"
assert "code.vy:" in str(e.value)


def test_interface_body_check(make_input_bundle):
Expand Down
28 changes: 27 additions & 1 deletion tests/unit/cli/storage_layout/test_storage_layout_overrides.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pytest

from vyper.cli.vyper_json import compile_json
from vyper.compiler import compile_code
from vyper.evm.opcodes import version_check
from vyper.exceptions import StorageLayoutException
Expand All @@ -13,7 +14,7 @@ def test_storage_layout_overrides():
b: uint256"""

storage_layout_overrides = {
"a": {"type": "uint256", "slot": 1, "n_slots": 1},
"a": {"type": "uint256", "slot": 5, "n_slots": 1},
"b": {"type": "uint256", "slot": 0, "n_slots": 1},
}

Expand All @@ -26,6 +27,31 @@ def test_storage_layout_overrides():
assert out["layout"] == expected_output


def test_storage_layout_overrides_json():
code = """
a: uint256
b: uint256"""

storage_layout_overrides = {
"a": {"type": "uint256", "slot": 5, "n_slots": 1},
"b": {"type": "uint256", "slot": 0, "n_slots": 1},
}

input_json = {
"language": "Vyper",
"sources": {"contracts/foo.vy": {"content": code}},
"storage_layout_overrides": {"contracts/foo.vy": storage_layout_overrides},
"settings": {"outputSelection": {"*": ["*"]}},
}

out = compile_code(
code, output_formats=["layout"], storage_layout_override=storage_layout_overrides
)
assert (
compile_json(input_json)["contracts"]["contracts/foo.vy"]["foo"]["layout"] == out["layout"]
)


def test_storage_layout_for_more_complex():
code = """
foo: HashMap[address, uint256]
Expand Down
Loading

0 comments on commit d0e2eca

Please sign in to comment.