Sicherheitsprüfung für Cakepie-Verträge

Sicherheitsauditbericht für Cakepie Contracts, November 2023.

Sicherheitsprüfung für Cakepie-Verträge

Berichtsbogen

Punkt Beschreibung
Kunde Magpie XYZ
Ziel CakePie Verträge

Versionshistorie

Version Datum Beschreibung
1.0 30. November 2023 Erste Veröffentlichung

1. Einleitung

1.1 Über Zielverträge

Information Beschreibung
Typ Intelligenter Vertrag
Sprache Solidity
Ansatz Halbautomatische und manuelle Überprüfung

Ziel dieser Prüfung ist das Code-Repository von CakePie Contracts^1 von Magpie XYZ. Die CakePie Contracts führen eine CakeRush-Kampagne aus, bei der Benutzer ihren CAKE-Token oder ihre gesperrte CAKE-Position von PancakeSwap auf CakePie umwandeln können. Bitte beachten Sie, dass nur CakeRush.sol und PancakeStakingBNBChain.sol im Prüfumfang enthalten sind, während andere Dateien für diese Prüfung außerhalb des Umfangs liegen.

Der Prüfprozess ist iterativ. Insbesondere prüfen wir die Commits, die die gefundenen Probleme beheben. Wenn neue Probleme auftreten, setzen wir diesen Prozess fort. Die Commit-SHA-Werte während der Prüfung sind in der folgenden Tabelle aufgeführt. Unser Prüfbericht ist für den Code in der Erstversion (Version 1) sowie für neuen Code (in den folgenden Versionen) zur Behebung von Problemen im Prüfbericht verantwortlich.

1.2 Sicherheitsmodell

Zur Risikobewertung folgen wir den Standards oder Vorschlägen, die sowohl in der Industrie als auch in der Wissenschaft weit verbreitet sind, einschließlich der OWASP Risk Rating Methodology ^2 und der Common Weakness Enumeration ^3. Die allgemeine Schwere des Risikos wird durch Wahrscheinlichkeit und Auswirkung bestimmt. Insbesondere wird die Wahrscheinlichkeit verwendet, um abzuschätzen, wie wahrscheinlich eine bestimmte Schwachstelle von einem Angreifer entdeckt und ausgenutzt werden kann, während die Auswirkung verwendet wird, um die Folgen einer erfolgreichen Ausnutzung zu messen.

In diesem Bericht sind sowohl Wahrscheinlichkeit als auch Auswirkung in zwei Kategorien eingeteilt, nämlich hoch und niedrig bzw. ihre Kombinationen sind in Tabelle 1.1 aufgeführt.

Dementsprechend werden die in diesem Bericht gemessenen Schweregrade in drei Kategorien eingeteilt: Hoch, Mittel, Niedrig. Der Vollständigkeit halber wird Unbestimmt auch verwendet, um Umstände abzudecken, bei denen das Risiko nicht gut bestimmt werden kann.

Darüber hinaus fällt der Status eines gefundenen Elements in eine der folgenden vier Kategorien:

  • Unbestimmt Noch keine Antwort.

  • Bestätigt Der Punkt wurde vom Kunden erhalten, aber noch nicht bestätigt.

  • Bestätigt Der Punkt wurde vom Kunden anerkannt, aber noch nicht behoben.

  • Behoben Der Punkt wurde vom Kunden bestätigt und behoben.

2. Ergebnisse

Insgesamt finden wir zwei potenzielle Probleme. Außerdem haben wir drei Empfehlungen und eine Anmerkung.

  • Hohes Risiko: 1

  • Niedriges Risiko: 1

  • Empfehlung: 3

  • Hinweis: 1

ID Schwere Beschreibung Kategorie Status
1 Niedrig Möglicher inkonsistenter Zustand nach Parameter-Reset Software-Sicherheit Behoben
2 Hoch Wiederholter Anspruch von mCake-Belohnungen Software-Sicherheit Behoben
3 - Prüfen Sie die Parameter in den Initialisierungsfunktionen Empfehlung Bestätigt
4 - Prüfen Sie die Parameter in den CakeRush-Verträgen Empfehlung Behoben
5 - Zusätzliche Bedingungen in Modifikatoren Empfehlung Bestätigt
6 - Potenzielles Zentralisierungsrisiko Hinweis -

Die Details sind in den folgenden Abschnitten aufgeführt.

2.1 Software-Sicherheit

2.1.1 Möglicher inkonsistenter Zustand nach Parameter-Reset

Artikel Beschreibung
Schwere Niedrig
Status Behoben in Version 2
Eingeführt von Version 1

Beschreibung Der CakeRush-Vertrag verteilt Belohnungen gemäß mehreren Parametern. Die folgenden Funktionen ermöglichen es dem Projektmanager, einige der Parameter zurückzusetzen:

function resetMultiplier() external onlyOwner {
        uint256 len = rewardMultiplier.length;
        for (uint8 i = 0; i < len; ++i) {
            rewardMultiplier.pop();
            rewardTier.pop();
        }

        tierLength = 0;
    }

    function resetTimeWeighting() external onlyOwner {
        uint256 len = weightedTime.length;
        for (uint8 i = 0; i < len; ++i) {
            weightedTime.pop();
            weighting.pop();
        }

        weightLength = 0;
    }

Auflistung 2.1: CakeRush.sol

Diese Funktionen setzen jedoch nur die Parameter zurück, nicht jedoch die im userInfos-Zustandsvariablen gespeicherten Benutzerinformationen. Infolgedessen können Berechnungen im CakeRush-Vertrag aufgrund des inkonsistenten Zustands fehlschlagen. Wenn beispielsweise die Parameter zurückgesetzt und auf falsche Werte gesetzt werden, kann die Subtraktion in Zeile 155 aufgrund von Integer-Unterläufen fehlschlagen.

