Back to Blog

Cakepie契約のセキュリティ監査レポート

Code Auditing
2023年11月30日
11 min read

レポートマニフェスト

項目 説明
クライアント Magpie XYZ
対象 CakePie Contracts

バージョン履歴

バージョン 日付 説明
1.0 2023年11月30日 初版リリース

1. はじめに

1.1 対象コントラクトについて

情報 説明
タイプ スマートコントラクト
言語 Solidity
アプローチ 半自動および手動検証

本監査の対象は、Magpie XYZのCakePieコントラクト^1のコードリポジトリです。CakePieコントラクトはCakeRushキャンペーンを実行しており、ユーザーはCakePie上でPancakeSwapからCAKEトークンまたはロックされたCAKEポジションを変換できます。なお、監査範囲にはCakeRush.solとPancakeStakingBNBChain.solのみが含まれ、その他のファイルは本監査の範囲外となります。

監査プロセスは反復的です。具体的には、発見された問題点を修正するコミットを監査します。新しい問題が発生した場合は、このプロセスを継続します。監査中のコミットSHA値は以下の表に示されています。本監査レポートは、初版(バージョン1)のコード、および監査レポートの問題点を修正するための新しいコード(後続バージョン)について責任を負います。

1.2 セキュリティモデル

リスクを評価するため、OWASPリスク評価方法論^2および共通脆弱性列挙(Common Weakness Enumeration)^3など、業界および学術界で広く採用されている基準または提案に従います。リスクの全体的な重大度は、発生可能性影響度によって決定されます。具体的には、発生可能性は、特定の脆弱性が攻撃者によって発見および悪用される可能性を推定するために使用され、影響度は、成功した悪用の結果を測定するために使用されます。

本レポートでは、発生可能性と影響度の両方を2つの評価(および)に分類し、その組み合わせを表1.1に示します。

したがって、本レポートで測定される重大度は、の3つのカテゴリに分類されます。完全性を期すため、リスクを適切に判断できない状況をカバーするために、未決定も使用されます。

さらに、発見された項目のステータスは、以下の4つのカテゴリのいずれかに分類されます。

  • 未決定 まだ応答がありません。

  • 承認済み 項目はクライアントによって受信されましたが、まだ確認されていません。

  • 確認済み 項目はクライアントによって認識されましたが、まだ修正されていません。

  • 修正済み 項目はクライアントによって確認および修正されました。

2. 監査結果

合計で、2件の潜在的な問題を発見しました。さらに、3件の推奨事項と1件の注記があります。

  • 高リスク:1件

  • 低リスク:1件

  • 推奨事項:3件

  • 注記:1件

ID 重大度 説明 カテゴリ ステータス
1 パラメータリセット後の状態の不整合の可能性 ソフトウェアセキュリティ 修正済み
2 mCake報酬の繰り返し請求 ソフトウェアセキュリティ 修正済み
3 - 初期化関数でのパラメータチェック 推奨事項 承認済み
4 - CakeRushコントラクトでのパラメータチェック 推奨事項 修正済み
5 - 修飾子での追加条件 推奨事項 承認済み
6 - 潜在的な中央集権化リスク 注記 -

詳細は以下のセクションで提供します。

2.1 ソフトウェアセキュリティ

2.1.1 パラメータリセット後の状態の不整合の可能性

項目 説明
重大度
ステータス バージョン2で修正済み
導入元 バージョン1

説明 CakeRushコントラクトは、いくつかのパラメータに基づいて報酬を分配します。以下の関数は、プロジェクトメンテナーが一部のパラメータをリセットすることを許可しています。

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;
    }

リスト2.1: CakeRush.sol

しかし、これらの関数はパラメータのみをリセットし、userInfos状態変数に保存されているユーザー情報はリセットしません。その結果、CakeRushコントラクトでの計算は、状態の不整合により失敗する可能性があります。たとえば、パラメータがリセットされ、不正確な値に設定された場合、155行目の減算は整数アンダーフローにより失敗する可能性があります。

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;

リスト2.2: CakeRush.sol

さらに悪いことに、ユーザーがパラメータをリセットした直後(例えばバックランニングによる新しいパラメータ設定前)にconvertまたはconvertWithCakePoolを呼び出した場合、141〜142行目のロジックにより、コントラクト内に記録されている合計および加重ファクターがリセットされる可能性があります。

影響 パラメータのリセットは、不整合で不正確な状態を引き起こす可能性があります。

