logo
bg_imgbg_imgbg_imgbg_img
exclamation mark iconReport an issue

If you notice some outdated information please let us know!

close icon
Name
Email
Your message
arrow-left

PancakeSwap V2

54%

Previous versions

Process Quality Review (0.8)

PancakeSwap V2

Final score:54%
Date:20 Jun 2022
Audit Process:version 0.8
Author:David J. Desjardins
PQR Score:54%

FAIL

Security Incidents

Date:12 Apr 2021
Details: PancakeSwap's lottery underwent a whitehack proceeding the discovery of a potential exploit. The whitehack is described in the following link under the pretense that PancakeSwap's admin performed the exploit maliciously, which is not true. However, it still describes the exploit quite well. https://cryptopwnage.medium.com/1-800-000-was-stolen-from-binance-smart-chain-pancakeswap-lottery-pool-ca2afb415f9
Reference Linklink
Date:15 Mar 2021
Details: PancakeSwap's DNS was compromised by a third party.
Reference Linklink

Scoring Appendix

The final review score is indicated as a percentage. The percentage is calculated as Achieved Points due to MAX Possible Points. For each element the answer can be either Yes/No or a percentage. For a detailed breakdown of the individual weights of each question, please consult this document.

The blockchain used by this protocol
BnB Smart Chain
#QuestionAnswer
67%
1.100%
2.100%
3.Yes
4.0%
5.0
27%
6.Yes
7.No
8.25%
9.15%
50%
10.100%
11.50%
12.No
13.0%
14.No
15.No
83%
16.80%
17.100%
60%
18.100%
19.100%
20.100%
21.50%
22.90%
23.0%
24.30%
25.0%
0%
26.0
27.No
28.No
Total:54%

Very simply, the audit looks for the following declarations from the developer's site. With these declarations, it is reasonable to trust the smart contracts.

  • Here is my smart contract on the blockchain
  • You can see it matches a software repository used to develop the code
  • Here is the documentation that explains what my smart contract does
  • Here are the tests I ran to verify my smart contract
  • Here are the audit(s) performed to review my code by third party experts

This report is for informational purposes only and does not constitute investment advice of any kind, nor does it constitute an offer to provide investment advisory or other services. Nothing in this report shall be considered a solicitation or offer to buy or sell any security, token, future, option or other financial instrument or to offer or provide any investment advice or service to any person in any jurisdiction. Nothing contained in this report constitutes investment advice or offers any opinion with respect to the suitability of any security, and the views expressed in this report should not be taken as advice to buy, sell or hold any security. The information in this report should not be relied upon for the purpose of investing. In preparing the information contained in this report, we have not taken into account the investment needs, objectives and financial circumstances of any particular investor. This information has no regard to the specific investment objectives, financial situation and particular needs of any specific recipient of this information and investments discussed may not be suitable for all investors.

Any views expressed in this report by us were prepared based upon the information available to us at the time such views were written. The views expressed within this report are limited to DeFiSafety and the author and do not reflect those of any additional or third party and are strictly based upon DeFiSafety, its authors, interpretations and evaluation of relevant data. Changed or additional information could cause such views to change. All information is subject to possible correction. Information may quickly become unreliable for various reasons, including changes in market conditions or economic circumstances.

This completed report is copyright (c) DeFiSafety 2023. Permission is given to copy in whole, retaining this copyright label.

Smart Contracts & Team

67%

This section looks at the code deployed on the relevant chain that gets reviewed and its corresponding software repository. The document explaining these questions is here.

1. Are the smart contract addresses easy to find? (%)

Answer: 100%

They can be found here, as indicated in the Appendix. Methods for finding Ad Hoc contracts are also described at this location.

Percentage Score Guidance:
100%
Clearly labelled and on website, documents or repository, quick to find
70%
Clearly labelled and on website, docs or repo but takes a bit of looking
40%
Addresses in mainnet.json, in discord or sub graph, etc
20%
Address found but labeling not clear or easy to find
0%
Executing addresses could not be found

2. How active is the primary contract? (%)

Answer: 100%

Contract MasterChef.sol is used at least 1164 times per day during the last month, as indicated in the Appendix.

Percentage Score Guidance:
100%
More than 10 transactions a day
70%
More than 10 transactions a week
40%
More than 10 transactions a month
10%
Less than 10 transactions a month
0%
No activity

3. Does the protocol have a public software repository? (Y/N)

Answer: Yes

https://github.com/pancakeswap/pancake-smart-contracts

Score Guidance:
Yes
There is a public software repository with the code at a minimum, but also normally test and scripts. Even if the repository was created just to hold the files and has just 1 transaction.
No
For teams with private repositories.

4. Is there a development history visible? (%)

Answer: 0%

PancakeSwap's contracts repository only has 1 commit, although the commit has 428 changed files with 116,992 additions.

Percentage Score Guidance:
100%
Any one of 100+ commits, 10+branches
70%
Any one of 70+ commits, 7+branches
50%
Any one of 50+ commits, 5+branches
30%
Any one of 30+ commits, 3+branches
0%
Less than 2 branches or less than 30 commits

5. Is the team public (not anonymous)?

Answer: 0

The PancakeSwap team operates pseudonymously as outlined here.

Score Guidance:
100%
At least two names can be easily found in the protocol's website, documentation or medium. These are then confirmed by the personal websites of the individuals / their linkedin / twitter.
50%
At least one public name can be found to be working on the protocol.
0%
No public team members could be found.

Documentation

27%

This section looks at the software documentation. The document explaining these questions is here.

6. Is there a whitepaper? (Y/N)

Answer: Yes

Location: https://docs.pancakeswap.finance/code/smart-contracts/pancakeswap-exchange/factory-v2

7. Is the protocol's software architecture documented? (Y/N)

Answer: No

This protocol's software architecture is not documented.

Score Guidance:
Yes
The documents identify software architecture and contract interaction through any of the following: diagrams, arrows, specific reference to software functions or a written explanation on how smart contracts interact.
No
Protocols receive a "no" if none of these are included.

8. Does the software documentation fully cover the deployed contracts' source code? (%)

Answer: 25%

The following contracts have function documentation.  PancakeSwapLotteryV2.sol  PancakeRouter V2.sol  PancakeFactory V2.sol  All other contracts in the repository (57 others) have no function/software documentation. Although functions are on average undocumented, the documented contracts are the most important ones. With the previous points considered, I will assign a 25% for software function documentation.    

Percentage Score Guidance:
100%
All contracts and functions documented
80%
Only the major functions documented
79 - 1%
Estimate of the level of software documentation
0%
No software documentation

9. Is it possible to trace the documented software to its implementation in the protocol's source code? (%)

Answer: 15%

There is implicit traceability between software documentation and implemented code. Given that only a limited amount of software functions are documented, a score reduced proportionally will be awarded in line with the amount covered by software function documentation.

Percentage Score Guidance:
100%
Clear explicit traceability between code and documentation at a requirement level for all code
60%
Clear association between code and documents via non explicit traceability
40%
Documentation lists all the functions and describes their functions
0%
No connection between documentation and code

Testing

50%

10. Has the protocol tested their deployed code? (%)

Answer: 100%

Code examples are in the Appendix at the end of this report.. As per the SLOC, there is 10029/22084= ~220% testing to code (TtC).    This score is guided by the Test to Code ratio (TtC). Generally a good test to code ratio is over 100%. However, the reviewer's best judgement is the final deciding factor.

Percentage Score Guidance:
100%
TtC > 120% Both unit and system test visible
80%
TtC > 80% Both unit and system test visible
40%
TtC < 80% Some tests visible
0%
No tests obvious

11. How covered is the protocol's code? (%)

Answer: 50%

PancakeSwap does not document tests for coverage. However, there's evidence of good testing in this repository. We will award points for this.

Percentage Score Guidance:
100%
Documented full coverage
99 - 51%
Value of test coverage from documented results
50%
No indication of code coverage but clearly there is a complete set of tests
30%
Some tests evident but not complete
0%
No test for coverage seen

12. Does the protocol provide scripts and instructions to run their tests? (Y/N)

Answer: No

PancakeSwap does not document instructions to run tests.

Score Guidance:
Yes
Scripts and/or instructions to run tests are available in the testing suite
No
Scripts and/or instructions to run tests are not available in the testing suite

13. Is there a detailed report of the protocol's test results?(%)

Answer: 0%

Pancakeswap documents a test report in their smart contract repository CLI. However, since this cannot be expanded for verification, we will not award points.

Percentage Score Guidance:
100%
Detailed test report as described below
70%
GitHub code coverage report visible
0%
No test report evident

14. Has the protocol undergone Formal Verification? (Y/N)

Answer: No

This protocol has not undergone formal verification.

Score Guidance:
Yes
Formal Verification was performed and the report is readily available
No
Formal Verification was not performed and/or the report is not readily available.

15. Were the smart contracts deployed to a testnet? (Y/N)

Answer: No

No addresses or documentation in relation to testnet deployments can be located.

Score Guidance:
Yes
Protocol has proved their tesnet usage by providing the addresses
No
Protocol has not proved their testnet usage by providing the addresses

Security

83%

This section looks at the 3rd party software audits done. It is explained in this document.

16. Is the protocol sufficiently audited? (%)

Answer: 80%

The PancakeSwap deployer was deployed on September 15th 2020.  PancakeSwap was audited by Slowmist 3 times; Once for overall security on May 12th 2021, once for Auto-CAKE pool security on May 21st 2021, and once for Lottery V2 on June 16th 2021.  In addition, PancakeSwap was audited by Certik on October 13th 2020. LotteryV2 was re-audited by Peckshield on July 7th 2021.

Percentage Score Guidance:
100%
Multiple Audits performed before deployment and the audit findings are public and implemented or not required
90%
Single audit performed before deployment and audit findings are public and implemented or not required
70%
Audit(s) performed after deployment and no changes required. The Audit report is public.
65%
Code is forked from an already audited protocol and a changelog is provided explaining why forked code was used and what changes were made. This changelog must justify why the changes made do not affect the audit.
50%
Audit(s) performed after deployment and changes are needed but not implemented.
30%
Audit(s) performed are low-quality and do not indicate proper due diligence.
20%
No audit performed
0%
Audit Performed after deployment, existence is public, report is not public OR smart contract address' not found.
Deduct 25% if the audited code is not available for comparison.

17. Is the bounty value acceptably high (%)

Answer: 100%

This protocol offers an active bug bounty of $1M for smart contract vulnerabilities. With an additional maximum of $7500 for website and app bugs.

Percentage Score Guidance:
100%
Bounty is 10% TVL or at least $1M AND active program (see below)
90%
Bounty is 5% TVL or at least 500k AND active program
80%
Bounty is 5% TVL or at least 500k
70%
Bounty is 100k or over AND active program
60%
Bounty is 100k or over
50%
Bounty is 50k or over AND active program
40%
Bounty is 50k or over
20%
Bug bounty program bounty is less than 50k
0%
No bug bounty program offered / the bug bounty program is dead
An active program means that a third party (such as Immunefi) is actively driving hackers to the site. An inactive program would be static mentions on the docs.

Admin Controls

60%

This section covers the documentation of special access controls for a DeFi protocol. The admin access controls are the contracts that allow updating contracts or coefficients in the protocol. Since these contracts can allow the protocol admins to "change the rules", complete disclosure of capabilities is vital for user's transparency. It is explained in this document.

18. Is the protocol's admin control information easy to find?

Answer: 100%

Admin control information was documented at this location. This was quick to find.

Percentage Score Guidance:
100%
Admin Controls are clearly labelled and on website, docs or repo, quick to find
70%
Admin Controls are clearly labelled and on website, docs or repo but takes a bit of looking
40%
Admin Control docs are in multiple places and not well labelled
20%
Admin Control docs are in multiple places and not labelled
0%
Admin Control information could not be found

19. Are relevant contracts clearly labelled as upgradeable or immutable? (%)

Answer: 100%

The relevant contracts are identified as upgradeable through a 3/6 Gnosis multisig, as identified here.

Percentage Score Guidance:
100%
Both the contract documentation and the smart contract code state that the code is not upgradeable or immutable.
80%
All Contracts are clearly labelled as upgradeable (or not)
50%
Code is immutable but not mentioned anywhere in the documentation
0%
Admin control information could not be found

20. Is the type of smart contract ownership clearly indicated? (%)

Answer: 100%

Ownership is clearly indicated in as shown here for relevant contracts.

