-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Removes redundant partner argument from setTotalWithdraw. #251
Removes redundant partner argument from setTotalWithdraw. #251
Conversation
as described in raiden-network#238. Additionally, the function was refactored to be more clear and readable, as discussed in raiden-network#47.
9951d37
to
d75821d
Compare
d75821d
to
18156df
Compare
Channel storage channel = channels[channel_identifier]; | ||
Participant storage participant_state = channel.participants[participant]; | ||
Participant storage partner_state = channel.participants[partner]; | ||
|
||
total_deposit = participant_state.deposit + partner_state.deposit; | ||
// This should never happen, as we have an overflow check in setTotalDeposit | ||
assert(total_deposit >= participant_state.deposit); | ||
assert(total_deposit >= partner_state.deposit); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why were these moved? These were placed here in #248, after reopening #47 (comment) - after the internal audit discussion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved them here as described in #47. It states "the code finishes with the asserts/invariants"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, I considered readability to be more important. Why did you not comment on #248? It is very inefficient to change and revert code back and forth.
And this discussion is not in the scope of this PR, which should have only fixed the redundant partner
argument.
If you wish to change the order again, please do it in another PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tl;dr why are we discussing checks order in a PR that should have fixed something else?
Then I would rather have this discussed in a separate PR. Especially that this seems so important for you. The #248 was labeled for review. Anyone could have reviewed it and everyone is incentivized to review PRs regardless of assignment, especially if they have strong opinions.
|
||
// Entire withdrawn amount must not be bigger than the current channel deposit | ||
require(total_withdraw <= (total_deposit - partner_state.withdrawn_amount)); | ||
require((total_withdraw + partner_state.withdrawn_amount) <= total_deposit); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually better, but now I see that it misses an overflow check:
require(total_withdraw <= total_withdraw + partner_state.withdrawn_amount)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overflows are out of the agreed upon contracts scope here (i.e. assuming one misbehaving client max.) - signatures from both clients are required, so they would have to agree upon a corrupted withdrawal request, where one party would loose tokens. I can add a check anyhow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
signatures from both clients are required, so they would have to agree upon a corrupted withdrawal request
Correct. However, the overflow check that I mentioned makes sure that a participant (with a collaborating partner) cannot withdraw more tokens from the TokenNetwork
contract.
Issue: total_deposit
is big enough to cause an overflow on total_withdraw + partner_state.withdrawn_amount
& pass the check here: require((total_withdraw + partner_state.withdrawn_amount) <= total_deposit);
No other checks fail before require(token.transfer(participant, current_withdraw));
. This can potentially transfer a lot of tokens to participant
if the TokenNetwork
contract has enough tokens or if the token contract is not properly implemented.
participant_state.withdrawn_amount = total_withdraw; | ||
require(token.transfer(participant, current_withdraw)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you change the order? It reverts changes done in #248 - e.g. d034f81
This triggered a warning when static analysis tools were used, because emitting an event is considered a state change.
The pattern that was checked for is: make sure all the state changes are made before any external calls (e.g. token transfers).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made more sense to me to emit the event only after the require(transfer) did not throw. Otherwise if the event is emitted and code by a Node, it might be in an ill defined state no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the require(transfer)
throws, then all changes are reverted, including the event.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To explain a bit more:
The entire transaction (including all the calls to external contracts done inside the transaction) is atomic.
Emitted events cannot be accessed from inside the EVM. They are for the outside world. Therefore, there cannot be a pattern where somehow, the emitted event can be used maliciously inside the EVM before the transaction is reverted due to an external call (it is not possible to have some kind of cross-function race condition with events)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok thx for the explanation, I'll place it back to where it was.
ecd81a2
to
ca005d0
Compare
Added overflow check to withdraw function.
ca005d0
to
6bb090d
Compare
`partner` argument was removed from `setTotalWithdraw` in raiden-network/raiden-contracts#251
Removes redundant partner argument from
setTotalWithdraw
, as described in #238. Additionally, the function was refactored to be more clear and readable, as discussed in #47. Closes #238.