The reason that in the DelegateRegistry contract there's some payable function is because users can tip the contract and then owner can receive it using sweep() later.
But in the DelegateToken contract, there's no way to send the tipping to the DelegateRegistry contract. Moreover, there's no use-case of users execute to the DelegateRegistry directly. Because of that, the protocol is not receiving tipping effectively.
Proof of Concept
The only function in the DelegateToken that payble is flashloan(), which is not sending its value to the DelegateRegistry contract
function flashloan(Structs.FlashInfo calldata info) external payable nonReentrant {
StorageHelpers.revertNotOperator(accountOperator, info.delegateHolder);
if (info.tokenType == IDelegateRegistry.DelegationType.ERC721) {
...
Helpers.revertOnCallingInvalidFlashloan(info);
...
} else if (info.tokenType == IDelegateRegistry.DelegationType.ERC20) {
...
Helpers.revertOnCallingInvalidFlashloan(info);
...
} else if (info.tokenType == IDelegateRegistry.DelegationType.ERC1155) {
...
Helpers.revertOnCallingInvalidFlashloan(info);
...
}
}
function revertOnCallingInvalidFlashloan(DelegateTokenStructs.FlashInfo calldata info) internal {
if (IDelegateFlashloan(info.receiver).onFlashloan{value: msg.value}(msg.sender, info) == IDelegateFlashloan.onFlashloan.selector) return;
revert IDelegateFlashloan.InvalidFlashloan();
}
Tools Used
Manual Review
Recommended Mitigation Steps
Add tipping mechanism to create() and withdraw() function in DelegateToken contract
Lines of code
https://github.com/code-423n4/2023-09-delegate/blob/a6dbac8068760ee4fc5bababb57e3fe79e5eeb2e/src/libraries/DelegateTokenLib.sol#L91-L94 https://github.com/code-423n4/2023-09-delegate/blob/a6dbac8068760ee4fc5bababb57e3fe79e5eeb2e/src/DelegateToken.sol#L389-L410
Vulnerability details
Impact
The reason that in the
DelegateRegistry
contract there's some payable function is because users can tip the contract and then owner can receive it usingsweep()
later. But in theDelegateToken
contract, there's no way to send the tipping to theDelegateRegistry
contract. Moreover, there's no use-case of users execute to theDelegateRegistry
directly. Because of that, the protocol is not receiving tipping effectively.Proof of Concept
The only function in the
DelegateToken
that payble isflashloan()
, which is not sending its value to theDelegateRegistry
contractTools Used
Manual Review
Recommended Mitigation Steps
Add tipping mechanism to
create()
andwithdraw()
function inDelegateToken
contractAssessed type
Other