Percentage Score Guidance:
100%
The type of ownership is clearly indicated in their documentation. (OnlyOwner / MultiSig / etc)
50%
The type of ownership is indicated, but only in the code. (OnlyOwner / MultiSig / etc)
0%
Admin Control information could not be found

21. Are the protocol's smart contract change capabilities described? (%)

Answer: 50%

The full extent of the contracts' change capabilities is not explicitly described, yet it can be assumed that they are mostly completely upgradeable through their 3/6 multisig. This proven in contract code.

Percentage Score Guidance:
100%
The documentation covers the capabilities for change for all smart contracts
50%
The documentation covers the capabilities for change in some, but not all contracts
0%
The documentation does not cover the capabilities for change in any contract

22. Is the protocol's admin control information easy to understand? (%)

Answer: 90%

Admin control is written in easy to interpret language.

Percentage Score Guidance:
100%
All the contracts are immutable
90%
Description relates to investments safety in clear non-software language
30%
Description all in software-specific language
0%
No admin control information could be found

23. Is there sufficient Pause Control documentation? (%)

Answer: 0%

No pause control information is documented.

Percentage Score Guidance:
100%
If immutable and no changes possible
100%
If admin control is fully via governance
80%
Robust transaction signing process (7 or more elements)
70%
Adequate transaction signing process (5 or more elements)
60%
Weak transaction signing process (3 or more elements)
0%
No transaction signing process evident
Evidence of audits of signers following the process add 20%

24. Is there sufficient Timelock documentation? (%)

Answer: 30%

No timelock information is documented. By reading the contract code, we learned there is a 6 hour timelock.

Percentage Score Guidance:
100%
Documentation identifies and explains why the protocol does not need a Timelock OR Timelock documentation identifies its duration, which contracts it applies to and justifies this time period.
60%
A Timelock is identified and its duration is specified
30%
A Timelock is identified
0%
No Timelock information was documented

25. Is the Timelock of an adequate length? (Y/N)

Answer: 0%

No timelock information is documented.

Percentage Score Guidance:
100%
Timelock is between 48 hours to 1 week OR justification as to why no Timelock is needed / is outside this length.
50%
Timelock is less than 48 hours or greater than 1 week.
0%
No Timelock information was documented OR no timelock length was identified.

Oracles

0%

This section goes over the documentation that a protocol may or may not supply about their Oracle usage. Oracles are a fundamental part of DeFi as they are responsible for relaying tons of price data information to thousands of protocols using blockchain technology. Not only are they important for price feeds, but they are also an essential component of transaction verification and security. These questions are explained in this document.

26. Is the protocol's Oracle sufficiently documented? (%)

Answer: 0

No oracle information could be found other than a mention of Uniswap V2 in "pancake-smart-contracts/projects/exchange-protocol/"'s README. Although it is widely known that PancakeSwap is a 1:1 fork of Uniswap, this should be documented in a far more concise fashion. As a decentralised exchange, this information should be explained.  

Score Guidance:
100%
If it uses one, the Oracle is specified. The contracts dependent on the oracle are identified. Basic software functions are identified (if the protocol provides its own price feed data). Timeframe of price feeds are identified. OR The reason as to why the protocol does not use an Oracle is identified and explained.
75%
The Oracle documentation identifies both source and timeframe, but does not provide additional context regarding smart contracts.
50%
Only the Oracle source is identified.
0%
No oracle is named / no oracle information is documented.

27. Is front running mitigated by this protocol? (Y/N)

Answer: No

No frontrunning information could be found.

Score Guidance:
Yes
The protocol cannot be front run and there is an explanation as to why OR documented front running countermeasures are implemented.
No
The Oracle documentation identifies both source and timeframe, but does not provide additional context regarding smart contracts.

28. Can flashloan attacks be applied to the protocol, and if so, are those flashloan attack risks mitigated? (Y/N)

Answer: No

No information relating to flashloan price manipulation mitigation can be found.

Score Guidance:
Yes
The protocol's documentation includes information on how they mitigate the possibilities and extents of flash loan attacks.
No
The protocol's documentation does not include any information regarding the mitigation of flash loan attacks.

Appendices

