Smart Contract Audit Report
Susumi Crowdfunding is a new smart contract allowing users to raise funds for SUSU tokens through Campaigns.
For this audit, we reviewed the project team's SusumiCrowdfunding contract at 0x1Ee55a4791D20ee9511E3e0A8F30B0b549f78e43 on the Binance Smart Chain Mainnet.
We previously reviewed the project team's Public Sale contract here and token contract here.
All findings have been resolved, though some centralized aspects are present.
Date: September 2nd, 2022.
Updated: September 7th, 2022 with resolutions to findings and updated address.
Updated: September 19th, 2022 with Mainnet address.
Finding #1 - SusumiCrowdfunding - High (Resolved)Description: A Campaign creator can claim their activation fee from a matured Campaign and are still able to restart it.
Risk/Impact: In certain circumstances, a user could create their Campaign for free.
Recommendation: A user should not be able to restart a matured Campaign that has a true isClaimed value.
Resolution: The team has implemented the above solution.
Finding #2 - SusumiCrowdfunding - Medium (Resolved)Description: A creator can restart a matured Campaign while user's funds are still deposited.
Risk/Impact: A creator could trap a user's funds until the Campaign succeeds by continually restarting a Campaign as soon as it matures even if the user wishes to withdraw their donation.
Recommendation: The team should consider adding a grace period before allowing a creator to restart their Campaign. They should also consider not allowing a Campaign to be restarted and instead require creators to make a new Campaign.
Resolution: The team has implemented the above solution with a grace period of 24 hours before creators may restart their campaign.
Finding #3 - SusumiCrowdfunding - Informational (Resolved)Description: The team has included functions for testing purposes only.
Recommendation: The team should ensure to remove these functions before deploying to prevent excess centralization of control.
Resolution: The team has removed the functions in the Mainnet deployment.
This contract is used to crowdfund for SUSU tokens through user-created Campaigns. Any user that does not have a current campaign may create a new campaign. Campaigns have various attributes based on the level of the Campaign. Users may only create a Campaign with a level up to their own level. The maximum amount of donators will be set to the "min key value" for the level of the Campaign. The goal amount of total BUSD the Campaign intends to raise must be between the minimum and maximum amount for the level of the Campaign. Users will be charged an activation fee based on the ratio of the goal amount of total BUSD for the Campaign relative to the maximum number of donators allowed and the current price. The price is adjusted based on the contract's SUSU balance each time a Campaign is created or completed. The Campaign's price per SUSU token will be set to the current price. The user's current campaign will be set to the newly created one. Users that are level 2 or higher may request a custom Campaign. Custom Campaigns may specify a maximum number of donors between the min key value and max key value for the Campaign's level. Users creating a custom Campaign must pay the activation fee and an additional "receiver SUSU" fee to the Receiver address. Users that have donated to a Campaign may create a new Campaign through a "claim". This method of creating a Campaign will use the user's earned SUSU tokens to pay the activation fee for the Campaign. Campaigns created through a claim may specify a maximum number of donors between the min key value and max key value for the Campaign's level. The user's current Campaign must be inactive or its maturity time passed. Additionally, the Campaign they donated to and earned tokens they are using must be inactive as well.
Any address may donate BUSD to an active Campaign if they have not donated to the Campaign before or they have reclaimed their donation from the Campaign after its "maturity time" has passed. Users will earn tokens equal to the amount they donated divided by the Campaign's token price. Creators may not donate to their own Campaign. The Campaign will be marked inactive if it has reached its goal amount of BUSD after the donation. The Campaign's creator's level will increase by one, to a maximum level of 3, if their current level is the same as the Campaign's level. Additionally, the current price will increase based on the contract's SUSU balance. A Campaign's creator can withdraw the donated BUSD from their Campaign once it is no longer active. The Receiver address will receive a "receiver share" of the BUSD based on the Campaign's level. Users that donated to a Campaign may claim their earned SUSU when the Campaign is no longer active and their vesting period has passed from when the Campaign expired. A user's vesting period will be determined by the amount of tokens being vested; all vesting levels default to 100 days. Sufficient SUSU tokens must be provided to the contract or users will be unable to claim their rewards. Users may claim their donated BUSD from a Campaign if it is still active when its maturity time has passed. A Campaign's creator may reclaim their SUSU activation fee if the Campaign is still active when the maturity time has passed. This will prevent the creator from restarting the Campaign. A Campaign's creator may restart a Campaign if their current Campaign is not active or its maturity time has passed with an additional grace period of 24 hours. The Campaign's maturity time will be the "default maturity period" in the future. The creator's current campaign will become the restarted one.
The contract employs an OwnableCrowd permission scheme. This is built on the standard Ownable library. In addition to the main owner the contract allows for sub-owners with granular permission for various functions. The owner may add a sub-owner, specifying their specific permissions, at any time. The owner may remove a sub-owner at any time. The owner may update the fee Receiver address at any time. The owner may update the BUSD address at any time.
Any BNB transferred directly to the contract will be sent to the Receiver address. The contract utilizes ReentrancyGuard to protect against reentrancy attacks in applicable functions. As the contract is implemented with Solidity v0.8.7, it is safe from any possible overflows/underflows.
|Arbitrary Jump/Storage Write||N/A||PASS|
|Centralization of Control||The owner may update the Fee Receiver address and BUSD address at any time.||PASS|
|Delegate Call to Untrusted Contract||N/A||PASS|
|Dependence on Predictable Variables||N/A||PASS|
|Improper Authorization Scheme||N/A||PASS|
|Outdated Compiler Version||N/A||PASS|
|Overall Contract Safety||PASS|
($) = payable function # = non-constant function Int = Internal Ext = External Pub = Public + [Lib] TransferHelper - [Int] safeApprove # - [Int] safeTransfer # - [Int] safeTransferFrom # - [Int] safeTransferETH # + [Lib] SusuLibrary + Ownable - [Pub] Constructor # - [Pub] addSubOwner # - modifiers: onlyOwner - [Pub] removeSubOwner # - modifiers: onlyOwner - [Pub] transferOwnership # - modifiers: onlyOwner - [Int] _setOwner # + ReentrancyGuard - [Pub] Constructor # + [Int] Token - [Ext] decimals - [Ext] symbol - [Ext] totalSupply - [Ext] balanceOf - [Ext] transfer # - [Ext] allowance - [Ext] transferFrom # + [Int] ISusumiCrowdfunding - [Ext] createCampaign # - [Ext] requestCustomCampaign # - [Ext] createCampaignUsingClaim # - [Ext] calculateSUSUActivation - [Ext] donateToCampaign # - [Ext] withdrawRaisedAmount # - [Ext] claimRewards # - [Ext] claimDonationAfterMaturity # - [Ext] claimStakeAfterMaturity # - [Ext] restartMaturedCampaign # + SusumiCrowdfunding (Ownable, ReentrancyGuard, ISusumiCrowdfunding) - [Ext] Receive Ether ($) - [Pub] initialize # - [Pub] setSusuValueInfo # - modifiers: onlySubOwner - [Pub] addUpdateVestingInfo # - modifiers: onlySubOwner - [Int] getVestingValue - [Ext] createCampaign # - modifiers: nonReentrant,checkUserCampaignStatus - [Int] campaignInternal # - [Int] newCampaignInternal # - [Ext] requestCustomCampaign # - modifiers: nonReentrant,checkUserCampaignStatus - [Ext] createCampaignUsingClaim # - modifiers: nonReentrant,checkUserCampaignStatus - [Pub] calculateSUSUActivation - [Pub] calculatePriceShare - [Int] setLevelAndCheckValue # - [Ext] donateToCampaign # - modifiers: nonReentrant,validateCampaign - [Ext] withdrawRaisedAmount # - modifiers: nonReentrant,validateCampaign - [Ext] claimRewards # - modifiers: validateCampaign - [Ext] claimDonationAfterMaturity # - modifiers: isCampaignMaturityOver - [Ext] claimStakeAfterMaturity # - modifiers: isCampaignMaturityOver - [Ext] restartMaturedCampaign # - modifiers: isCampaignMaturityOver - [Ext] updateDefaultMaturity # - modifiers: onlySubOwner - [Ext] updateReceiverFeeUSDT # - modifiers: onlySubOwner - [Ext] updateReceiverAddress # - modifiers: onlySubOwner - [Int] checkSusuAmount - [Pub] updateBUSDAddress # - modifiers: onlyOwner
SourceHat (formerly Solidity Finance - founded in 2020) has quickly grown to have one of the most experienced and well-equipped smart contract auditing teams in the industry. Our team has conducted 1300+ solidity smart contract audits covering all major project types and protocols, securing a total of over $50 billion U.S. dollars in on-chain value across 1500 projects!.
Our firm is well-reputed in the community and is trusted as a top smart contract auditing company for the review of solidity code, no matter how complex. Our team of experienced solidity smart contract auditors performs audits for tokens, NFTs, crowdsales, marketplaces, gambling games, financial protocols, and more!
Contact us today to get a free quote for a smart contract audit of your project!
What is a Solidity Audit?
Typically, a smart contract audit is a comprehensive review process designed to discover logical errors, security vulnerabilities, and optimization opportunities within code. A Solidity Audit takes this a step further by verifying economic logic to ensure the stability of smart contracts and highlighting privileged functionality to create a report that is easy to understand for developers and community members alike.
How Do I Interpret the Findings?
Each of our Findings will be labeled with a Severity level. We always recommend the team resolve High, Medium, and Low severity findings prior to deploying the code to the mainnet. Here is a breakdown on what each Severity level means for the project:
- High severity indicates that the issue puts a large number of users' funds at risk and has a high probability of exploitation, or the smart contract contains serious logical issues which can prevent the code from operating as intended.
- Medium severity issues are those which place at least some users' funds at risk and has a medium to high probability of exploitation.
- Low severity issues have a relatively minor risk association; these issues have a low probability of occurring or may have a minimal impact.
- Informational issues pose no immediate risk, but inform the project team of opportunities for gas optimizations and following smart contract security best practices.