提案 古いパラメータをクリアした後、新しいパラメータを設定してください。

プロジェクトからのフィードバック CakeRushキャンペーンが開始されたら、マルチプライヤーはリセットされません。

2.1.2 mCake報酬の繰り返し請求

項目 説明
重大度
ステータス バージョン3で修正済み
導入元 バージョン2

説明 コントラクトでCAKEトークンをロックした後、ユーザーは関数を通じてmCakeトークンを報酬として請求できます。しかし、この関数にはユーザーが報酬を複数回請求できる問題が含まれています。以下のコードセグメントでは、金額がユーザーの保有量よりも大きい場合、transferまたはdepositがユーザーに合計金額を渡します。正しい実装はclaimedMCake[msg.sender]を返すべきですが、現在の実装ではユーザーがmCake報酬を繰り返し請求できるようになっています。

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;
    }

リスト2.3: CakeRush.sol

影響 ユーザーはmCake報酬を繰り返し請求できます。

提案 報酬請求ロジックを修正してください。

2.2 追加の推奨事項

2.2.1 初期化関数でのパラメータチェック

項目 説明
ステータス 承認済み
導入元 バージョン1

説明 CakeRushおよびPancakeStakingBNBChainコントラクトの初期化関数には、初期化後に変更できないパラメータがあります。これらのパラメータは初期化関数でチェックすることが推奨されます。

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

リスト2.4: CakeRush.sol

影響 該当なし

提案 初期化関数でパラメータをチェックしてください。

2.2.2 CakeRushコントラクトでのパラメータチェック

項目 説明
ステータス バージョン2で修正済み
導入元 バージョン1

説明 CakeRushコントラクトでは、報酬分配に関するいくつかのパラメータを追加できます。しかし、これらのパラメータがコントラクトの仮定に従って正しく設定されているかどうかのチェックはありません。具体的には、setMultiplierおよびsetTimeWeighting関数では、追加の条件(つまり、rewardTierおよびweightedTime配列の単調増加プロパティ)をチェックする必要があります。

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;
        }
    }

リスト2.5: CakeRush.sol

影響 該当なし

提案 パラメータを設定する関数でパラメータをチェックしてください。

2.2.3 修飾子での追加条件

項目 説明
ステータス 承認済み
導入元 バージョン1

説明 CakeRushコントラクトでは、_onlyPancakeStaking修飾子に余分な条件があります。この修飾子の意味するところによれば、msg.sender != pancakeStakingをチェックするだけで十分です。

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

リスト2.6: CakeRush.sol

影響 該当なし

提案 修飾子から余分な条件を削除してください。

2.3 注記

2.3.1 潜在的な中央集権化リスク

説明 CakeRushのオーナーは、重要な設定を変更する広範な権限を保持しています。これは単一障害点となります。攻撃者がオーナーを侵害した場合、システム全体を無効化する可能性があります。

さらに、コントラクト内のCAKEトークンは、VECakeコントラクトにロックするために明示的に処理されていません。代わりに、CakeRushはオーナーにすべてのCAKEを引き出すことを許可しており、これはオーナーがCAKEトークンを引き出した後にロックする必要があることを意味します。しかし、このロジックはコードレベルでは保証されておらず、中央集権化の懸念も生じます。

プロジェクトからのフィードバック リスクを軽減するために、チームはオーナーをマルチシグにしました。

3. 通知と注記

3.1 免責事項

本監査レポートは、投資アドバイスまたは個人的な推奨を構成するものではありません。トークン、トークンセール、またはその他の製品、サービス、またはその他の資産の潜在的な経済性を考慮しておらず、考慮したとは解釈されず、またそれらに影響を与えるものでもありません。いかなる主体も、トークン、製品、サービス、またはその他の資産の売買の決定を行う目的を含め、いかなる方法においても本レポートに依存すべきではありません。

本監査レポートは、特定のプロジェクトまたはチームの推奨ではなく、レポートはいかなる特定のプロジェクトのセキュリティも保証するものではありません。本監査は、スマートコントラクトのすべてのセキュリティ問題を発見することを保証するものではありません。つまり、評価結果はいかなるさらなるセキュリティ問題の発見がないことを保証するものではありません。1回の監査では包括的とは見なされないため、スマートコントラクトのセキュリティを確保するために、独立した監査と公開バグバウンティプログラムの実施を常に推奨します。

