Open code423n4 opened 2 years ago
https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L816 https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L668 https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L681 https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L743 https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L785 https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L859
The JBController contract performs many unsafe casts uint256 to int256 and int256 to uint256 In example:
uint256
int256
-1
2**256 - 1
2**255
- 2**255
int256 to uint256:
if (uint256(_processedTokenTrackerOf[_projectId]) != tokenStore.totalSupplyOf(_projectId))
uint256 to int256:
int256(_tokenCount);
int256(beneficiaryTokenCount);
_processedTokenTrackerOf[_projectId] = int256(tokenStore.totalSupplyOf(_projectId));
_processedTokenTrackerOf[_projectId] = int256(_totalTokens + tokenCount);
Note: in the L1076 and L1077 there are two more casts but in the L1075 check the cast
Review
Use a SafeCast library of openzeppelin toUint256(int256 value) and toInt256(uint256 value) or check the number before cast it
toUint256(int256 value)
toInt256(uint256 value)
acknowledged here https://info.juicebox.money/dev/learn/risks#large-number-risk
Lines of code
https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L816 https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L668 https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L681 https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L743 https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L785 https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/733810a0339a5c0cb608345e6fc66a6edeac13cc/contracts/JBController.sol#L859
Vulnerability details
Impact
The JBController contract performs many unsafe casts
uint256
toint256
andint256
touint256
In example:-1
(int256) to uint256 was2**256 - 1
2**255
(uint256) to int256 was- 2**255
Proof of Concept
int256
touint256
:if (uint256(_processedTokenTrackerOf[_projectId]) != tokenStore.totalSupplyOf(_projectId))
uint256
toint256
:int256(_tokenCount);
int256(beneficiaryTokenCount);
int256(_tokenCount);
_processedTokenTrackerOf[_projectId] = int256(tokenStore.totalSupplyOf(_projectId));
_processedTokenTrackerOf[_projectId] = int256(_totalTokens + tokenCount);
Tools Used
Review
Recommended Mitigation Steps
Use a SafeCast library of openzeppelin
toUint256(int256 value)
andtoInt256(uint256 value)
or check the number before cast it