FLOKI - Smart Contract Audit Report

Audit Summary

FLOKI Audit Report FLOKI is building a new ERC20 token with DAO functionality allowing for decentralized governance within the protocol.

For this audit, we reviewed the StaticTaxHandler, TreasuryHandlerAlpha, ZeroTaxHandler, and ZeroTreasuryHandler at commit e94179f25c2e6f28e349763b83beef65ad3187fa on the team's public GitHub and the FLOKI contract at 0xcf0c122c6b73ff809c693db761e7baebe62b6a2e on the Ethereum blockchain.

We previously reviewed the team's token contract on BSC here and on ETH here.

Please ensure trust in the team prior to investing as they have some control in the ecosystem.
Date: January 13th, 2022.
Updated: January 17th, 2022 to support changes from commit dbd3489e6186c9c3e7233a1eaa550bd9dfcb1cb1 to commit 97acb1113cb6facfb43c94bc0c591df2a289d04c.
Updated: January 18th, 2022 with the new FLOKI deployment address.
Updated: January 22nd, 2022 to support changes from commit 97acb1113cb6facfb43c94bc0c591df2a289d04c on the team's private GitHub to commit e94179f25c2e6f28e349763b83beef65ad3187fa on the team's public GitHub.

Contracts Overview

FLOKI Contract:
  • The total supply of the token is initially set to 10 trillion.
  • No mint or burn functions exist, though the circulating supply can be decreased by sending tokens to the 0x..dead address.
  • At the time of this report, 14.43% of the total supply is stored in the 0x..dead address.
  • 12.58% of the total supply is held in an OKLGAtomicSwapInstance functioning as the FLOKI bridge.
  • There is a tax fee taken on buys and sells from specified "exchange pools" and sent to a Treasury address controlled by the team when neither the sender nor the recipient are whitelisted from fees.
  • Addresses on the whitelist are exempt from fees. If either the sender or receiver are exempt, no fees are taken.
  • Each FLOKI token additionally represents votes intended to be used in a DAO where one token represents one vote.
  • Users may delegate their votes to another address allowing them to vote on behalf of the user.
  • Once votes are delegated, the user must explicitly delegate back to themselves to regain their votes.
  • Users also have the option to delegate through the use of a signed message, allowing for a gasless delegation for the user.
  • The owner may update the tax and treasury addresses used during fee calculation at any time
TreasuryPool Contract:
  • This contract is used to send collected fees to the team as well as perform automatic liquidity adds.
  • During any sell, the balance of this contract is checked to see if there is any FLOKI collected from fees.
  • If there is FLOKI in the contract, the contract will perform an automatic liquidity add.
  • First, a check is done whether the contract's token balance is larger than a specified percentage in the "primary exchange". If it is larger, the percentage will be set to the specified percentage.
  • A liquidity-add is funded by selling the specified "liquidity percentage" of tokens collected as fees, pairing the received ETH with the token, and adding it as liquidity to the ETH pair.
  • Any remaining ETH is sent to a Treasury address controlled by the team.
  • The owner may update the liquidity percentage and max allowed percentage for swap and liquify functionality at any time.
  • The owner may update the Treasury address at any time.
  • The owner may withdraw any ERC20 token in the contract at any time. We recommend the team exclude the designated token from this functionality.
StaticTaxHandler Contract:
  • This contract is used to manage the FLOKI tax rate as well as exempted addresses.
  • The owner may update the tax rate at any time, but the value may only be decreased.
  • The owner may add and remove addresses from the whitelist at any time.
  • The owner may add and remove addresses as designated exchange pools at any time.
  • The owner may set the primary exchange pool at any time.
General Notes Across All Contracts:
  • If the team wishes to implement the FLOKI token with no fees, they may use the ZeroTreasureHandler and ZeroTaxHandler contracts in place of the TreasuryHandlerAlpha and StaticTaxHandler contracts. These contracts will always return 0 when calculating any tax value.
  • As the contracts are implemented in Solidity 0.8.X, they are protected from overflows.
  • Proper structuring of logic to prevent reentrancy attacks.

Resolved Issues

TreasuryHandlerAlpha.sol - Finding #1 - Medium

Description: The team may use the withdraw() function to withdraw any ERC20 token, including the designated token, from the contract.
Risk/Impact: Withdrawing all of the designated token will break any swap and liquify functionality intended to maintain adequate liquidity. The team will also gain voting power as well.
Recommendation: The team should prevent the withdrawal of the designated token using the following line:
require(tokenAddress != address(token));
Resolution: The team has implemented the recommendation described above.

TreasuryHandlerAlpha.sol - Finding #2 - Informational

Description: The maximum percentage of tokens to be swapped during a swap and liquify is uncapped.
Risk/Impact: If too large of a value is set, a swap and liquify may result in large shifts in the token's value within a trading pool.
Recommendation: The team should exercise caution to not set too high of a limit.
Resolution: The team has implemented the recommendation described above, with a limit of 15% price impact value in the swap and liquify functionality.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Centralization of ControlThe team has transferred control to a MultiSig wallet.PASS
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
Logical IssuesN/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

FLOKI Contract

smart_contract_audit_company

token_audit


 ($) = payable function
 # = non-constant function

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

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

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

 + [Int] IGovernanceToken 
    - [Ext] getVotesAtBlock

 + [Int] ITaxHandler 
    - [Ext] getTax

 + [Int] ITreasuryHandler 
    - [Ext] beforeTransferHandler #
    - [Ext] afterTransferHandler #

 +  FLOKI (IERC20, IGovernanceToken, Ownable)
    - [Pub]  #
    - [Pub] name
    - [Ext] symbol
    - [Ext] decimals
    - [Pub] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #
    - [Ext] increaseAllowance #
    - [Ext] decreaseAllowance #
    - [Ext] delegate #
    - [Ext] delegateBySig #
    - [Pub] getVotesAtBlock
    - [Ext] setTaxHandler #
       - modifiers: onlyOwner
    - [Ext] setTreasuryHandler #
       - modifiers: onlyOwner
    - [Prv] _delegate #
    - [Prv] _moveDelegates #
    - [Prv] _writeCheckpoint #
    - [Prv] _approve #
    - [Prv] _transfer #

							

TreasuryHandlerAlpha Contract

smart_contract_audit_company

