Customer : Populous Date : December 3 1 rd , 20 20 SMART CONTRACT CODE REVIEW AND SECURITY ANALYSIS REPORT This document may contain confidential information about IT systems and the intellectual property of the C ustomer as well as information about potential vulnerabilities and methods of their explo itation. The report containing confidential information can b e used internally by the C ustomer , or it can be disclosed publicly after all vulnerabilities fixed - upon a decision of the C ustomer. Document Name Smart Contract Code Review and Security Analy sis Report for Populous Approved by Andrew Matiukhin | CTO Hacken OU Type Multiple purpose s contracts Platform Ethereum / Solidity Methods Architecture Review, Functional Testing, Computer - Aided Verification, Manual Review Repository https://github.c om/bitpopulous/defi_audits/ Commit 3944 B 72830 AA 1 F 514 ECBEEFCD 11 EDBF 3 EC 377 C 53 Deployed contract Timeline 2 1 DEC 2020 – 3 1 DEC 2020 Changelog 30 DEC 2020 – I NITIAL A UDIT Table of contents Intr oduction ................................ ................................ ................................ .......................... 4 Scope ................................ ................................ ................................ ................................ .... 4 Executive Summary ................................ ................................ ................................ ............... 5 Severity Definit ions ................................ ................................ ................................ ............... 6 AS - IS overview ................................ ................................ ................................ ...................... 7 Conclusion ................................ ................................ ................................ .......................... 29 Disclaimers ................................ ................................ ................................ .......................... 30 Int roduction Hacken OÜ (Consultant) was contracted by Populous (Customer) to conduct a Smart Contract Code Review and Security Analysis. This report presents the findings of the security assessment of Customer ' s smart contract and its code review conducted be tween December 2 1 st , 2020 – December 3 1 st , 2020. Scope The scope of the project is smart contract s in the repository: Contract deployment address: Repository Commit Files: / reward/ RewardPoolAddressManager .sol / reward/ RewardPool .sol / lendingpool/Lendi ngPoolConfigurator.sol /lendingpool/LendingPoolDataProvider.sol /lendingpool/LendingPool.sol / governance / governance/PopulousProtoGovernance.sol / governance/governance/governance/PopulousPropositionPower.sol / governance/governance/GovernanceParamsProvid er.sol /governance/governance/AssetVotingWeightProvider.sol We have scanned this smart contract for commonly known and more specific vulnerabilitie s. Here are some of the commonly known vulnerabilities that are considered: Category Check Item Code review ▪ Reentrancy ▪ Ownership Takeover ▪ Timestamp Dependence ▪ Gas Limit and Loops ▪ DoS with (Unexpected) Throw ▪ DoS with Block Gas Limit ▪ Transaction - Ordering Dependence ▪ Style guide violation ▪ Costly Loop ▪ ERC20 API violation ▪ Unchecked external call ▪ Unchecked math ▪ Unsafe type inference ▪ Implicit visibility level ▪ Deployment Consistency ▪ Repository Consistency ▪ Data Consistency Functional review ▪ Business Logics Review ▪ Functionality Checks ▪ Access Control & Authorization ▪ Escrow manipulation ▪ Token Supply manipulation ▪ Assets inte grity ▪ User Balances manipulation ▪ Kill - Switch Mechanism ▪ Operation Trails & Event Generation Executive Summary According to the assessment, the Customer's smart contracts has some issues that should be fixed Our team performed an analysis of code fun ctionality, manual audit, and automated checks with Mythril and Slither. All issues found during automated analysis were manually reviewed , and important vulnerabilities are presented in the Audit overview section. A general overview is presented in AS - IS section , and all found issues can be found in the Audit overview section. Security engineers found 1 critical, 2 high, 5 medium, 5 low, and 2 informational issue during the audit. Notice: some contracts in the repository are not in the audit scope. They ca n be used by or can use contacts from the scope. During the audit we consider out - of - scope contracts as secure but cannot guaranty that they really are. We recommend reviewing those contr acts before using the system. Due to the limite d scope, we cannot gua rantee that the whole system will work properly all together. We recommend performing the full audit and UAT testing at the production environment as it can reveal issues which cannot be reproduced during the audit. Insecure Poor secured Secured Well - secured You are here Graph 1. The distribution of vulnerabi lities after the first review Severity Definitions Risk Level Description Critical Critical vulnerabilities are usually straightforward to exploit and can lead to assets los s or data manipulations. High High - level vulnerabilities are difficult to expl oit; however, they also have a significant impact on smart contract execution, e.g. , public access to crucial functions Medium Medium - level vulnerabilities are important to fix; however, they can ' t lead to assets los s or data manipulations. Low Low - level vulnerabilities are mostly related to outdated, unused , etc. code snippets that can ' t have a significant impact on execution Lowest / Code Style / Best Practice Lowest - level vulnerabilities, code style violations , and info statements can ' t affect smart c ontract execution and can be ignored. Medium 36% Low 36% Informational 7% Critical 7% High 14% Medium Low Informational Critical High AS - IS overview LendingPool .sol Description LendingPool is a contract used to provide a loans and flash - loans functionality. Imports LendingPool contract has the following imports: • @openzeppelin/contracts/math/Saf eMath.sol • @openzeppelin/contracts/utils/ReentrancyGuard.sol • @openzeppelin/contracts/utils/Address.sol • @openzeppelin/contracts/token/ERC20/IERC20.sol • ../libraries/openzeppelin - upgradeability/VersionedInitializable.sol • ../configuration/LendingPoolAddressesPr ovider.sol • ../configuration/LendingPoolParametersProvider.sol • ../tokenization/PToken.sol • ../libraries /CoreLibrary.sol • ../libraries/WadRayMath.sol • ../interfaces/IFeeProvider.sol • ../flashloan/interfaces/IFlashLoanReceiver.sol • ./LendingPoolCore.sol • ./LendingP oolDataProvider.sol • ./LendingPoolLiquidationManager.sol • ../libraries/EthAddressLib.sol • ./LendingPoolC onfigurator.sol • ./DefaultReserveInterestRateStrategy.sol Inheritance LendingPool contract is ReentrancyGuard , VersionedInitializable Usages LendingPool co ntract has following usages: • SafeMath for uint256 • WadRayMath for uint256 • Address for address Structs LendingPool contract has following data structures: • BorrowLocalVars – used for local computations in the ` borrow ` function • RepayLocalVars – used for lo cal computations in the ` repay ` function Enums LendingPool contract has no custom enums. Events LendingPool contract has following events : • Deposit – emitted on deposit. • RedeemUnderlying – mitted during a redeem action. • Borrow – emitted on borrow. • Repay – emitted on repay. • Swap - emitted when a user performs a rate swap. • ReserveUsedAsCollateralEnabled – emitted when a user enables a reserve as collateral. • ReserveUsedAsCollateralDisabled – emitted when a user disables a reserve as collateral. • RebalanceStabl eBorrowRate – emitted when the stable rate of a user gets rebalanced. • FlashLoan – emitted when a flashloan is executed. • OriginationFeeLiquidated – emitted when a borrow fee is liquidated. • LiquidationCall – emitted when a borrower is liquidated. Modifiers L endingPool has the following modifiers: • onlyO verlyingPToken – functions affected by this modifier can only be invoked by the PToken contract • onlyActiveReserve - functions affected by this modifier can only be invoked if the reserve is active. • onlyUnfreez edReserve – functions affected by this modifie r can only be invoked if the reserve is not frozen. • onlyAmountGreaterThanZero – functions affected by this modifier can only be invoked if the provided ` _amount ` input parameter is not zero. Fields LendingPool contract has following constants and fields : • LendingPoolAddressesProvider public addressesProvider • LendingPoolCore public core • LendingPoolDataProvider public dataProvider • LendingPoolParametersProvider public parametersProvider • IFeeProvider feeProvider • uint 256 public constant UINT_MAX_VAL UE = uint256( - 1) • uint256 public constant LENDINGPOOL_REVISION = 0x5 Function s LendingPool has following public functions: • initialize Description Initializes the contract Visibility public Input parameters o LendingPoolAddr essesProvider _addressesProvider – the address of the LendingPoolAddressesProvider registry Constraints o Can only be called once. Events emit None Output None • deposit Description D eposits t he underlying asset into the reserve. A corresponding amount of t he overlying asset (PTokens) is minted. Visibility external payable Input parameters o address _reserve – the reserve address. o uint256 _amount – an amount to be deposited. o uint16 _referralCode – referral code. Constraints o onlyActive Reserve modifier. o onlyUnf reezedReserve modifier. o onlyAmountGreaterThanZero modifier. Events emit Emits the Deposit event. Output None • redeemUnderlying Description Redeems the underlying amount of assets requested by ` _user ` Visibility external Input parameters o address _reserve – the reserve address. o address payable _user – the address of the user performing the action o uint256 _amount – the underlying amount to be redeemed o uint256 _PTokenBalanceAfterRedeem – PToken balance after redeem. Constraints o onlyOverlyingPToken modifier. o onlyActiveReserve modifier. o onlyAmountGreaterThanZero modifier. o The ` _ amount` should be less or equal to ` currentAvailableLiquidity `. Events emit Emits the RedeemUnderlying event. Output None • calculateUserReserveCollateralETHInvoicePool Description Rede ems the underlying amount of assets requested by ` _user ` Visibility public view Input parameters o address _reserve – the reserve address. o address payable _user – the address of the user performing the action o uint256 _amount – the underlying amount to be r edeemed o uint256 _PTokenBalanceAfterRedeem – PToken balance after redeem. Constraints o Stable interest rates should be set for reserve to borrow from o O nly stable rate mode allowed o A ` userCollateralBalanceETH ` should not exceed the ` amountOfCollateralNeede dETH ` Events emit None Output o b ool – always true. o uint256 – userCollateralBalanceETH o uint256 – amountOfCollateralNeededETH • borrow Description Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower already deposited enough collateral Visibility external Input parameters o address _reserve – the reserve address. o uint256 _amount – an amount to be borrowed. o uint256 _interestRateMode – the interest rate mode at which a user wants to borrow. o uint16 _referralCode – a referral code. Constraints o onlyActiveReserve modi fier. o onlyUnfreezedReserve modifier. o onlyAmountGreaterThanZero modifier. o The `_amount` should be less or equal to ` currentAvailableLiquidity `. o Reserve should be enabled for borrowing o Only STABLE inter est rate mode is allowed. o The `_amount` should not exceed an availableLiquidity o The borrower health factor should not be below threshold. o The borrow fee should be greater than 0. o The borrower should have enough collateral balance to take a loan. o The bor rower should be allowed to borrow at stable interest rate mode. o The `_amount` should not exceed a ` maxLoanSizeStable ` Events emit Emits the Borrow event. Output No n e • repay Description R epays a borrow on the specific reserve, for the specified amount (or for the whole amount, if uint256( - 1) is specified). Visibility external Input parameters o address _reserve – the reserve address. o uint256 _amount – an amount to repay o address payable _onBehalfOf – address for wich msg.sender is repaying. Constraints o only ActiveReserve modifier. o onlyAmountGreaterThanZero modifier. o The user should have an active borrow o If a msg.sender is repaying a borrow for another address, an `_amount` should be an exact sum and cannot be max uint256 value. o msg.value should be equal to ` _value` if repay is in ETH. Events emit Emits the Repay event. Output None • swapBorrowRateMode Description Used to swap between stable and variable borrow rate modes. Visibility external Input parameters o address _reserve – the reserve address. Constrain ts o onlyActiveReserve modifier. o onlyUnfreezedReserve modifier. o msg.sender should have an active borrow. o msg.sender should be allowed to borrow at stable mode if he wants to change it to the variable mode. Events emit Emits the Swap event. Output None • reb alanceStableBorrowRate Description Rebalances the stable interest rate of a user if current liquidity rate > user stable rate. Visibility external Input parameters o address _reserve – the reserve address. o a ddress _user – an address of the user to be rebala nced Constraints o onlyActiveReserve modifier. o ` _user ` should have an active borrow. o ` _user ` should have a variable rate mode. Events emit Emits the RebalanceStableBorrowRate event. Output None • setUserUseReserveAsCollateral Description A llows depositors to enable or disable a specific deposit as collateral. Visibility external Input parameters o address _reserve – the reserve address. o bool _useAsCollateral – true if a user wants to use the deposit as collateral, false otherwise. Constraints o onlyActiveReser ve modifier. o onlyUnfreezedReserve modifier. o msg.sender should have deposited liquidity o Cannot be disabled if already being used as collateral Events emit Emits ReserveUsedAsCollateralEnabled or ReserveUsedAsCollateralDisabled event s Output None • liquida tionCall Description A proxy function u sed to liquidate an undercollateralized position. • flashLoan Description A llows smartcontracts to access the liquidity of the pool within one transaction, as long as the amount taken plus a fee is returned. Visibili ty external Input parameters o address _receiver – the loan receiver. o address _reserve – the reserve address. o uint256 _amount – the loan amount. o bytes memory _params – params to be passed to the receiver. Constraints o onlyActiveReserve modifier. o onlyAmountG reaterThanZero modifier. o `_amount` should not exceed an available liquidity. o _receiver should be a contract that implements the IFlashLoanReceiver interface. o The requested amount should be big enough so that fees will be greater than 0. o In the end of trans action, the contract balance should be equal to the initial balance plus fees. Events emit Emits the FlashLoan event • getReserveConfigurationData , getReserveData , getUserAccountData , getUserReserveData , getReserves Description Simple view functions. LendingPoolConfigurator .sol Description LendingPoolConfigurator allows lending pool manager to configure lending pool parametres. Contains only simple protected setter functions ang getters. LendingPoolDataProvider .sol Description LendingPool DataProvider contains only view functions that allows to receive all the necessary information about the Lending Pool. AssetVotingWeightProvider .sol Description AssetVotingWeightProvider is a contract used to register whitelisted assets with its voting wei ght per asset. Only owner can change voting weights. GovernanceParamsProvider .sol Description GovernanceParamsProvider is a contract used to store parameters of the governance contract. O nly owner can change parameters. PopulousPropositionPower .sol Descrip tion PopulousPropositionPower is an Asset to control the permissions on the actions in PopulousProtoGovernance PopulousProtoGovernance .sol Description PopulousProtoGovernance provides voting functionality Imports PopulousProtoGovernance contract has the following imports: • @openzeppelin/contracts/math/SafeMath.sol • @openzeppelin/contracts/token/ERC20/IERC20.sol • @openzeppelin/contracts/cryptography/ECDSA.s ol • ../interfaces/IGovernanceParamsProvider.sol • ../interfaces/IAssetVotingWeightProvider.sol • ../interface s/IProposalExecutor.sol • ../interfaces/IPopulousProtoGovernance.sol Inheritance PopulousProtoGovernance contract is IPopulousProtoGovernance Usages PopulousProtoGovernance contract has following usages: • SafeMath for uint256 • ECDSA for bytes32 Structs Populo usProtoGovernance contract has following data structures: • Voter – used to store vote result. • Proposal – used to store a proposal info. Enums PopulousProtoGovernance contract has following enums: • ProposalStatus {Initializing, Voting, Validating, Executed} – stores proposal statuses. Events PopulousProtoGovernance contract has following events : • ProposalCreated – emitted when a new proposal is created. • StatusChangeToVoting – emitted when a proposal status changes to Voting. • StatusChangeToValidating – emitted when a proposal status changes to Validating • StatusChangeToExecuted – emitted when a prop osal status changes to Executed • VoteEmitted – emitted on a new vote. • VoteCancelled – emitted when a vote is cancelled. • YesWins – emitted when a proposal wins with “Y es”. • NoWins – emitted when a proposal wins with “No”. • AbstainWins – emitted when a proposa l wins with “Abstain”. Modifiers PopulousProtoGovernance has no custom modifiers. Fields PopulousProtoGovernance contract has following constants and fields: • uint256 public constant COUNT_CHOICES = 2 • uint256 public constant MIN_THRESHOLD = 13000000 ether • uint256 public constant MIN_STATUS_DURATION = 1660; • uint256 public constant MIN_MAXMOVESTOVOTINGALLOWED = 2 • uint256 public constant MAX_MAXMOVESTOVOTINGALLOWED = 6 • IG overnanceParamsProvider private govParamsProvider • Proposal[] private proposals Func tion s PopulousProtoGovernance has following public functions: • Fallback function Description Forbid transferring ETH to the contract. • newProposal Description Registers a n ew proposal Visibility external Input parameters o bytes32 _proposalType o bytes32 _ipfsHash o uint256 _threshold o address _proposalExecutor o uint256 _votingBlocksDuration o uint256 _validatingBlocksDuration o uint256 _maxMovesToVotingAllowed Constraints o A caller sho uld have voting power greater or equal to threshold. o `_ votingBlocksDuration ` and ` _validatingBlocksDuration ` should be at least MIN_STATUS_DURATION o ` _maxMovesToVotingAllowed ` should be between MIN_MAXMOVESTOVOTINGALLOWED and MAX_MAXMOVESTOVOTINGALLOWED Events emit Emits the ProposalCreated event. Output Non e • verifyParamsConsistencyAndSignature Description Verifies the consistency of the action's params and their correct signature • verifyNonce Description Verifies the nonce of a voter on a proposal • va lidateRelayAction Description • submitVoteByVoter Description Function called by a voter to submit his vote directly Visibility external Input parameters o uint256 _proposalId o uint256 _vote o IERC20 _asset Constraints o A proposal should be in the Voting statu s. o Asset weights of an ` _asset ` should be greater than 0. o `_vote` should be 0, 1 or 2. o The voter balance should be greater than 0. Events emit Emits the VoteEmitted event. Also, can emit the StatusChangeToValidating event. Output None • submitVoteByRelayer Description Function called by any address relaying signed vote params from another wallet. Visibility external Input parameters o uint256 _proposalId o uint256 _vote o IERC20 _asset o uint256 _nonce o bytes calldata _signature o bytes32 _paramsHashByVoter Constraint s o Signature and _nonce should be valid. o A proposal should be in the Voting status. o Asset weights of an ` _asset ` should be greater than 0. o `_vote` should be 0, 1 or 2. o The voter balance should be greater than 0. Events emit Emits the VoteEmitted event. Also , can emit the StatusChangeToValidating event. Output None • cancelVoteByVoter Description Revokes a vote in the proposal with ` _proposalId ` Visibility external Input parameters o uint256 _proposalId Constraints o A proposal should be in the Voting status. E vents emit Emits the VoteCancelled event. Output None • cancelVoteByRelayer Description Revokes a vote in the proposal with ` _proposalId `. Visibility external Input parameters o uint256 _proposalId o address _voter o uint256 _nonce o bytes calldata _signature o by tes32 _paramsHashByVoter Constraints o Signature and _nonce should be valid. o A proposal should be in the Voting status. Events emit Emits the VoteCancelled event. Output None • tryToMoveToValidating Description Moves a proposal to the Validating status. Vi sibility external Input parameters o uint256 _proposalId Constraints o A proposal should be in the Voting status. o All the requirements of moving from Voting to Validating status should be met. Events emit Emits the StatusChangeToValidating event. Output None • challengeVoters Description Called during the Validating period in order to cancel invalid votes where the voter was trying a double - voting attack