task: metadata: install: pip install -e .[dev]
patch: diff --git a/docs/built-in-functions.rst b/docs/built-in-functions.rst
index 74e85604..bfaa8fdd 100644
--- a/docs/built-in-functions.rst
+++ b/docs/built-in-functions.rst
@@ -379,7 +379,11 @@ Cryptography
     * ``s``: second 32 bytes of signature
     * ``v``: final 1 byte of signature
 
-    Returns the associated address, or ``0`` on error.
+    Returns the associated address, or ``empty(address)`` on error.
+
+    .. note::
+
+         Prior to Vyper ``0.3.10``, the ``ecrecover`` function could return an undefined (possibly nonzero) value for invalid inputs to ``ecrecover``. For more information, please see `GHSA-f5x6-7qgp-jhf3 <https://github.com/vyperlang/vyper/security/advisories/GHSA-f5x6-7qgp-jhf3>`_.
 
     .. code-block:: python
 
@@ -573,6 +577,24 @@ Math
         >>> ExampleContract.foo(3.1337)
         4
 
+.. py:function:: epsilon(typename) -> Any
+
+    Returns the smallest non-zero value for a decimal type.
+
+    * ``typename``: Name of the decimal type (currently only ``decimal``)
+
+    .. code-block:: python
+
+        @external
+        @view
+        def foo() -> decimal:
+            return epsilon(decimal)
+
+    .. code-block:: python
+
+        >>> ExampleContract.foo()
+        Decimal('1E-10')
+
 .. py:function:: floor(value: decimal) -> int256
 
     Round a decimal down to the nearest integer.
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
index 9a638469..f408c5c0 100644
--- a/docs/release-notes.rst
+++ b/docs/release-notes.rst
@@ -336,6 +336,7 @@ Special thanks to @skellet0r for some major features in this release!
 
 v0.3.0
 *******
+⚠️ A critical security vulnerability has been discovered in this version and we strongly recommend using version `0.3.1 <https://github.com/vyperlang/vyper/releases/tag/v0.3.1>`_ or higher. For more information, please see the Security Advisory `GHSA-5824-cm3x-3c38 <https://github.com/vyperlang/vyper/security/advisories/GHSA-5824-cm3x-3c38>`_.
 
 Date released: 2021-10-04
 
@@ -368,6 +369,7 @@ Special thanks to contributions from @skellet0r and @benjyz for this release!
 
 v0.2.16
 *******
+⚠️ A critical security vulnerability has been discovered in this version and we strongly recommend using version `0.3.1 <https://github.com/vyperlang/vyper/releases/tag/v0.3.1>`_ or higher. For more information, please see the Security Advisory `GHSA-5824-cm3x-3c38 <https://github.com/vyperlang/vyper/security/advisories/GHSA-5824-cm3x-3c38>`_.
 
 Date released: 2021-08-27
 
@@ -392,6 +394,7 @@ Special thanks to contributions from @skellet0r, @sambacha and @milancermak for
 
 v0.2.15
 *******
+⚠️ A critical security vulnerability has been discovered in this version and we strongly recommend using version `0.3.1 <https://github.com/vyperlang/vyper/releases/tag/v0.3.1>`_ or higher. For more information, please see the Security Advisory `GHSA-5824-cm3x-3c38 <https://github.com/vyperlang/vyper/security/advisories/GHSA-5824-cm3x-3c38>`_.
 
 Date released: 23-07-2021
 
diff --git a/vyper/semantics/analysis/local.py b/vyper/semantics/analysis/local.py
index c0c05325..c10df3b8 100644
--- a/vyper/semantics/analysis/local.py
+++ b/vyper/semantics/analysis/local.py
@@ -346,10 +346,11 @@ class FunctionNodeVisitor(VyperNodeVisitorBase):
                 raise IteratorException(
                     "Cannot iterate over the result of a function call", node.iter
                 )
-            validate_call_args(node.iter, (1, 2), kwargs=["bound"])
+            range_ = node.iter
+            validate_call_args(range_, (1, 2), kwargs=["bound"])
 
-            args = node.iter.args
-            kwargs = {s.arg: s.value for s in node.iter.keywords or []}
+            args = range_.args
+            kwargs = {s.arg: s.value for s in range_.keywords or []}
             if len(args) == 1:
                 # range(CONSTANT)
                 n = args[0]
@@ -371,6 +372,13 @@ class FunctionNodeVisitor(VyperNodeVisitorBase):
                     type_list = get_common_types(n, bound)
 
             else:
+                if range_.keywords:
+                    raise StructureException(
+                        "Keyword arguments are not supported for `range(N, M)` and"
+                        "`range(x, x + N)` expressions",
+                        range_.keywords[0],
+                    )
+
                 validate_expected_type(args[0], IntegerT.any())
                 type_list = get_common_types(*args)
                 if not isinstance(args[0], vy_ast.Constant):

problem_statement: Usage of kwargs not prevented for `range(N,M)` or `range(x,x+N)`  
### Version Information

* vyper Version (output of `vyper --version`): 0.3.10+commit.855f7349
* OS: OSX
* Python Version (output of `python --version`): 3.11.4

### What's your issue about?

Using the keyword argument `bound` for ranges on the form `range(N, M)` and `range(x, x + N)` is not syntactically forbidden. The generated bytecode of the following examples is identical to the one that would have been generated without having the `bound` keyword.

```Vyper
@external
def bar():
    for i in range(1,2,bound=2):
        pass
```
```Vyper
@external
def bar():
    x:uint256 = 1
    for i in range(x,x+1,bound=2):
        pass
```

### How can it be fixed?

Only allow ranges on the form `range(N)` to have kwargs.
repo: vyperlang/vyper
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/parser/syntax/test_for_range.py b/tests/parser/syntax/test_for_range.py
index b2a94910..e6f35c1d 100644
--- a/tests/parser/syntax/test_for_range.py
+++ b/tests/parser/syntax/test_for_range.py
@@ -12,7 +12,26 @@ def foo():
         pass
     """,
         StructureException,
-    )
+    ),
+    (
+        """
+@external
+def bar():
+    for i in range(1,2,bound=2):
+        pass
+    """,
+        StructureException,
+    ),
+    (
+        """
+@external
+def bar():
+    x:uint256 = 1
+    for i in range(x,x+1,bound=2):
+        pass
+    """,
+        StructureException,
+    ),
 ]