-
CVSS Score
-| Package Name | Ecosystem | Vulnerable Versions | First Patched Version |
|---|---|---|---|
| vyper | pip | <= 0.4.0 | 0.4.1 |
The vulnerability stems from two key components:
event I:
i: uint256
x: uint256
@deploy
def __init__():
self.x = 0
@external
def test():
for i: uint256 in [self.usesideeffect(), self.usesideeffect(), self.usesideeffect()]:
self.x += 1
log I(i)
@view
def usesideeffect() -> uint256:
return self.x
However, in the next two examples, because the iterator target is not a list literal, it will be evaluated in the loop body. In the second example, iter_list is an ifexp, thus it will be evaluated lazily in the loop body. The log output will be 0, 1, 2 due to consumption of side effects.
event I:
i: uint256
x: uint256
@deploy
def __init__():
self.x = 0
@external
def test():
for i: uint256 in ([self.usesideeffect(), self.usesideeffect(), self.usesideeffect()] if True else self.otherclause()):
self.x += 1
log I(i)
@view
def usesideeffect() -> uint256:
return self.x
@view
def otherclause() -> uint256[3]:
return [0, 0, 0]
In the third example, iter_list is also an ifexp, thus it will only be evaluated in the loop body. The log output will be 0, 1, 2 due to consumption of side effects.
event I:
i: uint256
x: uint256[3]
@deploy
def __init__():
self.x = [0, 0, 0]
@external
def test():
for i: uint256 in (self.usesideeffect() if True else self.otherclause()):
self.x[0] += 1
self.x[1] += 1
self.x[2] += 1
log I(i)
@view
def usesideeffect() -> uint256[3]:
return self.x
@view
def otherclause() -> uint256[3]:
return [0, 0, 0]