darkforestry/amms-rs

Fix/update simulate-swap example

vyorkin opened this issue · 3 comments

Currently it returns (prints) 0 as the amount_out value (when running in mainnet).
I took a quick look at the variables inside the UniswapV2Pool.get_amount_out fn:

fee=997 amount_in_with_fee=9970000 numerator=281249658069667830000 denominator=16758863713340495775670000

And

numenator / denominator = 281249658069667830000 / 16758863713340495775670000 = 0.0000167821 ~= 0

So the amount out for amount in of 10000 WETH should be 167821 USDC.

The calculations in get_amount_out look correct and 100% replicate those in the actual Uniswap V2 contract:

    function getAmountOut(
        uint256 _amountIn,
        uint256 _reserveIn,
        uint256 _reserveOut
    ) public pure returns (uint256) {
        if (_amountIn == 0) revert InsufficientAmount();
        if (_reserveIn == 0 || _reserveOut == 0) revert InsufficientLiquidity();

        uint256 amountInWithFee = _amountIn * 997;
        uint256 numerator = amountInWithFee * _reserveOut;
        uint256 denominator = (_reserveIn * 1000) + amountInWithFee;

        return numerator / denominator;
    }

Looks like a decimals issue.

Shouldn't it be this instead?

(numerator / denominator) * (10 ** token_in_decimals)
iht76 commented

I don't think so, the function is correct :

https://github.com/Uniswap/v2-periphery/blob/0335e8f7e1bd1e8d8329fd300aea2ef2f36dd19f/contracts/libraries/UniswapV2Library.sol#L43C113-L43C113

something is wrong with reserveIn/ ReserveOut numbers you got

997 shouldn't be hard coded as there are uV2 pools with different fees.

Currently it returns (prints) 0 as the amount_out value (when running in mainnet). I took a quick look at the variables inside the UniswapV2Pool.get_amount_out fn:

fee=997 amount_in_with_fee=9970000 numerator=281249658069667830000 denominator=16758863713340495775670000

And

numenator / denominator = 281249658069667830000 / 16758863713340495775670000 = 0.0000167821 ~= 0

So the amount out for amount in of 10000 WETH should be 167821 USDC.

The calculations in get_amount_out look correct and 100% replicate those in the actual Uniswap V2 contract:

    function getAmountOut(
        uint256 _amountIn,
        uint256 _reserveIn,
        uint256 _reserveOut
    ) public pure returns (uint256) {
        if (_amountIn == 0) revert InsufficientAmount();
        if (_reserveIn == 0 || _reserveOut == 0) revert InsufficientLiquidity();

        uint256 amountInWithFee = _amountIn * 997;
        uint256 numerator = amountInWithFee * _reserveOut;
        uint256 denominator = (_reserveIn * 1000) + amountInWithFee;

        return numerator / denominator;
    }

Looks like a decimals issue.

Shouldn't it be this instead?

(numerator / denominator) * (10 ** token_in_decimals)

Can you paste a code block of the quote you are testing?

It is the simulate-swap example.
The function get_amount_out of the UniswapV2 module (this is a single place that has numerator / denominator): https://github.com/darkforestry/amms-rs/blob/main/src/amm/uniswap_v2/mod.rs#L351-L361