Beispiel #1
0
def test_evm_versions(tmp_path):
    # should compile differently because of SELFBALANCE
    code = """
@public
def foo() -> uint256:
    return self.balance
"""

    bar_path = tmp_path.joinpath('bar.vy')
    with bar_path.open('w') as fp:
        fp.write(code)

    byzantium_bytecode = compile_files(
        [bar_path],
        output_formats=['bytecode'],
        evm_version="byzantium"
    )[str(bar_path)]['bytecode']
    istanbul_bytecode = compile_files(
        [bar_path],
        output_formats=['bytecode'],
        evm_version="istanbul"
    )[str(bar_path)]['bytecode']

    assert byzantium_bytecode != istanbul_bytecode

    # SELFBALANCE opcode is 0x47
    assert "47" not in byzantium_bytecode
    assert "47" in istanbul_bytecode
Beispiel #2
0
def test_import_parent_folder(tmp_path, assert_compile_failed):
    tmp_path.joinpath('contracts').mkdir()

    foo_path = tmp_path.joinpath('contracts/foo.vy')
    with foo_path.open('w') as fp:
        fp.write(FOO_CODE.format("from .. import Bar"))

    with tmp_path.joinpath('Bar.vy').open('w') as fp:
        fp.write(BAR_CODE)

    assert compile_files([foo_path], ['combined_json'], root_folder=tmp_path)
    # Cannot perform relative import outside of base folder
    with pytest.raises(FileNotFoundError):
        compile_files([foo_path], ['combined_json'], root_folder=tmp_path.joinpath('contracts'))
Beispiel #3
0
def test_local_namespace(tmp_path):
    # interface code namespaces should be isolated
    # all of these contract should be able to compile together
    codes = [
        "import foo as FooBar",
        "import bar as FooBar",
        "import foo as BarFoo",
        "import bar as BarFoo",
    ]
    struct_def = """
struct FooStruct:
    foo_: uint256

    """

    compile_paths = []
    for i, code in enumerate(codes):
        code += struct_def
        path = tmp_path.joinpath(f"code{i}.vy")
        with path.open("w") as fp:
            fp.write(code)
        compile_paths.append(path)

    for file_name in ("foo.vy", "bar.vy"):
        with tmp_path.joinpath(file_name).open("w") as fp:
            fp.write(BAR_CODE)

    assert compile_files(compile_paths, ["combined_json"], root_folder=tmp_path)
Beispiel #4
0
def test_derived_interface_imports(import_stmt_baz, import_stmt_foo, tmp_path):
    # contracts-as-interfaces should be able to contain import statements
    baz_code = """
{}

@public
def foo(a: address) -> uint256:
    return Foo(a).foo()

@public
def bar(_foo: address, _bar: address) -> uint256:
    return Foo(_foo).bar(_bar)
    """.format(import_stmt_baz)

    with tmp_path.joinpath('Foo.vy').open('w') as fp:
        fp.write(FOO_CODE.format(import_stmt_foo))

    with tmp_path.joinpath('Bar.vy').open('w') as fp:
        fp.write(BAR_CODE)

    baz_path = tmp_path.joinpath('Baz.vy')
    with baz_path.open('w') as fp:
        fp.write(baz_code)

    assert compile_files([baz_path], ['combined_json'], root_folder=tmp_path)
Beispiel #5
0
def test_derived_interface_imports(import_stmt_baz, import_stmt_foo, tmp_path):
    # contracts-as-interfaces should be able to contain import statements
    baz_code = f"""
{import_stmt_baz}

struct FooStruct:
    foo_: uint256

@external
def foo(a: address) -> FooStruct:
    return Foo(a).foo()

@external
def bar(_foo: address, _bar: address) -> FooStruct:
    return Foo(_foo).bar(_bar)
    """

    with tmp_path.joinpath("Foo.vy").open("w") as fp:
        fp.write(FOO_CODE.format(import_stmt_foo, "Bar"))

    with tmp_path.joinpath("Bar.vy").open("w") as fp:
        fp.write(BAR_CODE)

    baz_path = tmp_path.joinpath("Baz.vy")
    with baz_path.open("w") as fp:
        fp.write(baz_code)

    assert compile_files([baz_path], ["combined_json"], root_folder=tmp_path)
Beispiel #6
0
def create_contract(w3, path):
    wd = os.path.dirname(os.path.realpath(__file__))
    with open(os.path.join(wd, os.pardir, path)) as f:
        source = f.read()
    root_path = os.path.join(wd, os.pardir)
    source_path = os.path.join(root_path, path)
    out = compile_files([source_path], ['abi', 'bytecode'], root_path)[path]
    return w3.eth.contract(abi=out['abi'], bytecode=out['bytecode'])
Beispiel #7
0
def test_compile_outside_root_path(tmp_path):
    foo_path = tmp_path.joinpath('foo.vy')
    with foo_path.open('w') as fp:
        fp.write(FOO_CODE.format('import bar as Bar'))

    bar_path = tmp_path.joinpath('bar.vy')
    with bar_path.open('w') as fp:
        fp.write(BAR_CODE)

    assert compile_files([foo_path, bar_path], ['combined_json'], root_folder=".")
Beispiel #8
0
def test_compile_outside_root_path(tmp_path):
    foo_path = tmp_path.joinpath("foo.vy")
    with foo_path.open("w") as fp:
        fp.write(FOO_CODE.format("import bar as Bar", "Bar"))

    bar_path = tmp_path.joinpath("bar.vy")
    with bar_path.open("w") as fp:
        fp.write(BAR_CODE)

    assert compile_files([foo_path, bar_path], ["combined_json"], root_folder=".")
Beispiel #9
0
def test_import_same_folder(import_stmt, alias, tmp_path):
    tmp_path.joinpath("contracts").mkdir()

    foo_path = tmp_path.joinpath("contracts/foo.vy")
    with foo_path.open("w") as fp:
        fp.write(FOO_CODE.format(import_stmt, alias))

    with tmp_path.joinpath("contracts/Bar.vy").open("w") as fp:
        fp.write(BAR_CODE)

    assert compile_files([foo_path], ["combined_json"], root_folder=tmp_path)
Beispiel #10
0
def test_import_same_folder(import_stmt, tmp_path):
    tmp_path.joinpath('contracts').mkdir()

    foo_path = tmp_path.joinpath('contracts/foo.vy')
    with foo_path.open('w') as fp:
        fp.write(FOO_CODE.format(import_stmt))

    with tmp_path.joinpath('contracts/Bar.vy').open('w') as fp:
        fp.write(BAR_CODE)

    assert compile_files([foo_path], ['combined_json'], root_folder=tmp_path)
Beispiel #11
0
def test_combined_json_keys(tmp_path):
    bar_path = tmp_path.joinpath('bar.vy')
    with bar_path.open('w') as fp:
        fp.write("")

    combined_keys = {
        'bytecode', 'bytecode_runtime', 'abi', 'source_map',
        'method_identifiers'
    }
    compile_data = compile_files([bar_path], ['combined_json'],
                                 root_folder=tmp_path)

    assert set(compile_data.keys()) == {'bar.vy', 'version'}
    assert set(compile_data['bar.vy'].keys()) == combined_keys
Beispiel #12
0
def test_combined_json_keys(tmp_path):
    bar_path = tmp_path.joinpath("bar.vy")
    with bar_path.open("w") as fp:
        fp.write("")

    combined_keys = {
        "bytecode",
        "bytecode_runtime",
        "abi",
        "source_map",
        "method_identifiers",
        "userdoc",
        "devdoc",
    }
    compile_data = compile_files([bar_path], ["combined_json"],
                                 root_folder=tmp_path)

    assert set(compile_data.keys()) == {"bar.vy", "version"}
    assert set(compile_data["bar.vy"].keys()) == combined_keys