本監査の範囲は、セクション1.1で言及されているコードに限定されます。明示的に指定されていない限り、言語自体のセキュリティ(例:Solidity言語)、基盤となるコンパイラツールチェーン、およびコンピューティングインフラストラクチャは範囲外です。

3.2 監査手順

以下の手順に従って監査を実行しました。

  • 脆弱性検出 まず、自動コードアナライザーでスマートコントラクトをスキャンし、その後、それらが報告した問題を人間が検証(却下または確認)します。

  • 意味解析 スマートコントラクトのビジネスロジックを調査し、自動ファジングツール(当社研究チームによって開発)を使用して、潜在的な脆弱性についてさらに調査します。また、独立した監査人と協力して、潜在的な攻撃シナリオを人間が分析し、結果を相互に確認します。

  • 推奨事項 ガス最適化、コードスタイルなど、優れたプログラミングプラクティスの観点から、開発者に役立つアドバイスを提供します。

以下に、主な具体的なチェックポイントを示します。

3.2.1 ソフトウェアセキュリティ

  • 再入可能性(Reentrancy)

  • DoS(サービス拒否)

  • アクセス制御

  • データ処理とデータフロー

  • 例外処理

  • 信頼できない外部呼び出しと制御フロー

  • 初期化の一貫性

  • イベント操作

  • エラーが発生しやすい乱数

  • プロキシシステムの不適切な使用

3.2.2 DeFiセキュリティ

  • 意味の一貫性

  • 機能の一貫性

  • 権限管理

  • ビジネスロジック

  • トークン操作

  • 緊急メカニズム

  • オラクルセキュリティ

  • ホワイトリストとブラックリスト

  • 経済的影響

  • バッチ転送

3.2.3 NFTセキュリティ

  • 重複アイテム

  • トークン受信者の検証

  • オフチェーンメタデータセキュリティ

3.2.4 追加の推奨事項

  • ガス最適化

  • コード品質とスタイル

注記 上記のチェックポイントが主なものです。プロジェクトの機能に応じて、監査プロセス中にさらに多くのチェックポイントを使用する場合があります。

Sign up for the latest updates
Web3攻撃対象領域:ペネトレーションテストの概要

Web3攻撃対象領域:ペネトレーションテストの概要

暗号資産機関は従来の攻撃対象領域に加え、資金処理チェーンも抱えます。本記事は稼働システムをアプリケーション、認可・署名、ブロックチェーン連携、インフラの4要素で整理し、各要素の責務・実装例・継承される攻撃対象を示します。さらにweb3固有の範囲を、運用・署名意図・承認出金チェーン・資金ロジック・オンチェーン取引と契約という5領域に構造化します。

約2,300万ドル喪失:Cosmos EVM、Moonwellの被害事例 | BlockSec Weekly
Security Insights

約2,300万ドル喪失:Cosmos EVM、Moonwellの被害事例 | BlockSec Weekly

レポート期間(2026/08/22-2026/08/30)中、約2270万ドルの損害を伴う5件のブロックチェーンセキュリティ事件を報告。Tectonicから約7400万〜1.195億ドルが流出したが、CronosがExploit前状態にロールバックされ大部分が消失。ハイライトはTAC Chainで追跡された6チェーンにわたるCosmos EVM Exploitシリーズ(実現損失約570万ドル)で、共有残高同期バグがアンダーフローとオーバーフローを連鎖させステーキングプールを枯渇させた。Moonwellの担保会計とオラクル価格操作の複合、Tectonicのオラクル価格とレシートトークン交換レート操作、Ajnaの清算ビジネスロジック欠陥、SolanaのRain Card Contract ExploitシリーズにおけるEd25519署名検証バイパス(Avici、Tria等)も分析。

ブロックチェーンペネトレーションテストとは?定義と境界
Security Services

ブロックチェーンペネトレーションテストとは?定義と境界

ブロックチェーンペネトレーションテストに広く受け入れられた定義はなく、監査、スキャン、バグバウンティと混同されがちです。本稿は作業定義―合意された範囲とルールの下、稼働システムを実際に攻撃し悪用経路と制御連鎖を検証すること―を示し、web3特有の資金移動脅威モデルの核心であるオフチェーンからオンチェーンへの受け渡しの構成的隙間を論じます。さらにこの連鎖を構成する5つの検証可能な能力を整理し、関連目的をコード監査、ウォレットセキュリティ監査、web3セキュリティテスト、スキャン、バグバウンティへ振り分けます。

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit