Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect Precision in get_virtual_price() Calculation #109

Open
hats-bug-reporter bot opened this issue Oct 15, 2024 · 1 comment
Open

Incorrect Precision in get_virtual_price() Calculation #109

hats-bug-reporter bot opened this issue Oct 15, 2024 · 1 comment
Labels
bug Something isn't working invalid This doesn't seem right

Comments

@hats-bug-reporter
Copy link

Github username: --
Twitter username: --
Submission hash (on-chain): 0x994d521d911f2bd3bbc2b43c699b07b5427851838d5c5969f39690e96d595615
Severity: high

Description:
Description
The get_virtual_price() function in the StableSwapTwoPool.sol and StableSwapThreePool.solcontract calculates the virtual price of the pool's LP token using a precision of 1e18. This approach does not account for the actual decimals of the LP token, which leads to incorrect virtual price calculations.

function get_virtual_price() external view returns (uint256) {
    uint256 D = get_D(_xp(), get_A());
    uint256 token_supply = token.totalSupply();
    return (D * PRECISION) / token_supply; //@audit-incorrect precision,it should be D*token.decimals/token_supply
}

Attack Scenario
Lets understand issue with example:

  • The invariant D is calculated as 1e18(as get_D returns scaled value i.e 1e18).
  • The total supply of the LP token is (1e6).
  • The LP token has 6 decimals.

Current Calculation:(INCORRECT)

uint256 virtualPrice = (D * PRECISION) / token_supply;
// virtualPrice = (1e18 * 1e18) / 1e6 = 1e36 / 1e6 = 1e30

Expected Calculation with Correct Decimals:

uint256 tokenDecimals = 6;
uint256 virtualPrice = (D * (10 ** tokenDecimals)) / token_supply;
// virtualPrice = (1e18 * 1e6) / 1e6 = 1e24 / 1e6 = 1e18

As we can see here the current implementation returns incorrect virtual price
Attachments

  1. Proof of Concept (PoC) File
  1. Revised Code File (Optional)
function get_virtual_price() external view returns (uint256) {
    uint256 D = get_D(_xp(), get_A());
    uint256 token_supply = token.totalSupply();
    uint256 tokenDecimals = IERC20Metadata(address(token)).decimals();
    return (D * (10 ** tokenDecimals)) / token_supply;
}
  • By implementing this change, the function will correctly calculate the virtual price
@hats-bug-reporter hats-bug-reporter bot added the bug Something isn't working label Oct 15, 2024
@omega-audits
Copy link

The LP token is hardcoded to 18 decimals so this will never be an issue

@omega-audits omega-audits added the invalid This doesn't seem right label Oct 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

1 participant