From 8a81d508f5e9ec3e918e3daaf75bc8e50355357c Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 26 Sep 2023 12:43:48 -0400 Subject: [PATCH 1/9] fix some documentation inconsistencies - raw_args kwarg to create_from_blueprint - fix create_from_blueprint example - clarify "all but one 64th" behavior when forwarding gas left --- docs/built-in-functions.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/built-in-functions.rst b/docs/built-in-functions.rst index bfaa8fdd5e..f70f639432 100644 --- a/docs/built-in-functions.rst +++ b/docs/built-in-functions.rst @@ -184,13 +184,14 @@ Vyper has three built-ins for contract creation; all three contract creation bui The implementation of ``create_copy_of`` assumes that the code at ``target`` is smaller than 16MB. While this is much larger than the EIP-170 constraint of 24KB, it is a conservative size limit intended to future-proof deployer contracts in case the EIP-170 constraint is lifted. If the code at ``target`` is larger than 16MB, the behavior of ``create_copy_of`` is undefined. -.. py:function:: create_from_blueprint(target: address, *args, value: uint256 = 0, code_offset=0, [, salt: bytes32]) -> address +.. py:function:: create_from_blueprint(target: address, *args, value: uint256 = 0, raw_args: bool = False, code_offset: int = 0, [, salt: bytes32]) -> address Copy the code of ``target`` into memory and execute it as initcode. In other words, this operation interprets the code at ``target`` not as regular runtime code, but directly as initcode. The ``*args`` are interpreted as constructor arguments, and are ABI-encoded and included when executing the initcode. * ``target``: Address of the blueprint to invoke * ``*args``: Constructor arguments to forward to the initcode. * ``value``: The wei value to send to the new contract address (Optional, default 0) + * ``raw_args``: If ``True``, ``*args`` must be a single ``Bytes[...]`` argument, which will be interpreted as a raw bytes buffer to forward to the create operation (which is useful for instance, if pre- ABI-encoded data is passed in from elsewhere). (Optional, default ``False``) * ``code_offset``: The offset to start the ``EXTCODECOPY`` from (Optional, default 0) * ``salt``: A ``bytes32`` value utilized by the deterministic ``CREATE2`` opcode (Optional, if not supplied, ``CREATE`` is used) @@ -201,7 +202,7 @@ Vyper has three built-ins for contract creation; all three contract creation bui @external def foo(blueprint: address) -> address: arg1: uint256 = 18 - arg2: String = "some string" + arg2: String[32] = "some string" return create_from_blueprint(blueprint, arg1, arg2, code_offset=1) .. note:: @@ -226,7 +227,7 @@ Vyper has three built-ins for contract creation; all three contract creation bui * ``to``: Destination address to call to * ``data``: Data to send to the destination address * ``max_outsize``: Maximum length of the bytes array returned from the call. If the returned call data exceeds this length, only this number of bytes is returned. (Optional, default ``0``) - * ``gas``: The amount of gas to attach to the call. If not set, all remaining gas is forwarded. + * ``gas``: The amount of gas to attach to the call. (Optional, defaults to ``msg.gas``). * ``value``: The wei value to send to the address (Optional, default ``0``) * ``is_delegate_call``: If ``True``, the call will be sent as ``DELEGATECALL`` (Optional, default ``False``) * ``is_static_call``: If ``True``, the call will be sent as ``STATICCALL`` (Optional, default ``False``) @@ -264,6 +265,10 @@ Vyper has three built-ins for contract creation; all three contract creation bui assert success return response + .. note:: + + Regarding "forwarding all gas", note that, while Vyper will provide ``msg.gas`` to the call, in practice, there are some subtleties around forwarding all remaining gas on the EVM which are out of scope of this documentation and could be subject to change. For instance, see the language in EIP-150 around "all but one 64th". + .. py:function:: raw_log(topics: bytes32[4], data: Union[Bytes, bytes32]) -> None Provides low level access to the ``LOG`` opcodes, emitting a log without having to specify an ABI type. From 439da4edbfc84e25f8de55ded426a29c398e8f6c Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 26 Sep 2023 12:46:27 -0400 Subject: [PATCH 2/9] remove dead comment --- vyper/semantics/analysis/module.py | 1 - 1 file changed, 1 deletion(-) diff --git a/vyper/semantics/analysis/module.py b/vyper/semantics/analysis/module.py index 02ae82faac..e59422294c 100644 --- a/vyper/semantics/analysis/module.py +++ b/vyper/semantics/analysis/module.py @@ -98,7 +98,6 @@ def __init__( _ns.update({k: namespace[k] for k in namespace._scopes[-1]}) # type: ignore module_node._metadata["namespace"] = _ns - # check for collisions between 4byte function selectors self_members = namespace["self"].typ.members # get list of internal function calls made by each function From e8ee056143c5aa85809fefab4c9019ff94a3198b Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 26 Sep 2023 12:49:33 -0400 Subject: [PATCH 3/9] remove dead comment --- vyper/builtins/functions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/vyper/builtins/functions.py b/vyper/builtins/functions.py index 95759372a6..0ed796d5fc 100644 --- a/vyper/builtins/functions.py +++ b/vyper/builtins/functions.py @@ -2586,7 +2586,6 @@ def evaluate(self, node): if isinstance(input_type, IntegerT): ret = vy_ast.Int.from_node(node, value=val) - # TODO: to change to known_type once #3213 is merged ret._metadata["type"] = input_type return ret From ffe109642d52a0ebfec90fbb2250ebc4209c42c3 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 26 Sep 2023 12:49:42 -0400 Subject: [PATCH 4/9] update internal documentation for generate_ir_for_external_function() --- .../codegen/function_definitions/external_function.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/vyper/codegen/function_definitions/external_function.py b/vyper/codegen/function_definitions/external_function.py index 32236e9aad..f9c07b8cff 100644 --- a/vyper/codegen/function_definitions/external_function.py +++ b/vyper/codegen/function_definitions/external_function.py @@ -135,9 +135,6 @@ def handler_for(calldata_kwargs, default_kwargs): return ret -# TODO it would be nice if this returned a data structure which were -# amenable to generating a jump table instead of the linear search for -# method_id we have now. def generate_ir_for_external_function(code, func_t, context): # TODO type hints: # def generate_ir_for_external_function( @@ -146,9 +143,10 @@ def generate_ir_for_external_function(code, func_t, context): # context: Context, # check_nonpayable: bool, # ) -> IRnode: - """Return the IR for an external function. Includes code to inspect the method_id, - enter the function (nonpayable and reentrancy checks), handle kwargs and exit - the function (clean up reentrancy storage variables) + """ + Return the IR for an external function. Returns IR for the body + of the function, handle kwargs and exit the function. Also returns + metadata required for `module.py` to construct the selector table. """ nonreentrant_pre, nonreentrant_post = get_nonreentrant_lock(func_t) From 3702d93ba202c3e4129db730873ae014c64bcd77 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 26 Sep 2023 12:52:47 -0400 Subject: [PATCH 5/9] update memory layout in create_from_blueprint comments --- vyper/builtins/functions.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vyper/builtins/functions.py b/vyper/builtins/functions.py index 0ed796d5fc..5b034e2d9f 100644 --- a/vyper/builtins/functions.py +++ b/vyper/builtins/functions.py @@ -1917,9 +1917,8 @@ def _build_create_IR(self, expr, args, context, value, salt, code_offset, raw_ar # copy the target code into memory. # layout starting from mem_ofst: - # 00...00 (22 0's) | preamble | bytecode + # | ir.append(["extcodecopy", target, mem_ofst, code_offset, codesize]) - ir.append(copy_bytes(add_ofst(mem_ofst, codesize), argbuf, encoded_args_len, bufsz)) # theoretically, dst = "msize", but just be safe. From 00df0700aa127f2deb894b294c664e1c225cdd60 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 26 Sep 2023 12:53:16 -0400 Subject: [PATCH 6/9] fix warning for BitwiseNot --- vyper/builtins/functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vyper/builtins/functions.py b/vyper/builtins/functions.py index 5b034e2d9f..a0936712b2 100644 --- a/vyper/builtins/functions.py +++ b/vyper/builtins/functions.py @@ -1418,7 +1418,7 @@ class BitwiseNot(BuiltinFunction): def evaluate(self, node): if not self.__class__._warned: - vyper_warn("`bitwise_not()` is deprecated! Please use the ^ operator instead.") + vyper_warn("`bitwise_not()` is deprecated! Please use the ~ operator instead.") self.__class__._warned = True validate_call_args(node, 1) From 004398cb284ab93ddfb899747a5b25c80340f095 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 26 Sep 2023 12:54:00 -0400 Subject: [PATCH 7/9] fix error message about msg.data --- vyper/semantics/analysis/local.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vyper/semantics/analysis/local.py b/vyper/semantics/analysis/local.py index c10df3b8fd..b391b33953 100644 --- a/vyper/semantics/analysis/local.py +++ b/vyper/semantics/analysis/local.py @@ -150,7 +150,7 @@ def _validate_msg_data_attribute(node: vy_ast.Attribute) -> None: allowed_builtins = ("slice", "len", "raw_call") if not isinstance(parent, vy_ast.Call) or parent.get("func.id") not in allowed_builtins: raise StructureException( - "msg.data is only allowed inside of the slice or len functions", node + "msg.data is only allowed inside of the slice, len or raw_call functions", node ) if parent.get("func.id") == "slice": ok_args = len(parent.args) == 3 and isinstance(parent.args[2], vy_ast.Int) From 6a53ed965d4a899f4e9bb94c49ebc4e640c00a73 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 26 Sep 2023 12:55:21 -0400 Subject: [PATCH 8/9] docs: extract32 can output any bytesM type --- docs/built-in-functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/built-in-functions.rst b/docs/built-in-functions.rst index f70f639432..45cf9ec8c2 100644 --- a/docs/built-in-functions.rst +++ b/docs/built-in-functions.rst @@ -505,7 +505,7 @@ Data Manipulation * ``b``: ``Bytes`` list to extract from * ``start``: Start point to extract from - * ``output_type``: Type of output (``bytes32``, ``integer``, or ``address``). Defaults to ``bytes32``. + * ``output_type``: Type of output (``bytesM``, ``integer``, or ``address``). Defaults to ``bytes32``. Returns a value of the type specified by ``output_type``. From c343fdf99e39a5da52ccff52092a22596a27cce2 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Tue, 26 Sep 2023 13:08:06 -0400 Subject: [PATCH 9/9] remove dead variable in comment --- vyper/codegen/function_definitions/external_function.py | 1 - 1 file changed, 1 deletion(-) diff --git a/vyper/codegen/function_definitions/external_function.py b/vyper/codegen/function_definitions/external_function.py index f9c07b8cff..65276469e7 100644 --- a/vyper/codegen/function_definitions/external_function.py +++ b/vyper/codegen/function_definitions/external_function.py @@ -141,7 +141,6 @@ def generate_ir_for_external_function(code, func_t, context): # code: vy_ast.FunctionDef, # func_t: ContractFunctionT, # context: Context, - # check_nonpayable: bool, # ) -> IRnode: """ Return the IR for an external function. Returns IR for the body