Canto Application Specific Dollars and Bonding Curves for 1155s - Matin's results

Tokenizable bonding curves using a Stablecoin-as-a-Service token

General Information

Platform: Code4rena

Start Date: 13/11/2023

Pot Size: $24,500 USDC

Total HM: 3

Participants: 120

Period: 4 days

Judge: 0xTheC0der

Id: 306

League: ETH

Canto

Findings Distribution

Researcher Performance

Rank: 80/120

Findings: 1

Award: $4.08

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

4.0797 USDC - $4.08

Labels

bug
downgraded by judge
grade-b
QA (Quality Assurance)
satisfactory
duplicate-25
Q-34

External Links

Lines of code

https://github.com/code-423n4/2023-11-canto/blob/main/1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol#L42 https://github.com/code-423n4/2023-11-canto/blob/main/1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol#L30

Vulnerability details

Impact

Precision loss in Log2 calculation leads to wrong fee calculation in the contract LinearBondingCurve

Proof of Concept

The current Log2 calculation which is inspired from the Solady library, uses the most significant bit scheme:

    function log2(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            // forgefmt: disable-next-item
            r := or(
                r,
                byte(
                    and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
                    0x0706060506020504060203020504030106050205030304010505030400000000
                )
            )
        }
    }

This algorithm is vulnerable to round-off error which rounds the number to its floor. For example, if the actual Log2 of a number equals to 20.999 this algorithm will return 20. By default, this algorithm works well with high decimal numbers such as wads (~18) or rays (~27) as the discrepancy makes not such a big difference. If the number is relatively small, the slope and thus the discrepancy is bigger. If we look at the application of this function in the bonding curve based algorithm, we will find out that it is being used in the function getFee() in the contract LinearBondingCurve:

    function getFee(uint256 shareCount) public pure override returns (uint256) {
        uint256 divisor;
        if (shareCount > 1) {
            divisor = log2(shareCount);
        } else {
            divisor = 1;
        }
        // 0.1 / log2(shareCount)
        return 1e17 / divisor;
    }

As we can see, the log2() is used for the divisor calculation with the input of the shareCount. This number shows the number of tokens a person has. The vulnerable part starts from here, as the abovementioned discrepancy would decrease the precision.

For a POC, let's consider these scenarios:

Case NumberShare CountCurrent Log2()Actual Log2()Current getFee()Actual getFee()Discrepancy (%)
[01]311.5851e176.3e1658
[02]1233.5853.3e162.5e1632
[03]1533.9073.3e162.7e1622

These errors shows a large precision loss in the fees which currently charges the users more than the actual ones which is due to the fact that this mechanism doesn't ceil a number which is near to its nearest integer number. I understand that this is due to the fact that Solidity doesn't support decimal numbers, though, for a fair fee calculation, the system should check the nearest number and decide to round the number to its floor or ceil.

Tools Used

Manual Review

Short-term: Consider checking the nearest integer number and fairly round the number (especially if the number is less than 8) Long-term: Use a more accurate Taylor-based (with third order truncation error to lower the gas) considering a basis point of 1000.

log2(x)=1ln(2)(ln(5)ln(2)+25(x52)225(x52)2+O((x52)3))\log_2(x)= \frac{1}{\ln(2)}\left(\ln \left( 5 \right) -\ln \left( 2 \right) +{\frac {2}{5}} \left( x -{\frac {5}{2}} \right) -{\frac {2}{25}} \left( x-{\frac {5}{2}} \right) ^{2} +O \left( \left( x-{\frac {5}{2}} \right) ^{3} \right)\right)

Assessed type

Math

#0 - c4-pre-sort

2023-11-18T13:03:27Z

minhquanym marked the issue as duplicate of #25

#1 - c4-judge

2023-11-29T15:25:47Z

MarioPoneder changed the severity to 2 (Med Risk)

#2 - c4-judge

2023-11-29T15:26:43Z

MarioPoneder marked the issue as satisfactory

#3 - c4-judge

2023-11-30T20:57:28Z

MarioPoneder changed the severity to QA (Quality Assurance)

#4 - c4-judge

2023-11-30T20:58:54Z

MarioPoneder marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter