UlyssesToken
asset ID accounting error
#275
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
H-25
primary issue
Highest quality submission among a set of duplicates
satisfactory
satisfies C4 submission criteria; eligible for awards
selected for report
This submission will be included/highlighted in the audit report
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
upgraded by judge
Original issue severity upgraded from QA/Gas by judge
Lines of code
https://github.com/code-423n4/2023-05-maia/blob/54a45beb1428d85999da3f721f923cbf36ee3d35/src/ulysses-amm/UlyssesToken.sol#L72
Vulnerability details
Impact
Asset IDs in the
UlyssesToken
contract are 1-based, see L49 in UlyssesToken.addAsset(...) and L55 in ERC4626MultiToken.constructor(...) of the parent contract.However, when removing an asset from the
UlyssesToken
contract, the last added asset gets the 0-based ID of the removed asset, see L72 in UlyssesToken.removeAsset(...).This leads to the following consequences:
Example: We have assets with IDs
1,2,3,4
. Next, asset with ID=2 is removed. Now we have assets with IDs1,1,3
because the last asset with ID=4 gets ID=2-1=1.Example: Once the first asset with ID=1 is removed, the last asset gets ID=0 instead of ID=1. When trying to remove the last asset L62 in UlyssesToken.removeAsset(...) will revert due to underflow.
Example: Once the first asset with ID=1 is removed, the last asset gets ID=0 instead of ID=1. When trying to add the last asset again L45 in UlyssesToken.addAsset(...) will not revert since ID=0 indicates that the asset wasn't added yet. Therefore, the underlying vault can contain the same token twice with different weights.
In conclusion, the asset accounting of the
UlyssesToken
contract is broken after removing an asset (especially the first one). This was also highlighted as a special area of concern in the audit details:ulysses AMM and token accounting
Proof of Concept
The above issues are demostrated by the new test cases
test_UlyssesTokenAddAssetTwice
andtest_UlyssesTokenRemoveAssetFail
, just apply the diff below and run the tests withforge test --match-test test_UlyssesToken
.We can see that adding the last asset again does not revert but trying to remove it still fails:
Tools Used
VS Code, Foundry, MS Excel
Recommended Mitigation Steps
Fortunately, all of the above issues can be easily fixed by using an 1-based asset ID in L72 of UlyssesToken.removeAsset(...):
After applying the recommended fix, both new test cases pass:
Assessed type
Under/Overflow
The text was updated successfully, but these errors were encountered: