You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Using self.env().transferred_value() inside a loop is a dangerous pattern, as it typically assumes that this value will be updated each iteration.
The Opyn vulnerability described in the ToB and PeckShield blogs could be reduced to the following minimal example in ink!:
#[ink::contract]pubmod target {#[ink(storage)]pubstructTarget{balances:Mapping<AccountId,Balance>,receivers:Mapping<i64,AccountId>,}#[ink(message)]pubfnadd_balance(&mutself){for i in0..balances.len(){self.balances[self.receivers[i]] += self.env().transferred_value();}}}
In that example, add_balance might be called for multiple receivers, increasing the balance for each of them, despite the fact that the contract has received only one msg.value. The business logic of the contract might assume that balances is used to pay funds to the users, therefore, this vulnerability might lead to draining the contract.
The suggested implementation should check the following:
Accessing self.env().transferred_value() in loops of message functions. We must check for and similar control-flow statements. And it would be great to check these inside closures for iter_mut loops.
Using self.env().transferred_value() in private functions. If some private function is accessing self.env().transferred_value() and is called in a loop of other function, it should be highlighted.
Ideally, we should also check local variables that might be assigned to self.env().transferred_value(). It could be done using MIR dataflow framework, but it might unnecessarily complicate the implementation.
The text was updated successfully, but these errors were encountered:
Using
self.env().transferred_value()
inside a loop is a dangerous pattern, as it typically assumes that this value will be updated each iteration.The Opyn vulnerability described in the ToB and PeckShield blogs could be reduced to the following minimal example in ink!:
In that example,
add_balance
might be called for multiple receivers, increasing the balance for each of them, despite the fact that the contract has received only onemsg.value
. The business logic of the contract might assume thatbalances
is used to pay funds to the users, therefore, this vulnerability might lead to draining the contract.The suggested implementation should check the following:
self.env().transferred_value()
in loops ofmessage
functions. We must checkfor
and similar control-flow statements. And it would be great to check these inside closures foriter_mut
loops.self.env().transferred_value()
in private functions. If some private function is accessingself.env().transferred_value()
and is called in a loop of other function, it should be highlighted.Ideally, we should also check local variables that might be assigned to
self.env().transferred_value()
. It could be done using MIR dataflow framework, but it might unnecessarily complicate the implementation.The text was updated successfully, but these errors were encountered: