Back to Blog

Cakepie 컨트랙트 보안 감사 보고서

Code Auditing
November 30, 2023
9 min read

보고서 매니페스트

항목 설명
클라이언트 Magpie XYZ
대상 CakePie 컨트랙트

버전 이력

버전 날짜 설명
1.0 2023년 11월 30일 최초 배포

1. 소개

1.1 대상 컨트랙트 정보

정보 설명
유형 스마트 컨트랙트
언어 Solidity
접근 방식 반자동 및 수동 검증

이번 감사의 대상은 Magpie XYZ의 CakePie 컨트랙트^1 코드 저장소입니다. CakePie 컨트랙트는 CakeRush 캠페인을 운영하며, 사용자는 PancakeSwap에서 보유한 CAKE 토큰 또는 잠긴 CAKE 포지션을 CakePie로 전환할 수 있습니다. 감사 범위에는 CakeRush.sol과 PancakeStakingBNBChain.sol만 포함되며, 그 외 파일은 이번 감사 범위에 포함되지 않습니다.

감사 프로세스는 반복적으로 진행됩니다. 구체적으로, 발견된 이슈를 수정한 커밋을 감사합니다. 새로운 이슈가 발생할 경우 이 과정을 계속합니다. 감사 중 사용된 커밋 SHA 값은 아래 표에 나타나 있습니다. 본 감사 보고서는 초기 버전(버전 1)의 코드와 감사 보고서의 이슈를 수정하기 위한 새 코드(이후 버전)에 대해 책임집니다.

1.2 보안 모델

위험을 평가하기 위해, OWASP 위험 등급 방법론^2 및 공통 취약점 목록(CWE)^3을 포함하여 업계와 학계에서 널리 채택된 표준 또는 권고사항을 따릅니다. 위험의 전반적인 심각도가능성영향에 의해 결정됩니다. 구체적으로, 가능성은 특정 취약점이 공격자에 의해 발견되고 악용될 가능성을 추정하는 데 사용되며, 영향은 성공적인 악용의 결과를 측정하는 데 사용됩니다.

본 보고서에서 가능성과 영향은 각각 높음낮음 두 가지 등급으로 분류되며, 그 조합은 표 1.1에 나타나 있습니다.

이에 따라 본 보고서에서 측정된 심각도는 높음, 중간, 낮음의 세 가지 범주로 분류됩니다. 완전성을 위해, 위험을 명확히 판단할 수 없는 경우에는 미확정도 사용됩니다.

또한, 발견된 항목의 상태는 다음 네 가지 범주 중 하나에 해당합니다:

  • 미확정 아직 응답 없음.

  • 확인됨 항목이 클라이언트에 접수되었으나 아직 승인되지 않음.

  • 승인됨 항목이 클라이언트에 의해 인식되었으나 아직 수정되지 않음.

  • 수정됨 항목이 클라이언트에 의해 승인 및 수정됨.

2. 발견 사항

개의 잠재적 이슈를 발견했습니다. 또한 개의 권고사항과 하나의 참고사항이 있습니다.

  • 높은 위험: 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 토큰을 보상으로 청구할 수 있습니다. 그러나 이 함수에는 사용자가 보상을 여러 번 청구할 수 있는 문제가 포함되어 있습니다. 다음 코드 세그먼트에서, 금액이 사용자의 금액보다 클 경우 사용자에게 총 금액을 전송하거나 예치합니다. 올바른 구현은 해당 금액만 반환해야 하므로, 현재 구현은 사용자가 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 컨트랙트에서 보상 분배와 관련된 여러 매개변수를 추가할 수 있습니다. 그러나 이러한 매개변수가 컨트랙트의 가정에 따라 올바르게 설정되었는지 확인하는 검사가 없습니다. 구체적으로, setMultipler 및 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에서 언급된 코드로 제한됩니다. 명시적으로 지정되지 않는 한, 언어 자체의 보안(예: Solidity 언어), 기반 컴파일 툴체인 및 컴퓨팅 인프라는 범위에 포함되지 않습니다.

3.2 감사 절차

다음 절차에 따라 감사를 수행합니다.

  • 취약점 탐지 먼저 자동 코드 분석기로 스마트 컨트랙트를 스캔한 후, 보고된 이슈를 수동으로 검증(거부 또는 확인)합니다.

  • 의미 분석 스마트 컨트랙트의 비즈니스 로직을 연구하고, 자동 퍼징 도구(연구팀이 개발)를 사용하여 가능한 취약점에 대한 추가 조사를 수행합니다. 또한 독립적인 감사자와 함께 가능한 공격 시나리오를 수동으로 분석하여 결과를 교차 확인합니다.

  • 권고사항 가스 최적화, 코드 스타일 등 좋은 프로그래밍 관행의 관점에서 개발자에게 유용한 조언을 제공합니다.

주요 구체적인 점검 항목은 다음과 같습니다.

3.2.1 소프트웨어 보안

  • 재진입

  • 서비스 거부(DoS)

  • 접근 제어

  • 데이터 처리 및 데이터 흐름

  • 예외 처리

  • 신뢰할 수 없는 외부 호출 및 제어 흐름

  • 초기화 일관성

  • 이벤트 운영

  • 오류 발생 가능한 무작위성

  • 프록시 시스템의 부적절한 사용

3.2.2 DeFi 보안

  • 의미적 일관성

  • 기능적 일관성

  • 권한 관리

  • 비즈니스 로직

  • 토큰 운영

  • 비상 메커니즘

  • 오라클 보안

  • 화이트리스트 및 블랙리스트

  • 경제적 영향

  • 일괄 전송

3.2.3 NFT 보안

  • 중복 항목

  • 토큰 수신자 검증

  • 오프체인 메타데이터 보안

3.2.4 추가 권고사항

  • 가스 최적화

  • 코드 품질 및 스타일

참고 이전 점검 항목은 주요 항목입니다. 프로젝트의 기능에 따라 감사 과정에서 더 많은 점검 항목을 사용할 수 있습니다.

Sign up for the latest updates
~$410만 손실: Taiko, SecondFi 익스플로잇 | BlockSec 위클리
Security Insights

~$410만 손실: Taiko, SecondFi 익스플로잇 | BlockSec 위클리

이 주간 블록체인 보안 리포트는 2026년 6월 22~28일 발생한 주요 사건 2건을 다루며, 이더리움과 카르다노에서 약 410만 달러의 피해가 확인됐습니다. Taiko 브릿지 공격은 노출된 SGX 서명 키와 디버그 엔클레이브를 거부하지 못한 증명 정책 결함을 이용해 악성 증명자를 등록하고 L2 상태 증명을 위조했습니다. SecondFi 지갑은 Ed25519 논스 도출 시 비밀 입력이 제거되는 결함으로 공개 트랜잭션 데이터만으로 개인 키 복구가 가능했습니다.

~$18M 손실: jaredFromSubway, Aztec 등 | BlockSec 위클리
Security Insights

~$18M 손실: jaredFromSubway, Aztec 등 | BlockSec 위클리

이 주간 블록체인 보안 보고서는 2026년 6월 15일~21일을 다루며, 이더리움과 BNB 체인에서 3건의 주요 사고가 발생해 약 $18.3M의 손실이 발생했습니다. jaredFromSubway 사건은 MEV 봇이 차익거래를 위해 신뢰할 수 없는 제3자 컨트랙트에 자산을 승인한 역방향 승인 공격으로, 가짜 래퍼 토큰과 스왑 풀을 이용해 약 $15M 손실이 발생했습니다. Aztec은 이스케이프 해치 ZK 회로의 제약 누락으로 공격자가 가짜 머클 트리로 온체인 검증을 통과했습니다.

Web3 컴패니언: 오픈소스 보안 에이전틱 지갑

Web3 컴패니언: 오픈소스 보안 에이전틱 지갑

BlockSec가 Web3 Companion을 오픈소스로 공개했습니다. 이 보안 중심의 에이전트 지갑은 자체 AI 에이전트를 신뢰하지 않는 방식으로 설계되었으며, 키 격리, 강력한 정책, Passkey를 활용해 온체인 자산을 보호합니다.

Best Security Auditor for Web3

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

BlockSec Audit