YSL.IO Protocol - Smart Contract Audit Report

Summary

 YSLProtocol Audit Report YSL.IO Protocol is launching two new tokens with a presale platform that will be used to raise funds and determine the price of the sYSL token.

We reviewed YSL.IO Protocol's sYSLToken, YSLToken, and Referral contracts at commit d99166c63865bc0d35959aa5891cca8ed78300ae on the team's private GitHub.
We reviewed the PriceDiscovery contract at 0xD61B29106181D0C543841dda7845822facc9DE75 on the Binance Smart Chain mainnet.
We reviewed the ApeAdapter contract at 0xda66efebf2a182dde1690b74e7b40ad0144c880f on the Binance Smart Chain mainnet.

Notes on the Contracts:
  • The total supply of the token is set to 100,000 in the presale platform.
  • The Price Discovery consists of a Private Sale period which lasts for 23 days followed by a Public Sale period which has 7 stages, each lasting 1 day.
  • The Private Sale and Price Discovery start times are set on construction.

  • Users who wish to participate in the Price Discovery period must deposit at least the minimum amount of either BUSD or WBNB during the Private or Public Sale stages; the minimum deposit amount per stage is defined in the PriceDiscovery contract and cannot be modified.
  • The minimum deposit amount does not apply if the user has been added to the airdropped mapping in the Airdrop contract specified in the PriceDiscovery contract; anyone is able to add or remove any address from the airdropped mapping at any time.
  • The deposited WBNB is immediately swapped for BUSD using Pancakeswap and stored in the contract.
  • Whitelisted users will receive 4 times their deposit amount as a bonus during the Private Sale.
  • All users will receive a bonus on their deposits during the Public Sale stages; the multiplier values vary per day and are defined in the PriceDiscovery contract.

  • Users are able to specify a referrer address and signature on each deposit.
  • Upon validating the referrer address and signature in the Referral contract, the system will add an amount equal to 10% of the referree's deposit amount to the deposit amount of the referrer for the current stage as a referral reward.

  • When the Price Discovery period is over, users are able to initiate a withdrawal of sYSL tokens once; these tokens will be timelocked for a period.
  • Users will be eligible to receive an amount of sYSL proportional to the amount of BUSD they contributed to the pool once the timelock period is over.
  • This amount of sYSL tokens is minted on withdrawal and will be locked for a factor of time proportional to the amount of BUSD the user contributed to the pool; the base time lengths are defined in the PriceDiscovery contract and cannot be modified.
  • Portions of the user's tokens are released as the time approaches the timelock duration; these tokens are able to be transferred at will.
  • Users can send locked or unlocked tokens to the zero address if desired.

  • Ownership of the PriceDiscovery contract has been granted to the ApeAdapter contract.
  • When the Price Discovery period is over, the owner of the ApeAdapter contract is able to transfer half of the BUSD deposited in the PriceDiscovery contract to any wallet address, and the second half to the ApeAdapter contract.
  • The owner is able to use the BUSD in the contract to fund ApeSwap liquidity; the liquidity will be locked in the ApeSwap contract forever.
  • The owner is able to transfer any amount of any other ERC20 token erroneously sent to the PriceDiscovery contract to the owner's wallet address.
  • The owner can set the Airdrop contract to any address at any time.
  • The owner can set the sYSL token address to any address only before the price discovery period has begun or while the system is paused.

  • The owner has the Admin role and the Operator role in the Referral contract.
  • The owner is able to grant or revoke the Operator role for any address at any time.
  • An Operator is able to add or remove a referrer's address for any user at any time.

  • The owner has the Admin role and the Minter role in the sYSLToken contract.
  • The owner is able to grant or revoke the Minter role for any address at any time.
  • A Minter is able to mint any amount of sYSL tokens to any wallet address at any time.
  • A Minter is able to burn any amount of sYSL tokens from their own wallet address at any time.

  • The owner is able to grant or revoke the Minter role for any address at any time in the YSLToken contract.
  • A Minter is able to mint any amount of YSL tokens to any wallet address at any time.
  • A Minter is able to burn any amount of YSL tokens from their own wallet address at any time.

  • The contracts utilize Solidity v0.8.4 to prevent overflows along with following the BEP20 standard.

Audit Findings Summary:
  • No security issues from outside attackers were identified.
  • As with any presale, ensure trust in the team prior to investing.
  • Ensure trust in the team as they have notable control in the ecosystem.
  • Date: July 8th, 2021.
  • Updated: July 20th, 2021 to include ApeAdapter contract and modifications to PriceDiscovery contract.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