function quoteConvert(
        uint256 _amountToConvert,
        address _account
    )
        external
        view
        returns (
            uint256 newUserFactor,
            uint256 newTotalFactor,
            uint256 newUserWeightedFactor,
            uint256 newWeightedTotalFactor
        )
    {
        if (_amountToConvert == 0 || rewardMultiplier.length == 0 || weighting.length == 0)
            return (0, 0, 0, 0);

        UserInfo storage userInfo = userInfos[_account];
        uint256 accumulated = _amountToConvert + userInfo.converted;

        uint256 factorAccuNoWeighting = 0;
        uint256 i = 1;
        while (i < rewardTier.length && accumulated > rewardTier[i]) {
            factorAccuNoWeighting += (rewardTier[i] - rewardTier[i - 1]) * rewardMultiplier[i - 1];
            i++;
        }
        factorAccuNoWeighting += (accumulated - rewardTier[i - 1]) * rewardMultiplier[i - 1];

        uint256 factorToEarnNoWeighting = (factorAccuNoWeighting / DENOMINATOR) - userInfo.factor;

Auflistung 2.2: CakeRush.sol

Was noch schlimmer ist: Wenn Benutzer convert oder convertWithCakePool unmittelbar nach dem Zurücksetzen der Parameter aufrufen (bevor die neuen Parameter festgelegt werden, z. B. durch Backrunning), kann dies zum Zurücksetzen der im Vertrag gespeicherten Gesamt- und gewichteten Faktoren führen, aufgrund der Logik in Zeile 141-142.

Auswirkung Das Zurücksetzen von Parametern kann zu inkonsistenten und falschen Zuständen führen.

Vorschlag Setzen Sie die neuen Parameter nach dem Löschen der alten.

Feedback vom Projekt Multiplikatoren werden nicht zurückgesetzt, sobald die Cake-Rush-Kampagne beginnt.

2.1.2 Wiederholter Anspruch von mCake-Belohnungen

Artikel Beschreibung
Schwere Hoch
Status Behoben in Version 3
Eingeführt von Version 2

Beschreibung Nach dem Sperren von CAKE-Token im Vertrag können Benutzer mCake-Token als Belohnungen über die Funktion beanspruchen. Die Funktion enthält jedoch ein Problem, das es Benutzern ermöglicht, die Belohnungen mehrmals zu beanspruchen. Im folgenden Code-Segment, wenn der Betrag größer ist als der des Benutzers, wird dem Benutzer ein Gesamtbetrag von transferiert oder eingezahlt. Die korrekte Implementierung sollte nur zurückgeben, sodass die aktuelle Implementierung es einem Benutzer effektiv ermöglicht, mCake-Belohnungen wiederholt zu beanspruchen.

function claim(bool _isStake) external nonReentrant {
        UserInfo storage userInfo = userInfos[msg.sender];
        if (claimedMCake[msg.sender] >= userInfo.converted) revert AlreadyClaimed();
        if (_isStake && userInfo.converted > 0) {
            if (masterCakepie == address(0)) revert MasterCakepieNotSet();
            IERC20(mCakeOFT).safeApprove(address(masterCakepie), userInfo.converted);
            IMasterCakepie(masterCakepie).depositFor(
                address(mCakeOFT),
                address(msg.sender),
                userInfo.converted
            );
        } else if (userInfo.converted > 0) {
            IERC20(mCakeOFT).transfer(msg.sender, userInfo.converted);
            emit Claim(msg.sender, userInfo.converted);
        }

        claimedMCake[msg.sender] = userInfo.converted;
    }

Auflistung 2.3: CakeRush.sol

Auswirkung Benutzer können mCake-Belohnungen wiederholt beanspruchen.

Vorschlag Überarbeiten Sie die Logik für die Belohnungsansprüche.

2.2 Zusätzliche Empfehlung

2.2.1 Prüfen Sie die Parameter in den Initialisierungsfunktionen

Artikel Beschreibung
Status Bestätigt
Eingeführt von Version 1

Beschreibung In den Initialisierungsfunktionen der Verträge CakeRush und PancakeStakingBNBChain gibt es Parameter, die nach der Initialisierung nicht mehr geändert werden können. Es wird empfohlen, dass diese Parameter in den Initialisierungsfunktionen überprüft werden.

function __CakeRush_init(
        address _cake,
        address _mCakeOFT,
        address _masterCakepie
    ) public initializer {
        __Ownable_init();
        __ReentrancyGuard_init();
        __Pausable_init();
        cake = _cake;
        mCakeOFT = _mCakeOFT;
        masterCakepie = _masterCakepie;
    }

Auflistung 2.4: CakeRush.sol

Auswirkung N/A

Vorschlag Prüfen Sie die Parameter in den Initialisierungsfunktionen.

2.2.2 Prüfen Sie die Parameter in den CakeRush-Verträgen

Artikel Beschreibung
Status Behoben in Version 2
Eingeführt von Version 1

Beschreibung Im CakeRush-Vertrag können mehrere Parameter bezüglich der Belohnungsverteilung hinzugefügt werden. Es gibt jedoch keine Prüfung, ob diese Parameter gemäß den Annahmen im Vertrag korrekt gesetzt sind. Insbesondere in den Funktionen setMultiplier und setTimeWeighting müssen zusätzliche Bedingungen geprüft werden (d. h. die monoton steigende Eigenschaft des rewardTier- und weightedTime-Arrays).

function setMultiplier(
        uint256[] calldata _multiplier,
        uint256[] calldata _tier
    ) external onlyOwner {
        if (_multiplier.length == 0 || (_multiplier.length != _tier.length)) revert LengthInvalid();

        for (uint8 i = 0; i < _multiplier.length; ++i) {
            if (_multiplier[i] == 0) revert InvalidAmount();
            rewardMultiplier.push(_multiplier[i]);
            rewardTier.push(_tier[i]);
            tierLength += 1;
        }
    }

Auflistung 2.5: CakeRush.sol

Auswirkung N/A

Vorschlag Prüfen Sie die Parameter in den Funktionen, die die Parameter setzen.

2.2.3 Zusätzliche Bedingungen in Modifikatoren

Artikel Beschreibung
Status Bestätigt
Eingeführt von Version 1

Beschreibung Im CakeRush-Vertrag hat der _onlyPancakeStaking-Modifikator eine überflüssige Bedingung. Gemäß der Semantik dieses Modifikators wäre die Prüfung msg.sender != pancakeStaking ausreichend.

modifier _onlyPancakeStaking() {
        if (pancakeStaking == address(0) || msg.sender != pancakeStaking)
            revert OnlyPancakeStaking();
        _;
    }

Auflistung 2.6: CakeRush.sol

Auswirkung N/A

Vorschlag Entfernen Sie überflüssige Bedingungen im Modifikator.

2.3 Hinweis

2.3.1 Potenzielles Zentralisierungsrisiko

Beschreibung Der Eigentümer von CakeRush besitzt erhebliche Befugnisse zur Änderung kritischer Konfigurationen. Dies stellt einen einzelnen Ausfallpunkt dar. Wenn ein Angreifer den Eigentümer kompromittiert, könnte er das gesamte System potenziell außer Gefecht setzen.

Darüber hinaus werden die CAKE-Token im Vertrag nicht explizit für die Sperrung im VECake-Vertrag behandelt. Stattdessen erlaubt CakeRush dem Eigentümer, alle diese CAKEs abzuheben, was bedeutet, dass der Eigentümer die CAKE-Token nach der Abhebung sperren muss. Die Logik ist jedoch auf Code-Ebene nicht garantiert, was ebenfalls zu Zentralisierungsbedenken führt.

Feedback vom Projekt Das Team macht den Eigentümer zu einer Multisig, um das Risiko zu mindern.

3. Hinweise und Bemerkungen

3.1 Haftungsausschluss

Dieser Prüfbericht stellt keine Anlageberatung oder persönliche Empfehlung dar. Er berücksichtigt nicht und sollte auch nicht als solche interpretiert werden oder sich auf die potenzielle Wirtschaftlichkeit eines Tokens, eines Token-Verkaufs oder eines anderen Produkts, einer Dienstleistung oder eines anderen Vermögenswerts auswirken. Kein Unternehmen sollte sich in irgendeiner Weise auf diesen Bericht verlassen, auch nicht für Entscheidungen zum Kauf oder Verkauf von Token, Produkten, Dienstleistungen oder anderen Vermögenswerten.

Dieser Prüfbericht ist keine Befürwortung eines bestimmten Projekts oder Teams, und der Bericht garantiert nicht die Sicherheit eines bestimmten Projekts. Diese Prüfung gibt keine Gewährleistung für die Entdeckung aller Sicherheitsprobleme der Smart Contracts, d. h. das Bewertungsergebnis garantiert nicht die Nichtexistenz weiterer Funde von Sicherheitsproblemen. Da eine Prüfung nicht als umfassend betrachtet werden kann, empfehlen wir stets unabhängige Prüfungen und ein öffentliches Bug-Bounty-Programm, um die Sicherheit von Smart Contracts zu gewährleisten.

Der Umfang dieser Prüfung beschränkt sich auf den in Abschnitt 1.1 genannten Code. Sofern nicht ausdrücklich anders angegeben, liegt die Sicherheit der Sprache selbst (z. B. der Solidity-Sprache), der zugrunde liegenden Compiler-Toolchain und der Recheninfrastruktur außerhalb des Umfangs.

3.2 Prüfverfahren

Wir führen die Prüfung nach folgendem Verfahren durch.

  • Schwachstellenerkennung Wir scannen zunächst Smart Contracts mit automatischen Code-Analysetools und überprüfen dann manuell (lehnen ab oder bestätigen) die von ihnen gemeldeten Probleme.

  • Semantische Analyse Wir untersuchen die Geschäftslogik von Smart Contracts und führen weitere Untersuchungen zu möglichen Schwachstellen mit einem automatischen Fuzzing-Tool (entwickelt von unserem Forschungsteam) durch. Wir analysieren auch manuell mögliche Angriffsszenarien mit unabhängigen Prüfern, um die Ergebnisse zu überprüfen.

  • Empfehlung Wir geben Entwicklern einige nützliche Ratschläge aus der Perspektive guter Programmierpraxis, einschließlich Gasoptimierung, Code-Stil und etc.

Die wichtigsten konkreten Prüfpunkte zeigen wir im Folgenden.

3.2.1 Software-Sicherheit

  • Reentrancy
  • DoS
  • Zugriffskontrolle
  • Datenverarbeitung und Datenfluss
  • Fehlerbehandlung
  • Nicht vertrauenswürdiger externer Aufruf und Kontrollfluss
  • Konsistenz der Initialisierung
  • Ereignisoperationen
  • Fehleranfällige Zufälligkeit
  • Unsachgemäße Verwendung des Proxy-Systems

3.2.2 DeFi-Sicherheit

  • Semantische Konsistenz
  • Funktionale Konsistenz
  • Berechtigungsverwaltung
  • Geschäftslogik
  • Token-Betrieb
  • Notfallmechanismus
  • Oracle-Sicherheit
  • Whitelist und Blacklist
  • Wirtschaftliche Auswirkungen
  • Batch-Übertragung

3.2.3 NFT-Sicherheit

  • Duplizierter Artikel
  • Verifizierung des Token-Empfängers
  • Sicherheit von Off-Chain-Metadaten

3.2.4 Zusätzliche Empfehlung

  • Gasoptimierung
  • Codequalität und Stil

Hinweis Die vorherigen Prüfpunkte sind die wichtigsten. Wir können während des Prüfprozesses weitere Prüfpunkte je nach Funktionalität des Projekts verwenden.

Sign up for the latest updates