Shiburai - Smart Contract Audit Report
Audit Summary
Shiburai is releasing a series of contracts allowing users to lock tokens in various ways.
For this audit, we reviewed the ETHLockFactory, ETHLockWallet, LiquidityPairLocker, and LockTokens contracts provided to us by the team.
Audit Findings
Please ensure trust in the team prior to investing as they have some control in the ecosystem.
Date: February 3rd, 2022.
Contracts Overview
ETHLockFactory and ETHLockWallet Contracts:
- The team should exercise caution when using fee on transfer tokens with these contracts, as users may be able to wihtdraw funds they are not entitled to in certain situations.
- The contracts use SafeMath to prevent overflows/underflows.
- The contracts use Reentrancy Guard where appropriate.
LiquidityPairLocker Contract:
- Any user may use this contract to deposit ETH or tokens into a lock, preventing withdrawal until a specified time has passed.
- Users specify an "owner" which is the recipient for the deposited tokens when creating a new lock.
- Once the specified unlock time has passed, the owner may withdraw the deposited tokens at any time.
- All deposited tokens and ETH are subject to the same unlock time no matter when they were deposited.
- There are no fees, beyond the gas cost, for creating, locking, or withdrawing tokens from a lock.
LockTokens Contract:
- Any user may use this contract to lock a valid Uniswap V2 LP token. Tokens may not be withdrawn until a specified time has passed.
- Users specify a lock "owner" which is the recipient for the locked LP Tokens.
- Users must pay either an ETH fee or a "liquidity fee" in the token being locked.
- The liquidity fee defaults to 1% of the amount of token being locked and the ETH fee defaults to 0.1 ETH.
- Both the liquidity and ETH fees collected are transferred to a Dev address controlled by the team.
- If a user is whitelisted and has a sufficient balance of a valid "fee exemption" token, they do not need to pay the ETH fee, if that is the fee type selected.
- Whitelisted users are exempt from the liquidity fee when locking LP tokens.
- Once the specified unlock time has passed, the lock owner may withdraw the deposited tokens at any time.
- Lock owners may extend the lock duration of any of their locks. An additional liquidity fee is taken when extending the lock duration.
- Lock owners may add additional LP tokens to any of the locks that they own. An additional liquidity fee is taken from the original balance before the new LP tokens are added.
- Lock owners may transfer the ownership of any locks they own to any other address.
- If a Migrator address has been set, owners may use the Migrator to move their locks to a new contract. The Migrator contract was outside the scope of this audit, so we cannot provide an assessment with regards to security.
- The contract owner may update the Dev and Migrator address at any time.
- The contract owner may set the ETH fee and liquidity fee to any value at any time.
- The contract owner may add or remove any address from the whitelist at any time.
- Any user may use this contract to create a lock, or series of locks, for a specified token.
- Users specify a lock "owner" which is the recipient for the locked tokens.
- Users also have the option to create a series of locks to simulate a vesting structure. A specified amount of tokens and unlock time is provided for each individual lock allowing for non-linear vesting.
- A fee is taken per lock created and transferred to a Fee wallet controlled by the team; this fee defaults to 0.01 ETH.
- Users that are exempt, or have a sufficient balance of a valid "fee exemption" token, do not have to pay the fee required to lock tokens.
- Once the specified unlock time has passed, the lock owner may withdraw the deposited tokens at any time.
- Lock owners may extend the lock duration of any of their locks.
- Lock owners may transfer the ownership of any locks they own to any other address.
- Any user may add additional tokens to any lock given they have a sufficient token balance.
- The contract owner may update the Fee wallet address at any time.
- The contract owner may set the fee to any value at any time.
External Threat Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
Centralization of Control | WARNING | |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Deprecated Opcodes | N/A | PASS |
Ether Thief | N/A | PASS |
Exceptions | N/A | PASS |
External Calls | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Logical Issues | N/A | PASS |
Multiple Sends | N/A | PASS |
Suicide | N/A | PASS |
State Change External Calls | N/A | PASS |
Unchecked Retval | N/A | PASS |
User Supplied Assertion | N/A | PASS |
Critical Solidity Compiler | N/A | PASS |
Overall Contract Safety | PASS |
ETHWalletFactory Contract
($) = payable function
# = non-constant function
+ [Int] ERC20
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ ETHLockWallet
- [Pub] Constructor #
- [Ext] Fallback ($)
- [Pub] withdraw #
- [Pub] withdrawTokens #
- [Pub] walletInfo
+ ETHLockFactory
- [Pub] createETHLockWallet ($)
- [Pub] getETHWalletsOwned
- [Pub] getETHWalletsCreated
- [Pub] getETHWalletInfo
- [Pub] withdrawTokens #
- [Pub] withdrawETH #
- [Ext] Fallback ($)
LiquidityPairLocker Contract
($) = payable function
# = non-constant function
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Pub] Constructor #
- [Pub] owner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Lib] TransferHelper
- [Int] safeApprove #
- [Int] safeTransfer #
- [Int] safeTransferFrom #
+ [Lib] EnumerableSet
- [Prv] _add #
- [Prv] _remove #
- [Prv] _contains
- [Prv] _length
- [Prv] _at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
+ [Int] IUniswapV2Pair
- [Ext] factory
- [Ext] token0
- [Ext] token1
+ [Int] IUniFactory
- [Ext] getPair
+ [Int] IMigrator
- [Ext] migrate #
+ [Int] ERC20
- [Ext] balanceOf
+ LiquidityPairLocker (Ownable)
- [Pub] Constructor #
- [Pub] setDev #
- modifiers: onlyOwner
- [Pub] setMigrator #
- modifiers: onlyOwner
- [Pub] setFees #
- modifiers: onlyOwner
- [Pub] whitelistFeeAccount #
- modifiers: onlyOwner
- [Ext] lockLPToken ($)
- modifiers: ReEntrancyGuard
- [Ext] extendlock #
- modifiers: ReEntrancyGuard
- [Ext] withdraw #
- modifiers: ReEntrancyGuard
- [Ext] incrementLock #
- modifiers: ReEntrancyGuard
- [Ext] transferLockOwnership #
- [Ext] migrate #
- modifiers: ReEntrancyGuard
- [Ext] getNumLocksForToken
- [Ext] getNumLockedTokens
- [Ext] getLockedTokenAtIndex
- [Ext] getUserNumLockedTokens
- [Ext] getUserLockedTokenAtIndex
- [Ext] getUserNumLocksForToken
- [Ext] getUserLockForTokenAtIndex
LockTokens Contract
($) = payable function
# = non-constant function
+ [Lib] SafeMath
- [Int] sub
- [Int] add
- [Int] mul
+ [Int] ERC20
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ LockTokens
- [Pub] Constructor #
- [Pub] lockTokens ($)
- modifiers: ReEntrancyGuard
- [Pub] createVest ($)
- modifiers: ReEntrancyGuard
- [Prv] _lockTokens #
- [Pub] withdrawAllTokens #
- modifiers: ReEntrancyGuard
- [Pub] extendLock #
- modifiers: ReEntrancyGuard
- [Pub] addToLock #
- modifiers: ReEntrancyGuard
- [Ext] getTokenLockInformation
- [Ext] getTokenLocksCreatedByAddress
- [Ext] getLockedTokensOwnedByAddress
- [Ext] getLockedTokensByTokenAddress
- [Ext] transferVestOwnerShip #
- [Ext] setFeeCollectorWallet #
- modifiers: onlyOwner
- [Ext] setETHFee #
- modifiers: onlyOwner
- [Ext] getTime