SuicideN/APASS
State Change External CallsN/APass
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

PriceDiscovery Contract

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Lib] Address 
    - [Int] isContract
    - [Int] sendValue #
    - [Int] functionCall #
    - [Int] functionCall #
    - [Int] functionCallWithValue #
    - [Int] functionCallWithValue #
    - [Int] functionStaticCall
    - [Int] functionStaticCall
    - [Int] functionDelegateCall #
    - [Int] functionDelegateCall #
    - [Prv] _verifyCallResult

 + [Lib] SafeERC20 
    - [Int] safeTransfer #
    - [Int] safeTransferFrom #
    - [Int] safeApprove #
    - [Int] safeIncreaseAllowance #
    - [Int] safeDecreaseAllowance #
    - [Prv] _callOptionalReturn #

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  Ownable (Context)
    - [Pub]  #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Prv] _setOwner #

 +  Pausable (Context)
    - [Pub]  #
    - [Pub] paused
    - [Int] _pause #
       - modifiers: whenNotPaused
    - [Int] _unpause #
       - modifiers: whenPaused

 + [Int] IPancakeRouter02 
    - [Ext] swapExactTokensForTokens #
    - [Ext] getAmountsOut

 + [Int] IERC20Mintable 
    - [Ext] mintFor #
    - [Ext] mintPurchased #
    - [Ext] mint #
    - [Ext] isMinter

 + [Int] IsYSL 
    - [Ext] YSLSupply #
    - [Ext] isMinted #
    - [Ext] mintPurchased #

 + [Int] IReferral 
    - [Ext] hasReferral
    - [Ext] referrals
    - [Ext] proccessReferral #

 + [Int] IAirdrop 
    - [Ext] isAirdropped

 +  PriceDiscovery (Ownable, Pausable)
    - [Pub]  #
    - [Ext] updateStartTime #
       - modifiers: onlyOwner,notStarted
    - [Ext] updateInitialTotalSupply #
       - modifiers: onlyOwner
    - [Ext] setDeadline #
       - modifiers: onlyOwner
    - [Ext] setAirdrop #
       - modifiers: onlyOwner
    - [Ext] setSYSL #
       - modifiers: onlyOwner
    - [Ext] recoverToken #
       - modifiers: onlyOwner,discoveryFinished
    - [Ext] withdrawTeamBUSD #
       - modifiers: onlyOwner,discoveryFinished
    - [Ext] withdrawLiquidityBUSD #
       - modifiers: onlyOwner,discoveryFinished
    - [Ext] deposit #
       - modifiers: discoveryCurrent,supportedToken,whenNotPaused
    - [Int] _deposit #
    - [Ext] sYSLwithdraw #
       - modifiers: discoveryFinished,whenNotPaused
    - [Ext] addToWhitelist #
       - modifiers: onlyOwner
    - [Ext] removeFromWhitelist #
       - modifiers: onlyOwner
    - [Ext] adminPause #
       - modifiers: onlyOwner
    - [Ext] adminUnpause #
       - modifiers: onlyOwner
    - [Pub] getLockTimeByUser
    - [Pub] getDiscoveredPrice
    - [Ext] getDiscoveredSupply
    - [Pub] getTotalDepositedWithBonusesByUser
    - [Ext] getTotalDepositedByUser
    - [Ext] getCurrentMinDeposit
    - [Ext] getMinDepositByUserAndStage
    - [Ext] getMinWBNBDepositByStage
    - [Pub] getCurrentStage
    - [Int] _swapToBusd #

