diff --git a/icontract/_checkers.py b/icontract/_checkers.py
index 1dc79d3..e5909e2 100644
--- a/icontract/_checkers.py
+++ b/icontract/_checkers.py
@@ -92,11 +92,12 @@ def _assert_precondition(contract: Contract, resolved_kwargs: Mapping[str, Any])
     Assert that the contract holds as a precondition.
 
     :param contract: contract to be verified
-    :param resolved_kwargs: resolved keyword arguments (including the default values)
+    :param resolved_kwargs:
+        resolved keyword arguments of the call (including the default argument values of the decorated function)
     :return:
     """
     # Check that all arguments to the condition function have been set.
-    missing_args = [arg_name for arg_name in contract.condition_args if arg_name not in resolved_kwargs]
+    missing_args = [arg_name for arg_name in contract.mandatory_args if arg_name not in resolved_kwargs]
     if missing_args:
         raise TypeError(
             ("The argument(s) of the precondition have not been set: {}. "
@@ -207,7 +208,7 @@ def _assert_postcondition(contract: Contract, resolved_kwargs: Mapping[str, Any]
         "Expected 'result' to be set in the resolved keyword arguments of a postcondition."
 
     # Check that all arguments to the condition function have been set.
-    missing_args = [arg_name for arg_name in contract.condition_args if arg_name not in resolved_kwargs]
+    missing_args = [arg_name for arg_name in contract.mandatory_args if arg_name not in resolved_kwargs]
     if missing_args:
         raise TypeError(
             ("The argument(s) of the postcondition have not been set: {}. "
diff --git a/icontract/_decorators.py b/icontract/_decorators.py
index f4cb5dc..e48b090 100644
--- a/icontract/_decorators.py
+++ b/icontract/_decorators.py
@@ -326,7 +326,7 @@ class invariant:  # pylint: disable=invalid-name
         self._contract = Contract(
             condition=condition, description=description, a_repr=a_repr, error=error, location=location)
 
-        if self._contract.condition_args and self._contract.condition_args != ['self']:
+        if self._contract.mandatory_args and self._contract.mandatory_args != ['self']:
             raise ValueError("Expected an invariant condition with at most an argument 'self', but got: {}".format(
                 self._contract.condition_args))
 
diff --git a/icontract/_types.py b/icontract/_types.py
index c6e80d0..a7e01da 100644
--- a/icontract/_types.py
+++ b/icontract/_types.py
@@ -37,9 +37,17 @@ class Contract:
         # pylint: disable=too-many-arguments
         self.condition = condition
 
-        self.condition_args = list(inspect.signature(condition).parameters.keys())  # type: List[str]
+        signature = inspect.signature(condition)
+
+        # All argument names of the condition
+        self.condition_args = list(signature.parameters.keys())  # type: List[str]
         self.condition_arg_set = set(self.condition_args)  # type: Set[str]
 
+        # Names of the mandatory arguments of the condition
+        self.mandatory_args = [
+            name for name, param in signature.parameters.items() if param.default == inspect.Parameter.empty
+        ]
+
         self.description = description
         self._a_repr = a_repr
 

checking of contract arguments is too strict
consider:

```
$ cat i.py                                                                                                                                                                                                          (time_gym) 
from icontract import require, ensure

def gt(x, y=0):
    return x > y

@require(gt)
def frobulate(x: int) -> int:
    return x

frobulate(-1)

$ python i.py                                                                                                                                                                                                       Traceback (most recent call last):
  File "i.py", line 10, in <module>
    frobulate(-1)
  File "/home/james/Src/icontract/icontract/_checkers.py", line 309, in wrapper
    _assert_precondition(contract=contract, resolved_kwargs=resolved_kwargs)
  File "/home/james/Src/icontract/icontract/_checkers.py", line 93, in _assert_precondition
    "Does the original function define them? Did you supply them in the call?").format(missing_args))
TypeError: The argument(s) of the precondition have not been set: ['y']. Does the original function define them? Did you supply them in the call?
```

Should I have to set y here?  I don't think so.
diff --git a/tests/test_invariant.py b/tests/test_invariant.py
index a971cd7..c18eba0 100644
--- a/tests/test_invariant.py
+++ b/tests/test_invariant.py
@@ -386,6 +386,62 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(violation_error)
         self.assertEqual("z != 42: z was 42", tests.error.wo_mandatory_location(str(violation_error)))
 
+    def test_condition_as_function(self):
+        def some_condition(self: 'A') -> bool:  # type: ignore
+            return self.x > 0
+
+        @icontract.invariant(some_condition)
+        class A:
+            def __init__(self) -> None:
+                self.x = 100
+
+            def some_method(self) -> None:
+                self.x = -1
+
+            def __repr__(self) -> str:
+                return "A(x={})".format(self.x)
+
+        # Valid call
+        a = A()
+
+        # Invalid call
+        violation_error = None  # type: Optional[icontract.ViolationError]
+        try:
+            a.some_method()
+        except icontract.ViolationError as err:
+            violation_error = err
+
+        self.assertIsNotNone(violation_error)
+        self.assertEqual('some_condition: self was A(x=-1)', tests.error.wo_mandatory_location(str(violation_error)))
+
+    def test_condition_as_function_with_default_argument_value(self):
+        def some_condition(self: 'A', y: int = 0) -> bool:  # type: ignore
+            return self.x > y
+
+        @icontract.invariant(some_condition)
+        class A:
+            def __init__(self) -> None:
+                self.x = 100
+
+            def some_method(self) -> None:
+                self.x = -1
+
+            def __repr__(self) -> str:
+                return "A(x={})".format(self.x)
+
+        # Valid call
+        a = A()
+
+        # Invalid call
+        violation_error = None  # type: Optional[icontract.ViolationError]
+        try:
+            a.some_method()
+        except icontract.ViolationError as err:
+            violation_error = err
+
+        self.assertIsNotNone(violation_error)
+        self.assertEqual('some_condition: self was A(x=-1)', tests.error.wo_mandatory_location(str(violation_error)))
+
 
 class TestProperty(unittest.TestCase):
     def test_property_getter(self):
diff --git a/tests/test_postcondition.py b/tests/test_postcondition.py
index 3cbe98a..4804dde 100644
--- a/tests/test_postcondition.py
+++ b/tests/test_postcondition.py
@@ -41,6 +41,71 @@ class TestViolation(unittest.TestCase):
                          "result was -4\n"
                          "x was 1", tests.error.wo_mandatory_location(str(violation_error)))
 
+    def test_condition_as_function(self):
+        def some_condition(result: int) -> bool:
+            return result > 3
+
+        @icontract.ensure(some_condition)
+        def some_func(x: int) -> int:
+            return x
+
+        # Valid call
+        some_func(x=4)
+
+        # Invalid call
+        violation_error = None  # type: Optional[icontract.ViolationError]
+        try:
+            some_func(x=1)
+        except icontract.ViolationError as err:
+            violation_error = err
+
+        self.assertIsNotNone(violation_error)
+        self.assertEqual('some_condition: result was 1', tests.error.wo_mandatory_location(str(violation_error)))
+
+    def test_condition_as_function_with_default_argument_value(self):
+        def some_condition(result: int, y: int = 0) -> bool:
+            return result > y
+
+        @icontract.ensure(some_condition)
+        def some_func(x: int) -> int:
+            return x
+
+        # Valid call
+        some_func(x=1)
+
+        # Invalid call
+        violation_error = None  # type: Optional[icontract.ViolationError]
+        try:
+            some_func(x=-1)
+        except icontract.ViolationError as err:
+            violation_error = err
+
+        self.assertIsNotNone(violation_error)
+        self.assertEqual('some_condition: result was -1', tests.error.wo_mandatory_location(str(violation_error)))
+
+    def test_condition_as_function_with_default_argument_value_set(self):
+        def some_condition(result: int, y: int = 0) -> bool:
+            return result > y
+
+        @icontract.ensure(some_condition)
+        def some_func(x: int, y: int) -> int:
+            return x
+
+        # Valid call
+        some_func(x=-1, y=-2)
+
+        # Invalid call
+        violation_error = None  # type: Optional[icontract.ViolationError]
+        try:
+            some_func(x=1, y=3)
+        except icontract.ViolationError as err:
+            violation_error = err
+
+        self.assertIsNotNone(violation_error)
+        self.assertEqual('some_condition:\n'
+                         'result was 1\n'
+                         'y was 3', tests.error.wo_mandatory_location(str(violation_error)))
+
     def test_with_description(self):
         @icontract.ensure(lambda result, x: result > x, "expected summation")
         def some_func(x: int, y: int = 5) -> int:
diff --git a/tests/test_precondition.py b/tests/test_precondition.py
index 9b08408..8709edb 100644
--- a/tests/test_precondition.py
+++ b/tests/test_precondition.py
@@ -55,7 +55,7 @@ class TestViolation(unittest.TestCase):
         self.assertEqual("x must not be small: x > 3: x was 1", tests.error.wo_mandatory_location(str(violation_error)))
 
     def test_condition_as_function(self):
-        def some_condition(x: int):
+        def some_condition(x: int) -> bool:
             return x > 3
 
         @icontract.require(some_condition)
@@ -71,6 +71,50 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(violation_error)
         self.assertEqual("some_condition: x was 1", tests.error.wo_mandatory_location(str(violation_error)))
 
+    def test_condition_as_function_with_default_argument_value(self):
+        def some_condition(x: int, y: int = 0) -> bool:
+            return x > y
+
+        @icontract.require(some_condition)
+        def some_func(x: int) -> None:
+            pass
+
+        # Valid call
+        some_func(x=1)
+
+        # Invalid call
+        violation_error = None  # type: Optional[icontract.ViolationError]
+        try:
+            some_func(x=-1)
+        except icontract.ViolationError as err:
+            violation_error = err
+
+        self.assertIsNotNone(violation_error)
+        self.assertEqual("some_condition: x was -1", tests.error.wo_mandatory_location(str(violation_error)))
+
+    def test_condition_as_function_with_default_argument_value_set(self):
+        def some_condition(x: int, y: int = 0) -> bool:
+            return x > y
+
+        @icontract.require(some_condition)
+        def some_func(x: int, y: int) -> None:
+            pass
+
+        # Valid call
+        some_func(x=3, y=1)
+
+        # Invalid call
+        violation_error = None  # type: Optional[icontract.ViolationError]
+        try:
+            some_func(x=-1, y=1)
+        except icontract.ViolationError as err:
+            violation_error = err
+
+        self.assertIsNotNone(violation_error)
+        self.assertEqual('some_condition:\n'
+                         'x was -1\n'
+                         'y was 1', tests.error.wo_mandatory_location(str(violation_error)))
+
     def test_with_pathlib(self):
         @icontract.require(lambda path: path.exists())
         def some_func(path: pathlib.Path) -> None:

pip install -e .[dev]
parse_log_pytest
requirements.txt
tox pytest
3.6
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
astroid==2.3.0
asttokens==1.1.15
attrs==22.2.0
certifi==2021.5.30
coverage==4.5.4
distlib==0.3.9
docutils==0.18.1
filelock==3.4.1
-e git+https://github.com/Parquery/icontract.git@5eecd149ac76db451a978ba208b95768fa1685af#egg=icontract
importlib-metadata==4.8.3
importlib-resources==5.4.0
iniconfig==1.1.1
isort==4.3.21
lazy-object-proxy==1.7.1
mccabe==0.6.1
mypy==0.641
mypy-extensions==0.4.4
packaging==21.3
platformdirs==2.4.0
pluggy==1.0.0
py==1.11.0
pydocstyle==2.1.1
Pygments==2.14.0
pylint==2.3.1
pyparsing==3.1.4
pytest==7.0.1
six==1.17.0
snowballstemmer==2.2.0
toml==0.10.2
tomli==1.2.3
tox==3.28.0
typed-ast==1.1.2
typing_extensions==4.1.1
virtualenv==20.17.1
wrapt==1.16.0
yapf==0.20.2
zipp==3.6.0

name: icontract
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - astroid==2.3.0
      - asttokens==1.1.15
      - attrs==22.2.0
      - coverage==4.5.4
      - distlib==0.3.9
      - docutils==0.18.1
      - filelock==3.4.1
      - importlib-metadata==4.8.3
      - importlib-resources==5.4.0
      - iniconfig==1.1.1
      - isort==4.3.21
      - lazy-object-proxy==1.7.1
      - mccabe==0.6.1
      - mypy==0.641
      - mypy-extensions==0.4.4
      - packaging==21.3
      - platformdirs==2.4.0
      - pluggy==1.0.0
      - py==1.11.0
      - pydocstyle==2.1.1
      - pygments==2.14.0
      - pylint==2.3.1
      - pyparsing==3.1.4
      - pytest==7.0.1
      - six==1.17.0
      - snowballstemmer==2.2.0
      - toml==0.10.2
      - tomli==1.2.3
      - tox==3.28.0
      - typed-ast==1.1.2
      - typing-extensions==4.1.1
      - virtualenv==20.17.1
      - wrapt==1.16.0
      - yapf==0.20.2
      - zipp==3.6.0
prefix: /opt/conda/envs/icontract

tests/test_invariant.py::TestViolation::test_condition_as_function_with_default_argument_value tests/test_postcondition.py::TestViolation::test_condition_as_function_with_default_argument_value tests/test_precondition.py::TestViolation::test_condition_as_function_with_default_argument_value
tests/test_invariant.py::TestOK::test_class_method tests/test_invariant.py::TestOK::test_init tests/test_invariant.py::TestOK::test_instance_method tests/test_invariant.py::TestOK::test_inv_broken_before_private_method tests/test_invariant.py::TestOK::test_inv_broken_before_protected_method tests/test_invariant.py::TestOK::test_inv_with_empty_arguments tests/test_invariant.py::TestOK::test_magic_method tests/test_invariant.py::TestOK::test_private_method_may_violate_inv tests/test_invariant.py::TestOK::test_protected_method_may_violate_inv tests/test_invariant.py::TestViolation::test_condition_as_function tests/test_invariant.py::TestViolation::test_init tests/test_invariant.py::TestViolation::test_inv_as_precondition tests/test_invariant.py::TestViolation::test_inv_ok_but_post_violated tests/test_invariant.py::TestViolation::test_inv_violated_after_pre tests/test_invariant.py::TestViolation::test_inv_violated_but_post_ok tests/test_invariant.py::TestViolation::test_inv_with_empty_arguments tests/test_invariant.py::TestViolation::test_magic_method tests/test_invariant.py::TestViolation::test_method tests/test_invariant.py::TestViolation::test_multiple_invs_first_violated tests/test_invariant.py::TestViolation::test_multiple_invs_last_violated tests/test_invariant.py::TestProperty::test_property_deleter tests/test_invariant.py::TestProperty::test_property_getter tests/test_invariant.py::TestProperty::test_property_setter tests/test_invariant.py::TestError::test_as_function tests/test_invariant.py::TestError::test_as_function_with_empty_args tests/test_invariant.py::TestError::test_as_type tests/test_invariant.py::TestToggling::test_disabled tests/test_invariant.py::TestInvalid::test_no_boolyness tests/test_invariant.py::TestInvalid::test_with_invalid_arguments tests/test_postcondition.py::TestOK::test_with_condition_as_lambda tests/test_postcondition.py::TestViolation::test_condition_as_function tests/test_postcondition.py::TestViolation::test_condition_as_function_with_default_argument_value_set tests/test_postcondition.py::TestViolation::test_only_result tests/test_postcondition.py::TestViolation::test_with_condition tests/test_postcondition.py::TestViolation::test_with_default_values_outer tests/test_postcondition.py::TestViolation::test_with_description tests/test_postcondition.py::TestViolation::test_with_stacked_decorators tests/test_postcondition.py::TestError::test_as_function tests/test_postcondition.py::TestError::test_as_type tests/test_postcondition.py::TestError::test_with_different_args_from_condition tests/test_postcondition.py::TestError::test_with_empty_args tests/test_postcondition.py::TestToggling::test_disabled tests/test_postcondition.py::TestInClass::test_deleter tests/test_postcondition.py::TestInClass::test_getter tests/test_postcondition.py::TestInClass::test_postcondition_in_abstract_class_method tests/test_postcondition.py::TestInClass::test_postcondition_in_abstract_static_method tests/test_postcondition.py::TestInClass::test_postcondition_in_class_method tests/test_postcondition.py::TestInClass::test_postcondition_in_static_method tests/test_postcondition.py::TestInClass::test_setter tests/test_postcondition.py::TestInvalid::test_conflicting_OLD_argument tests/test_postcondition.py::TestInvalid::test_conflicting_result_argument tests/test_postcondition.py::TestInvalid::test_error_with_invalid_arguments tests/test_postcondition.py::TestInvalid::test_invalid_postcondition_arguments tests/test_postcondition.py::TestInvalid::test_no_boolyness tests/test_precondition.py::TestOK::test_that_it_works tests/test_precondition.py::TestViolation::test_condition_as_function tests/test_precondition.py::TestViolation::test_condition_as_function_with_default_argument_value_set tests/test_precondition.py::TestViolation::test_only_with_condition_arg tests/test_precondition.py::TestViolation::test_with_default_values tests/test_precondition.py::TestViolation::test_with_description tests/test_precondition.py::TestViolation::test_with_multiple_comparators tests/test_precondition.py::TestViolation::test_with_pathlib tests/test_precondition.py::TestViolation::test_with_stacked_decorators tests/test_precondition.py::TestError::test_as_function tests/test_precondition.py::TestError::test_as_function_with_outer_scope tests/test_precondition.py::TestError::test_as_type tests/test_precondition.py::TestError::test_with_different_args_from_condition tests/test_precondition.py::TestError::test_with_empty_args tests/test_precondition.py::TestToggling::test_enabled tests/test_precondition.py::TestInClass::test_deleter tests/test_precondition.py::TestInClass::test_getter tests/test_precondition.py::TestInClass::test_instance_method tests/test_precondition.py::TestInClass::test_setter tests/test_precondition.py::TestInvalid::test_error_with_invalid_arguments tests/test_precondition.py::TestInvalid::test_no_boolyness tests/test_precondition.py::TestInvalid::test_unexpected_precondition_arguments
icontract/_decorators.py icontract/_checkers.py icontract/_types.py
icontract/_decorators.py icontract/_checkers.py icontract/_types.py