Open code423n4 opened 1 year ago
asselstine marked the issue as sponsor confirmed
I think this report is incorrect no @asselstine?
It's intended behaviour to revert if you're trying to delegate to the same address that's already delegated to. In this case you're trying to delegate from SPONSORSHIP_ADDRESS
to SPONSORSHIP_ADDRESS
(because 0 is now arbitrarily mapped to SPONSORSHIP_ADDRESS
).
The new implementation has changed the "reset" behaviour to specify the user address rather than address(0) to undelegate (i.e. delegate back to yourself).
The new implementation has changed the "reset" behaviour to specify the user address rather than address(0) to undelegate (i.e. delegate back to yourself).
Actually, the new implementation attempted to undelegate by delegating to the SPONSORSHIP_ADDRESS if the address in the delegate() was passed as the 0x address. See the comment in the TwabController::_delegate()
Exactly my point! Why is forcing the delegation to the SPONSORSHIP_ADDRESS
any different to forcing the delegation to the user address when calling with address(0)
?
With your suggested change, If I had delegated to myself and then tried to delegate to address(0)
then the transaction would also revert.
The sponsor has decided to map address(0)
to the SPONSORSHIP_ADDRESS
and there isn't anything invalid about that imo
Because setting the current_delegate to the SPONSORSHIP_ADDRESS can be done not only by the new undelegation logic.
Users using the Vault:sponsor()
function will get their current_delegate
to the SPONSORSHIP_ADDRESS, and then if they'd like to undelegate by passing the address(0), the undelegation will fail because current_delegate
is already the SPONSORSHP_ADDRESS.
If a user has delegated to themselves then there is no need to undelegate, their delegate_balance is already on their hands.
But if a user has delegated to the sponsorship_address through the Vault:sponsor(), then there is required to undelegate and get their delegate_balance back on their hands
Hmm the reproduction didn't work; this test failed as it should.
Need to dig in.
@asselstine The test is expected to fail with the message "Reason: SameDelegateAlreadySet(0x0000000000000000000000000000000000000001)] "
Ok let me phrase this another way. Why does delegating to address(0)
have to be considered "undelegating"? Why can't it be considered as "sponsoring"? I agree with you it's more logical to sponsor back to yourself, but just because it doesn't I don't think that's a bug.
The worst case scenario is:
SPONSORSHIP_ADDRESS
address(0)
to reset their delegation but the transaction reverts because delegating to address(0)
is the same as delegating to SPONSORSHIP_ADDRESS
The end result is 1 reverted transaction with no funds lost, so surely QA at best?
I'm sure we could go round in circles with this anyway haha
I believe I see the confusion: the implementation doesn't match the intent. It does work, however. It needs clarification!
I believe this is comment is the problem:
L646: // Treat address(0) as un-delegating
Because the comments also say:
L646: ... this lets
// them do so without knowing the sponsorship special value address.
The "this" is referring to address(0).
So in the same breath it's saying address(0) is used to un-delegate but is also used as an alias for the SPONSORSHIP_ADDRESS. So which is it?
I do like having address(0)
interpreted as sponsorship. They are essentially burning their chance; this intuitive to me.
I also think removing the erroneous comment and adding some additional natspec on undelegating by delegating to yourself.
okaay, so, looks like @asselstine has cleared all the doubts, so, I think you are right @djb15 , it could be a QA.
Thanks @asselstine for summarizing and explaining what was the intention of the address(0).
Thanks for your explanations everyone. Will downgrade this to QA.
Picodes changed the severity to QA (Quality Assurance)
Picodes marked the issue as grade-b
Lines of code
https://github.com/GenerationSoftware/pt-v5-twab-controller/blob/main/src/TwabController.sol#L645-L651
Vulnerability details
Original Issue
H-06 - Resetting delegation will result in user funds being lost forever
Details
The previous implementation to reset the delegation was causing that the users lost their own delegate balance if they tried to reset the delegation to themselves by setting the
_to
parameter as the address(0), which that is the value used to determine if a user is the delegate or not.Mitigation
The implemented mitigation is attempting to treat the value of the
_to
parameter to be used as indicative of an undelegation operation._to
parameter is the address(0), the delegate will be set to theSPONSORSHIP_ADDRESS
, otherwise it will not be updated.Conclusion of the Mitigation and Proof of Concept of the new Bug
This mitigation introduces a new bug in the undelegation process.
_currentDelegate
is already theSPONSORSHIP_ADDRESS
, and the user set_to
as the address(0), theto
address will be set also as theSPONSORSHIP_ADDRESS
, this will cause the execution to be reverted because theto
address is equals to the_currentDelegate
.There are different ways how the
_currentDelegate
could end up being set to theSPONSORSHIP_ADDRESS
, one of them is if the user calls the sponsor() in the Vault contract._currentDelegate
is already set to theSPONSORSHIP_ADDRESS
and the user wants to undelegate its delegate balance by passing the address(0) as theto
parameter.Coded PoC
forge test -m testFirstSponsorshipAndThenUndelegate -vvvv
And this is the expected result, the tx to delegate to the address(0) should revert with the error message: "SameDelegateAlreadySet"Test result: FAILED. 0 passed; 1 failed; finished in 2.36ms
Failing tests: Encountered 1 failing test in test/TwabController.t.sol:TwabControllerTest [FAIL. Reason: SameDelegateAlreadySet(0x0000000000000000000000000000000000000001)] testFirstSponsorshipAndThenUndelegate() (gas: 109875)
Assessed type
Context