Closed code423n4 closed 2 years ago
The casting is done using u128()
which is a yield-utils function which checks for overflow, see CastU256U128 :
vlibrary CastU256U128 {
/// @dev Safely cast an uint256 to an uint128
function u128(uint256 x) internal pure returns (uint128 y) {
require (x <= type(uint128).max, "Cast overflow");
y = uint128(x);
u128() function is not used when passing parameters from payFYToken() internally to _updateAccounting function at the input level. @KenzoAgada
Hmm... _updateAccounting
receives inkOut
and artIn
as uint256.
But in the end it converts them to uint128, reverting if they don't fit. So it will revert. Am I missing something?
You're right @KenzoAgada. I was confused assuming the flow on the other direction uint256 -> uint128
Disputed, @KenzoAgada explained why.
Agree with Kenzo, the casting to uint128 happens in the _updateAccounting
function. So it will revert there if the value doesn't fit in a uint128.
For this reason, I have labelled this issue as invalid.
Lines of code
https://github.com/code-423n4/2022-07-yield/blob/6ab092b8c10e4dabb470918ae15c6451c861655f/contracts/Witch.sol#L409-L414 https://github.com/code-423n4/2022-07-yield/blob/6ab092b8c10e4dabb470918ae15c6451c861655f/contracts/Witch.sol#L344-L361 https://github.com/code-423n4/2022-07-yield/blob/6ab092b8c10e4dabb470918ae15c6451c861655f/contracts/Witch.sol#L443-L444
Vulnerability details
Impact
In the
_updateAccounting
function, theinkOut
andartIn
parameters are cast from type uint256 to uint128. However, since the explicit cast does not ensure the value fits the uint128 data type (i.e., not ensuring value <= type(uint128).max), casting overflows are possible, causing the results to be incorrect.Proof of Concept
The parameters are accepted as uint128 in the below code;
https://github.com/code-423n4/2022-07-yield/blob/6ab092b8c10e4dabb470918ae15c6451c861655f/contracts/Witch.sol#L409-L414
But the previous function -
payFYToken()
- which calls_updateAccounting
function internally has the parameters in different datatype - uint256;https://github.com/code-423n4/2022-07-yield/blob/6ab092b8c10e4dabb470918ae15c6451c861655f/contracts/Witch.sol#L344-L361
And finally, both parameters are cast to uint128 as below;
https://github.com/code-423n4/2022-07-yield/blob/6ab092b8c10e4dabb470918ae15c6451c861655f/contracts/Witch.sol#L443-L444
An actor who can manage to artificially create max debt in uint256 type in a vault can pay his debt with a lower value in an auction that he initiated due to this overflow.
Tools Used
Manual review
Recommended Mitigation Steps
The team might consider adding casting overflow checks for the above-mentioned lines.