token_audit


 ($) = payable function
 # = non-constant function

 + [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 #
    - [Int] verifyCallResult

 + [Int] IUniswapV2Router01 
    - [Ext] factory
    - [Ext] WETH
    - [Ext] addLiquidity #
    - [Ext] addLiquidityETH ($)
    - [Ext] removeLiquidity #
    - [Ext] removeLiquidityETH #
    - [Ext] removeLiquidityWithPermit #
    - [Ext] removeLiquidityETHWithPermit #
    - [Ext] swapExactTokensForTokens #
    - [Ext] swapTokensForExactTokens #
    - [Ext] swapExactETHForTokens ($)
    - [Ext] swapTokensForExactETH #
    - [Ext] swapExactTokensForETH #
    - [Ext] swapETHForExactTokens ($)
    - [Ext] quote
    - [Ext] getAmountOut
    - [Ext] getAmountIn
    - [Ext] getAmountsOut
    - [Ext] getAmountsIn

 + [Int] IUniswapV2Router02 (IUniswapV2Router01)
    - [Ext] removeLiquidityETHSupportingFeeOnTransferTokens #
    - [Ext] removeLiquidityETHWithPermitSupportingFeeOnTransferTokens #
    - [Ext] swapExactTokensForTokensSupportingFeeOnTransferTokens #
    - [Ext] swapExactETHForTokensSupportingFeeOnTransferTokens ($)
    - [Ext] swapExactTokensForETHSupportingFeeOnTransferTokens #

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

 +  Ownable (Context)
    - [Pub] Constructor #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Int] _transferOwnership #

 + [Lib] EnumerableSet 
    - [Prv] _add #
    - [Prv] _remove #
    - [Prv] _contains
    - [Prv] _length
    - [Prv] _at
    - [Prv] _values
    - [Int] add #
    - [Int] remove #
    - [Int] contains
    - [Int] length
    - [Int] at
    - [Int] values
    - [Int] add #
    - [Int] remove #
    - [Int] contains
    - [Int] length
    - [Int] at
    - [Int] values
    - [Int] add #
    - [Int] remove #
    - [Int] contains
    - [Int] length
    - [Int] at
    - [Int] values

 +  ExchangePoolProcessor (Ownable)
    - [Ext] getExchangePoolAddresses
    - [Ext] addExchangePool #
       - modifiers: onlyOwner
    - [Ext] removeExchangePool #
       - modifiers: onlyOwner
    - [Ext] setPrimaryPool #
       - modifiers: onlyOwner

 +  LenientReentrancyGuard 
    - [Pub] Constructor #

 + [Int] ITreasuryHandler 
    - [Ext] beforeTransferHandler #
    - [Ext] afterTransferHandler #

 +  TreasuryHandlerAlpha (ITreasuryHandler, LenientReentrancyGuard, ExchangePoolProcessor)
    - [Pub] Constructor #
    - [Ext] beforeTransferHandler #
       - modifiers: nonReentrant
    - [Ext] afterTransferHandler #
       - modifiers: nonReentrant
    - [Ext] setLiquidityPercentage #
       - modifiers: onlyOwner
    - [Ext] setPriceImpactPercentage #
       - modifiers: onlyOwner
    - [Ext] setTreasury #
       - modifiers: onlyOwner
    - [Ext] withdraw #
       - modifiers: onlyOwner
    - [Prv] _swapTokensForEth #
    - [Prv] _addLiquidity #

							

StaticTaxHandler Contract

smart_contract_audit_company

token_audit


 ($) = payable function
 # = non-constant function

  + [Lib] EnumerableSet 
    - [Prv] _add #
    - [Prv] _remove #
    - [Prv] _contains
    - [Prv] _length
    - [Prv] _at
    - [Prv] _values
    - [Int] add #
    - [Int] remove #
    - [Int] contains
    - [Int] length
    - [Int] at
    - [Int] values
    - [Int] add #
    - [Int] remove #
    - [Int] contains
    - [Int] length
    - [Int] at
    - [Int] values
    - [Int] add #
    - [Int] remove #
    - [Int] contains
    - [Int] length
    - [Int] at
    - [Int] values

 + [Int] ITaxHandler 
    - [Ext] getTax

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

 +  Ownable (Context)
    - [Pub] Constructor #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Int] _transferOwnership #

 +  ExchangePoolProcessor (Ownable)
    - [Ext] getExchangePoolAddresses
    - [Ext] addExchangePool #
       - modifiers: onlyOwner
    - [Ext] removeExchangePool #
       - modifiers: onlyOwner
    - [Ext] setPrimaryPool #
       - modifiers: onlyOwner

 +  StaticTaxHandler (ITaxHandler, ExchangePoolProcessor)
    - [Pub] Constructor #
    - [Ext] getTax
    - [Ext] setTaxBasisPoints #
       - modifiers: onlyOwner
    - [Ext] addExemption #
       - modifiers: onlyOwner
    - [Ext] removeExemption #
       - modifiers: onlyOwner

							

ZeroTaxHandler Contract

smart_contract_audit_company

token_audit


 ($) = payable function
 # = non-constant function

   + [Int] ITaxHandler 
    - [Ext] getTax

 +  ZeroTaxHandler (ITaxHandler)
    - [Ext] getTax
	

ZeroTreasuryHandler Contract

smart_contract_audit_company

token_audit


 ($) = payable function
 # = non-constant function
 
+ [Int] ITreasuryHandler 
    - [Ext] beforeTransferHandler #
    - [Ext] afterTransferHandler #

 +  ZeroTreasuryHandler (ITreasuryHandler)
    - [Ext] beforeTransferHandler #
    - [Ext] afterTransferHandler #