Repository: vyperlang/vyper

Issue:
incorrectly reported overflow exception
### Version Information

* vyper Version (output of `vyper --version`): 0.4.0

### What's your issue about?
```vyper
@external
def foo() -> uint256:
    return (10**18)**2
```
panics at compilation with the following error, which is clearly wrong given that 10**36 clearly fits in a uint256:
```
vyper.exceptions.OverflowException: Base is too large, calculation will always overflow

  contract "contracts/token.vy:3", function "foo", line 3:12 
       2 def foo() -> uint256:
  ---> 3     return (10**18)**2
  -------------------^
```


Discussion:

Patch:
diff --git a/vyper/semantics/analysis/utils.py b/vyper/semantics/analysis/utils.py
index a31ce7ac..8727f375 100644
--- a/vyper/semantics/analysis/utils.py
+++ b/vyper/semantics/analysis/utils.py
@@ -41,7 +41,7 @@ def _validate_op(node, types_list, validation_fn_name):
         try:
             _validate_fn(node)
             ret.append(type_)
-        except InvalidOperation as e:
+        except (InvalidOperation, OverflowException) as e:
             err_list.append(e)
 
     if ret:
diff --git a/vyper/semantics/types/primitives.py b/vyper/semantics/types/primitives.py
index 5c0362e6..dcc4fe8c 100644
--- a/vyper/semantics/types/primitives.py
+++ b/vyper/semantics/types/primitives.py
@@ -173,11 +173,11 @@ class NumericT(_PrimT):
             if isinstance(left, vy_ast.Int):
                 if left.value >= 2**value_bits:
                     raise OverflowException(
-                        "Base is too large, calculation will always overflow", left
+                        f"Base is too large for {self}, calculation will always overflow", left
                     )
                 elif left.value < -(2**value_bits):
                     raise OverflowException(
-                        "Base is too small, calculation will always underflow", left
+                        f"Base is too small for {self}, calculation will always underflow", left
                     )
             elif isinstance(right, vy_ast.Int):
                 if right.value < 0:


Test patch:
diff --git a/tests/functional/codegen/types/numbers/test_exponents.py b/tests/functional/codegen/types/numbers/test_exponents.py
index 702cbcb1..28dba59e 100644
--- a/tests/functional/codegen/types/numbers/test_exponents.py
+++ b/tests/functional/codegen/types/numbers/test_exponents.py
@@ -173,3 +173,17 @@ def foo(b: int128) -> int128:
     c.foo(max_power)
     with tx_failed():
         c.foo(max_power + 1)
+
+
+valid_list = [
+    """
+@external
+def foo() -> uint256:
+    return (10**18)**2
+    """
+]
+
+
+@pytest.mark.parametrize("good_code", valid_list)
+def test_exponent_success(good_code):
+    assert compile_code(good_code) is not None