1// SPDX-License-Identifier: MIT
2pragma solidity 0.6.12;
3
4import "@openzeppelin/contracts/access/Ownable.sol";
5import "@openzeppelin/contracts/math/SafeMath.sol";
6import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
7import "@openzeppelin/contracts/utils/Pausable.sol";
8import "./interfaces/IMasterChef.sol";
9
10contract CakeVault is Ownable, Pausable {
11    using SafeERC20 for IERC20;
12    using SafeMath for uint256;
13
14    struct UserInfo {
15        uint256 shares; // number of shares for a user
16        uint256 lastDepositedTime; // keeps track of deposited time for potential penalty
17        uint256 cakeAtLastUserAction; // keeps track of cake deposited at the last user action
18        uint256 lastUserActionTime; // keeps track of the last user action time
19    }
20
21    IERC20 public immutable token; // Cake token
22    IERC20 public immutable receiptToken; // Syrup token
23
24    IMasterChef public immutable masterchef;
25
26    mapping(address => UserInfo) public userInfo;
27
28    uint256 public totalShares;
29    uint256 public lastHarvestedTime;
30    address public admin;
31    address public treasury;
32
33    uint256 public constant MAX_PERFORMANCE_FEE = 500; // 5%
34    uint256 public constant MAX_CALL_FEE = 100; // 1%
35    uint256 public constant MAX_WITHDRAW_FEE = 100; // 1%
36    uint256 public constant MAX_WITHDRAW_FEE_PERIOD = 72 hours; // 3 days
37
38    uint256 public performanceFee = 200; // 2%
39    uint256 public callFee = 25; // 0.25%
40    uint256 public withdrawFee = 10; // 0.1%
41    uint256 public withdrawFeePeriod = 72 hours; // 3 days
42
43    event Deposit(address indexed sender, uint256 amount, uint256 shares, uint256 lastDepositedTime);
44    event Withdraw(address indexed sender, uint256 amount, uint256 shares);
45    event Harvest(address indexed sender, uint256 performanceFee, uint256 callFee);
46    event Pause();
47    event Unpause();
48
49    /**
50     * @notice Constructor
51     * @param _token: Cake token contract
52     * @param _receiptToken: Syrup token contract
53     * @param _masterchef: MasterChef contract
54     * @param _admin: address of the admin
55     * @param _treasury: address of the treasury (collects fees)
56     */
57    constructor(
58        IERC20 _token,
59        IERC20 _receiptToken,
60        IMasterChef _masterchef,
61        address _admin,
62        address _treasury
63    ) public {
64        token = _token;
65        receiptToken = _receiptToken;
66        masterchef = _masterchef;
67        admin = _admin;
68        treasury = _treasury;
69
70        // Infinite approve
71        IERC20(_token).safeApprove(address(_masterchef), uint256(-1));
72    }
73
74    /**
75     * @notice Checks if the msg.sender is the admin address
76     */
77    modifier onlyAdmin() {
78        require(msg.sender == admin, "admin: wut?");
79        _;
80    }
81
82    /**
83     * @notice Checks if the msg.sender is a contract or a proxy
84     */
85    modifier notContract() {
86        require(!_isContract(msg.sender), "contract not allowed");
87        require(msg.sender == tx.origin, "proxy contract not allowed");
88        _;
89    }
90
91    /**
92     * @notice Deposits funds into the Cake Vault
93     * @dev Only possible when contract not paused.
94     * @param _amount: number of tokens to deposit (in CAKE)
95     */
96    function deposit(uint256 _amount) external whenNotPaused notContract {
97        require(_amount > 0, "Nothing to deposit");
98
99        uint256 pool = balanceOf();
100        token.safeTransferFrom(msg.sender, address(this), _amount);
101        uint256 currentShares = 0;
102        if (totalShares != 0) {
103            currentShares = (_amount.mul(totalShares)).div(pool);
104        } else {
105            currentShares = _amount;
106        }
107        UserInfo storage user = userInfo[msg.sender];
108
109        user.shares = user.shares.add(currentShares);
110        user.lastDepositedTime = block.timestamp;
111
112        totalShares = totalShares.add(currentShares);
113
114        user.cakeAtLastUserAction = user.shares.mul(balanceOf()).div(totalShares);
115        user.lastUserActionTime = block.timestamp;
116
117        _earn();
118
119        emit Deposit(msg.sender, _amount, currentShares, block.timestamp);
120    }
121
122    /**
123     * @notice Withdraws all funds for a user
124     */
125    function withdrawAll() external notContract {
126        withdraw(userInfo[msg.sender].shares);
127    }
128
129    /**
130     * @notice Reinvests CAKE tokens into MasterChef
131     * @dev Only possible when contract not paused.
132     */
133    function harvest() external notContract whenNotPaused {
134        IMasterChef(masterchef).leaveStaking(0);
135
136        uint256 bal = available();
137        uint256 currentPerformanceFee = bal.mul(performanceFee).div(10000);
138        token.safeTransfer(treasury, currentPerformanceFee);
139
140        uint256 currentCallFee = bal.mul(callFee).div(10000);
141        token.safeTransfer(msg.sender, currentCallFee);
142
143        _earn();
144
145        lastHarvestedTime = block.timestamp;
146
147        emit Harvest(msg.sender, currentPerformanceFee, currentCallFee);
148    }
149
150    /**
151     * @notice Sets admin address
152     * @dev Only callable by the contract owner.
153     */
154    function setAdmin(address _admin) external onlyOwner {
155        require(_admin != address(0), "Cannot be zero address");
156        admin = _admin;
157    }
158
159    /**
160     * @notice Sets treasury address
161     * @dev Only callable by the contract owner.
162     */
163    function setTreasury(address _treasury) external onlyOwner {
164        require(_treasury != address(0), "Cannot be zero address");
165        treasury = _treasury;
166    }
167
168    /**
169     * @notice Sets performance fee
170     * @dev Only callable by the contract admin.
171     */
172    function setPerformanceFee(uint256 _performanceFee) external onlyAdmin {
173        require(_performanceFee <= MAX_PERFORMANCE_FEE, "performanceFee cannot be more than MAX_PERFORMANCE_FEE");
174        performanceFee = _performanceFee;
175    }
176
177    /**
178     * @notice Sets call fee
179     * @dev Only callable by the contract admin.
180     */
181    function setCallFee(uint256 _callFee) external onlyAdmin {
182        require(_callFee <= MAX_CALL_FEE, "callFee cannot be more than MAX_CALL_FEE");
183        callFee = _callFee;
184    }
185
186    /**
187     * @notice Sets withdraw fee
188     * @dev Only callable by the contract admin.
189     */
190    function setWithdrawFee(uint256 _withdrawFee) external onlyAdmin {
191        require(_withdrawFee <= MAX_WITHDRAW_FEE, "withdrawFee cannot be more than MAX_WITHDRAW_FEE");
192        withdrawFee = _withdrawFee;
193    }
194
195    /**
196     * @notice Sets withdraw fee period
197     * @dev Only callable by the contract admin.
198     */
199    function setWithdrawFeePeriod(uint256 _withdrawFeePeriod) external onlyAdmin {
200        require(
201            _withdrawFeePeriod <= MAX_WITHDRAW_FEE_PERIOD,
202            "withdrawFeePeriod cannot be more than MAX_WITHDRAW_FEE_PERIOD"
203        );
204        withdrawFeePeriod = _withdrawFeePeriod;
205    }
206
207    /**
208     * @notice Withdraws from MasterChef to Vault without caring about rewards.
209     * @dev EMERGENCY ONLY. Only callable by the contract admin.
210     */
211    function emergencyWithdraw() external onlyAdmin {
212        IMasterChef(masterchef).emergencyWithdraw(0);
213    }
214
215    /**
216     * @notice Withdraw unexpected tokens sent to the Cake Vault
217     */
218    function inCaseTokensGetStuck(address _token) external onlyAdmin {
219        require(_token != address(token), "Token cannot be same as deposit token");
220        require(_token != address(receiptToken), "Token cannot be same as receipt token");
221
222        uint256 amount = IERC20(_token).balanceOf(address(this));
223        IERC20(_token).safeTransfer(msg.sender, amount);
224    }
225
226    /**
227     * @notice Triggers stopped state
228     * @dev Only possible when contract not paused.
229     */
230    function pause() external onlyAdmin whenNotPaused {
231        _pause();
232        emit Pause();
233    }
234

JavaScript Tests

Language
Files
Lines
Blanks
Comments
Testing Code
Deployed Code
Complexity
TypeScript & Javascript
61
27379
3763
1532
22084
10029
225

Tests to Code: 22084 / 10029 = 220 %