Prophecy Core - Smart Contract Audit Report
Summary
Prophecy introduces a SecondChancePool lottery system in which users can enter after failing to win the ProphetPool lottery.
We reviewed Prophecy's ChanceToken, ProphetPool, SecondChancePool, Controller, and ReferralAirdrop contracts at commit 8305cc0eb459be501238f80b51411cfab64b3259 on the team's private GitHub.
We previously reviewed the project team's Prophecy Pool here.
Notes on the Contracts:
- The owner can create ProphetPools and SecondaryChancePools at will, and grant other addresses the ability to create pools as well.
- Users can enter into the ProphetPool lottery by depositing ETH or an ERC20 token. The asset used in the lottery, as well as the amount required to enter, will be set by the team.
- The owner has the ability to set the number of participants, number of winners, and the fee percentage on the pool; there are no limitations on these values.
- Further, these values cannot be modified while to pool is in the INPROGRESS state.
- A for loop is used to check if participants are winners. The team must ensure the maximum participants are no more than a few hunded addresses to prevent this loop from hitting the block gas limit.
- When the participant limit has been met, anyone may settle the pool once; this will generate a set of winners.
- Chainlink is used to generate random data securely from off-chain to select lottery winners. This is the industry standard and is resistant to manipulation.
- Upon settling the pool, a portion of the funds will be sent to the project team and the winners will be able to claim the remaining rewards.
- Everyone else will receive 1 ChanceToken which can be used to enter the SecondChancePool lottery.
- Once the rewards have been distributed, the state variables will be reset and a new round will begin.
- The SecondChancePool lottery functions generally the same as the ProphetPool lottery, but users will need 1 ChanceToken in order to enter; The token is burned upon entry.
- The asset used in the reward pool, as well as the amount of it, are set by the project team upon construction and configuration.
- There are no fees associated with the SecondChancePool.
- ChanceToken is an ERC1155 which represents an NFT with common ERC20 functionality.
- Users specified by the owner will be able to mint and burn specific token IDs.
- The Prophecy Core also features a ReferralAirdrop contract.
- The owner may airdrop PRY tokens to a set of referrers as long as they have a referree to match.
- The airdropped tokens are taken from the contract balance, so the owner must ensure the contract balance has a sufficient amount of PRY tokens, or the transaction will fail.
- The owner may withdraw the PRY tokens from the contract balance to any any other contract or wallet address at any time.
- Contract-based wallets are not allowed to use the system.
- SafeMath is utilized to prevent overflows and ReentrancyGuard to prevent reentrancy attacks.
Audit Findings Summary:
- No security issues from outside attackers were identified.
- Ensure trust in the team as they have notable control in the ecosystem.
- Date: June 28th, 2021.
External Threat Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
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 |
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 |
Prophecy Controller Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Lib] AddressArrayUtils
- [Int] indexOf
- [Int] contains
- [Int] hasDuplicate
- [Int] remove
- [Int] removeStorage #
- [Int] pop
- [Int] extend
- [Int] validatePairsWithArray
- [Int] validatePairsWithArray
- [Int] validatePairsWithArray
- [Int] validatePairsWithArray
- [Int] validatePairsWithArray
- [Int] _validateLengthAndUniqueness
+ [Lib] SafeMathChainlink
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
+ [Int] LinkTokenInterface
- [Ext] allowance
- [Ext] approve #
- [Ext] balanceOf
- [Ext] decimals
- [Ext] decreaseApproval #
- [Ext] increaseApproval #
- [Ext] name
- [Ext] symbol
- [Ext] totalSupply
- [Ext] transfer #
- [Ext] transferAndCall #
- [Ext] transferFrom #
+ VRFRequestIDBase
- [Int] makeVRFInputSeed
- [Int] makeRequestId
+ VRFConsumerBase (VRFRequestIDBase)
- [Int] fulfillRandomness #
- [Int] requestRandomness #
- [Pub] #
- [Ext] rawFulfillRandomness #
+ [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
+ ReentrancyGuard
- [Int] #
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ [Lib] Uint256ArrayUtils
- [Int] indexOf
- [Int] contains
- [Int] hasDuplicate
- [Int] remove
- [Int] removeStorage #
- [Int] pop
- [Int] extend
- [Int] _validateLengthAndUniqueness
+ [Int] IWETH (IERC20)
- [Ext] deposit ($)
- [Ext] withdraw #
+ [Int] IController
- [Ext] getWeth
- [Ext] getChanceToken
- [Ext] getVrfKeyHash
- [Ext] getVrfFee
- [Ext] getLinkToken
- [Ext] getVrfCoordinator
- [Ext] getAllPools
+ [Int] IChanceToken
- [Ext] mint #
- [Ext] burn #
+ ProphetPool (VRFConsumerBase, ReentrancyGuard, Ownable)
- [Pub] #
- modifiers: VRFConsumerBase
- [Ext] setPoolRules #
- modifiers: onlyOwner
- [Ext] setFeeRecipient #
- modifiers: onlyOwner
- [Ext] enterPoolEth ($)
- modifiers: onlyValidPool,onlyEOA
- [Ext] enterPool #
- modifiers: onlyValidPool,onlyEOA
- [Ext] settlePool #
- [Ext] collectRewards #
- modifiers: nonReentrant
- [Ext] ($)
- [Ext] getController
- [Ext] getFeeRecipient
- [Ext] getPoolName
- [Ext] getEnterToken
- [Ext] getChanceTokenId
- [Ext] getPoolStatus
- [Ext] getPoolConfig
- [Ext] getTotalEnteredAmount
- [Ext] getRewardPerParticipant
- [Ext] getParticipants
- [Ext] getParticipant
- [Ext] getWinnerIndexes
- [Ext] isWinner
- [Int] _enterPool #
- [Int] _resetPool #
- [Int] _transferEnterToken #
- [Int] _isEthPool
- [Int] _getRandomNumberBlockchain
- [Int] _getRandomNumber #
- [Int] fulfillRandomness #
+ SecondChancePool (VRFConsumerBase, ReentrancyGuard, Ownable)
- [Pub] #
- modifiers: VRFConsumerBase
- [Ext] ($)
- [Ext] setPoolRules #
- modifiers: onlyOwner
- [Ext] enterPool #
- modifiers: onlyValidPool,onlyEOA
- [Ext] settlePool #
- [Ext] collectRewards #
- modifiers: nonReentrant
- [Ext] getController
- [Ext] getPoolName
- [Ext] getRewardToken
- [Ext] getChanceTokenId
- [Ext] getPoolStatus
- [Ext] getPoolConfig
- [Ext] getParticipants
- [Ext] getParticipant
- [Ext] getWinnerIndexes
- [Ext] isWinner
- [Int] _enterPool #
- [Int] _resetPool #
- [Int] _transferRewardToken #
- [Int] _isEthPool
- [Int] _getRandomNumberBlockchain
- [Int] _getRandomNumber #
- [Int] fulfillRandomness #
+ Controller (Ownable)
- [Pub] #
- [Ext] createProphetPool #
- modifiers: onlyAllowedCreator
- [Ext] createSecondChancePool #
- modifiers: onlyAllowedCreator
- [Ext] updateCreatorStatus #
- modifiers: onlyOwner
- [Ext] getWeth
- [Ext] getChanceToken
- [Ext] getVrfKeyHash
- [Ext] getVrfFee
- [Ext] getLinkToken
- [Ext] getVrfCoordinator
- [Ext] getAllProphetPools
- [Pub] isAllowedCreator
ReferralAirdrop Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Prv] _functionCallWithValue #
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ ReferralAirdrop (Ownable)
- [Pub] #
- [Ext] airdrop #
- modifiers: onlyOwner
- [Ext] emergencyWithdraw #
- modifiers: onlyOwner