Beispiel #13
0
def test_import_self_interface(import_stmt, tmp_path):
    # a contract can access it's derived interface by importing itself
    code = """
{}

@public
def know_thyself(a: address) -> uint256:
    return Meta(a).be_known()

@public
def be_known() -> uint256:
    return 42
    """.format(import_stmt)

    tmp_path.joinpath('contracts').mkdir()

    meta_path = tmp_path.joinpath('contracts/Meta.vy')
    with meta_path.open('w') as fp:
        fp.write(code)

    assert compile_files([meta_path], ['combined_json'], root_folder=tmp_path)
Beispiel #14
0
def test_import_self_interface(import_stmt, tmp_path):
    # a contract can access it's derived interface by importing itself
    code = f"""
{import_stmt}

@external
def know_thyself(a: address) -> uint256:
    return Meta(a).be_known()

@external
def be_known() -> uint256:
    return 42
    """

    tmp_path.joinpath("contracts").mkdir()

    meta_path = tmp_path.joinpath("contracts/Meta.vy")
    with meta_path.open("w") as fp:
        fp.write(code)

    assert compile_files([meta_path], ["combined_json"], root_folder=tmp_path)
Beispiel #15
0
def test_local_namespace(tmp_path):
    # interface code namespaces should be isolated
    # all of these contract should be able to compile together
    codes = [
        "import foo as FooBar",
        "import bar as FooBar",
        "import foo as BarFoo",
        "import bar as BarFoo",
    ]

    compile_paths = []
    for i, code in enumerate(codes):
        path = tmp_path.joinpath(f'code{i}.vy')
        with path.open('w') as fp:
            fp.write(code)
        compile_paths.append(path)

    for file_name in ('foo.vy', 'bar.vy'):
        with tmp_path.joinpath(file_name).open('w') as fp:
            fp.write(BAR_CODE)

    assert compile_files(compile_paths, ['combined_json'], root_folder=tmp_path)
Beispiel #16
0
def test_invalid_root_path():
    with pytest.raises(FileNotFoundError):
        compile_files([], [], root_folder="path/that/does/not/exist")
Beispiel #17
0
    def compile(self):
        # check what kind of contract we are compiling
        if self.contract_filepath.endswith('.vy'):
            contract_type = 'vyper'
        else:
            contract_type = 'solidity'

        print(
            f'Compiling {contract_type.title()} contract {self.name} from {self.contract_filepath}'
        )

        contract_filename = os.path.basename(self.contract_filepath)

        # load the contract source code from file
        with open(self.contract_filepath, 'r') as f:
            contract_content = f.read()

        if contract_type == 'solidity':
            from solc import compile_standard

            # compile the contract source code
            compiled_sol = compile_standard({
                "language": "Solidity",
                "sources": {
                    contract_filename: {
                        "content": contract_content
                    }
                },
                "settings": {
                    "outputSelection": {
                        "*": {
                            "*": [
                                "metadata", "evm.bytecode",
                                "evm.bytecode.sourceMap"
                            ]
                        }
                    }
                }
            })

            # the contract ABI, used by web3 to interact with the contract
            self.abi = json.loads(compiled_sol['contracts'][contract_filename][
                self.name]['metadata'])['output']['abi']

            # the compiled bytecode, used for deploying the contract
            self.bytecode = compiled_sol['contracts'][contract_filename][
                self.name]['evm']['bytecode']['object']

        if contract_type == 'vyper':
            from vyper.cli.vyper_compile import compile_files

            output = compile_files(input_files=[self.contract_filepath],
                                   output_formats=['abi', 'bytecode'])
            self.abi = output[self.contract_filepath]['abi']
            self.bytecode = output[self.contract_filepath]['bytecode']

        # optionally save the ABI to file so that it can be re-used
        if self.abi_filepath:
            print(f'saving ABI to {self.abi_filepath}')
            with open(self.abi_filepath, 'w') as f:
                json.dump(self.abi, f)

        # optionally save the bytecode to file so that it can be re-used
        if self.bytecode_filepath:
            print(f'saving bytecode to {self.bytecode_filepath}')
            with open(self.bytecode_filepath, 'w') as f:
                f.write(self.bytecode)