ApeAdapter Contract

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Lib] Address 
    - [Int] isContract
    - [Int] sendValue #
    - [Int] functionCall #
    - [Int] functionCall #
    - [Int] functionCallWithValue #
    - [Int] functionCallWithValue #
    - [Int] functionStaticCall
    - [Int] functionStaticCall
    - [Int] functionDelegateCall #
    - [Int] functionDelegateCall #
    - [Prv] _verifyCallResult

 + [Lib] SafeERC20 
    - [Int] safeTransfer #
    - [Int] safeTransferFrom #
    - [Int] safeApprove #
    - [Int] safeIncreaseAllowance #
    - [Int] safeDecreaseAllowance #
    - [Prv] _callOptionalReturn #

 +  Initializable 

 +  ContextUpgradeable (Initializable)
    - [Int] __Context_init #
       - modifiers: initializer
    - [Int] __Context_init_unchained #
       - modifiers: initializer
    - [Int] _msgSender
    - [Int] _msgData

 +  OwnableUpgradeable (Initializable, ContextUpgradeable)
    - [Int] __Ownable_init #
       - modifiers: initializer
    - [Int] __Ownable_init_unchained #
       - modifiers: initializer
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Prv] _setOwner #

 + [Int] IPancakeRouter 
    - [Ext] addLiquidity #

 + [Int] IPriceDiscovery 
    - [Ext] amountAvailableToClaim #
    - [Ext] sYSLTokenPrice #
    - [Ext] usdEquivalentOfTotalAmountCollected #
    - [Ext] BUSDContract #
    - [Ext] YSLSupply #

 + [Int] IsYSL 
    - [Ext] YSLSupply #
    - [Ext] isMinted #
    - [Ext] mintPurchased #

 +  ApeAdapter (Initializable, OwnableUpgradeable)
    - [Ext] initialize #
       - modifiers: initializer
    - [Ext] setPair #
       - modifiers: onlyOwner
    - [Ext] withdrawTeam #
       - modifiers: onlyOwner
    - [Ext] withdrawLiquidity #
       - modifiers: onlyOwner
    - [Ext] recoverToken #
       - modifiers: onlyOwner
    - [Ext] setAirdrop #
       - modifiers: onlyOwner
    - [Ext] setSYSL #
       - modifiers: onlyOwner
    - [Ext] setDeadline #
       - modifiers: onlyOwner
    - [Ext] addLiquidityApe #
       - modifiers: onlyOwner,pairInitialized
    - [Ext] neverWithdraw #
       - modifiers: onlyOwner,pairInitialized

sYSLToken Contract

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Int] IERC20Metadata (IERC20)
    - [Ext] name
    - [Ext] symbol
    - [Ext] decimals

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  ERC20 (Context, IERC20, IERC20Metadata)
    - [Pub]  #
    - [Pub] name
    - [Pub] symbol
    - [Pub] decimals
    - [Pub] totalSupply
    - [Pub] balanceOf
    - [Pub] transfer #
    - [Pub] allowance
    - [Pub] approve #
    - [Pub] transferFrom #
    - [Pub] increaseAllowance #
    - [Pub] decreaseAllowance #
    - [Int] _transfer #
    - [Int] _mint #
    - [Int] _burn #
    - [Int] _approve #
    - [Int] _beforeTokenTransfer #
    - [Int] _afterTokenTransfer #

 +  Ownable (Context)
    - [Pub]  #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Prv] _setOwner #

 + [Lib] Strings 
    - [Int] toString
    - [Int] toHexString
    - [Int] toHexString

 + [Int] IERC165 
    - [Ext] supportsInterface

 +  ERC165 (IERC165)
    - [Pub] supportsInterface

 + [Int] IAccessControl 
    - [Ext] hasRole
    - [Ext] getRoleAdmin
    - [Ext] grantRole #
    - [Ext] revokeRole #
    - [Ext] renounceRole #

 +  AccessControl (Context, IAccessControl, ERC165)
    - [Pub] supportsInterface
    - [Pub] hasRole
    - [Int] _checkRole
    - [Pub] getRoleAdmin
    - [Pub] grantRole #
       - modifiers: onlyRole
    - [Pub] revokeRole #
       - modifiers: onlyRole
    - [Pub] renounceRole #
    - [Int] _setupRole #
    - [Int] _setRoleAdmin #
    - [Prv] _grantRole #
    - [Prv] _revokeRole #

 +  sYSLToken (ERC20, Ownable, AccessControl)
    - [Pub]  #
       - modifiers: ERC20
    - [Ext] setMinter #
       - modifiers: onlyOwner
    - [Ext] removeMinter #
       - modifiers: onlyOwner
    - [Ext] addToWhitelist #
       - modifiers: onlyOwner
    - [Ext] removeFromWhitelist #
       - modifiers: onlyOwner
    - [Ext] isMinter
    - [Ext] mint #
       - modifiers: minterOnly
    - [Ext] mintFor #
       - modifiers: minterOnly
    - [Ext] mintPurchased #
       - modifiers: minterOnly
    - [Ext] burn #
       - modifiers: minterOnly
    - [Ext] burnFrom #
       - modifiers: minterOnly
    - [Pub] lockedTokens
    - [Pub] lockedTransferrableTokens
    - [Ext] unlockedTokens
    - [Ext] availableTokens
    - [Int] _beforeTokenTransfer #
    - [Pub] unlock #

YSLToken Contract

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Int] IERC20Metadata (IERC20)
    - [Ext] name
    - [Ext] symbol
    - [Ext] decimals

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  ERC20 (Context, IERC20, IERC20Metadata)
    - [Pub]  #
    - [Pub] name
    - [Pub] symbol
    - [Pub] decimals
    - [Pub] totalSupply
    - [Pub] balanceOf
    - [Pub] transfer #
    - [Pub] allowance
    - [Pub] approve #
    - [Pub] transferFrom #
    - [Pub] increaseAllowance #
    - [Pub] decreaseAllowance #
    - [Int] _transfer #
    - [Int] _mint #
    - [Int] _burn #
    - [Int] _approve #
    - [Int] _beforeTokenTransfer #
    - [Int] _afterTokenTransfer #

 +  Ownable (Context)
    - [Pub]  #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Prv] _setOwner #

 + [Lib] Strings 
    - [Int] toString
    - [Int] toHexString
    - [Int] toHexString

 + [Int] IERC165 
    - [Ext] supportsInterface

 +  ERC165 (IERC165)
    - [Pub] supportsInterface

 + [Int] IAccessControl 
    - [Ext] hasRole
    - [Ext] getRoleAdmin
    - [Ext] grantRole #
    - [Ext] revokeRole #
    - [Ext] renounceRole #

 +  AccessControl (Context, IAccessControl, ERC165)
    - [Pub] supportsInterface
    - [Pub] hasRole
    - [Int] _checkRole
    - [Pub] getRoleAdmin
    - [Pub] grantRole #
       - modifiers: onlyRole
    - [Pub] revokeRole #
       - modifiers: onlyRole
    - [Pub] renounceRole #
    - [Int] _setupRole #
    - [Int] _setRoleAdmin #
    - [Prv] _grantRole #
    - [Prv] _revokeRole #

 +  YSLToken (ERC20, Ownable, AccessControl)
    - [Pub]  #
       - modifiers: ERC20
    - [Ext] isMinter
    - [Ext] mintFor #
       - modifiers: _isMinter
    - [Ext] mint #
       - modifiers: _isMinter
    - [Ext] burnFrom #
       - modifiers: _isMinter
    - [Ext] burn #
       - modifiers: _isMinter
    - [Ext] setMinter #
       - modifiers: onlyOwner
    - [Ext] removeMinter #
       - modifiers: onlyOwner

Referral Contract

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  Ownable (Context)
    - [Pub]  #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Prv] _setOwner #

 + [Lib] Strings 
    - [Int] toString
    - [Int] toHexString
    - [Int] toHexString

 + [Int] IERC165 
    - [Ext] supportsInterface

 +  ERC165 (IERC165)
    - [Pub] supportsInterface

 + [Int] IAccessControl 
    - [Ext] hasRole
    - [Ext] getRoleAdmin
    - [Ext] grantRole #
    - [Ext] revokeRole #
    - [Ext] renounceRole #

 +  AccessControl (Context, IAccessControl, ERC165)
    - [Pub] supportsInterface
    - [Pub] hasRole
    - [Int] _checkRole
    - [Pub] getRoleAdmin
    - [Pub] grantRole #
       - modifiers: onlyRole
    - [Pub] revokeRole #
       - modifiers: onlyRole
    - [Pub] renounceRole #
    - [Int] _setupRole #
    - [Int] _setRoleAdmin #
    - [Prv] _grantRole #
    - [Prv] _revokeRole #

 +  Referral (Ownable, AccessControl)
    - [Pub]  #
    - [Ext] adminAddReferal #
       - modifiers: operatorOnly
    - [Ext] adminDeleteReferral #
       - modifiers: operatorOnly
    - [Ext] setOperator #
       - modifiers: onlyOwner
    - [Ext] removeOperator #
       - modifiers: onlyOwner
    - [Ext] isOperator
    - [Ext] proccessReferral #
       - modifiers: operatorOnly
    - [Pub] formReferral
    - [Pub] hasReferral
    - [Int] hashMessage
    - [Int] getSigner
    - [Int] recoverAddress