Dayvidende

QuillAuditsFiles named in the report

Audit · firm’s term: audit report

QuillAudits reviewed TAC2.0 (Dayvidende) on 12 Nov 2024: 8 findings, 0 critical; all marked fixed.

No open critical findings
Open the reportOpen TAC2.0’s security record

Report hosted on quillaudits.com.

Trustblock does not review code.

Findings8

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High002
Medium003
Low003
HighReferral DVE amount in buyTokens() became substantially high than the actual DVE buy amountFixed

When a user buys DVE tokens then level one/two/three referral gets some percentage of DVE tokens. Now the problem is, when combining the level one/two/three referral DVE amount, it became substantially higher than the actual buy amount.Let's see this via example: 1. Suppose there are 100 DVE tokens are for sale and user1 bought all 100 tokens. 2. Level1 referral will get 10% of amount ie `10 DVE` tokens 3. Level1 referrer has 10 Level2 referrals & they get 5% of amount ie 5 \* 10 = `50 DVE` tokens 4. Now, each Level2 referrer has 10 referrals & they get 2.5% of amount ie 2.5 \* 10 \* 10 = `250 DVE` tokens 5. Total referral DVE tokens = 10(Level1) + 50(Level2) + 250(Level3) = 310 DVE tokens, whereas only 100 DVE tokens were sold Impact would be that referral amount will be substantially high than the actual amount ie a large amount of DVE tokens will be vested, which are not present in the contract

HighVesting DVE tokens will also be sold in DVESale:buyTokens() due to use of DVE.balanceOf(address(this))Fixed

Users can buy DVE tokens using buyTokens(), which give some percentage of DVE tokens to the referral. Tokens that referral gets are vested over a period of 1 year.```solidity function buyTokens(address ref, uint256 amount) external whenNotPaused {         require(ref != msg.sender, "Cannot refer yourself");         require(ref != address(0), "Referral have to be entered");         require(amount > 0, "Must purchase a positive number of tokens"); @>      require(amount < DVE.balanceOf(address(this)), "There are not enough tokens left to purchase");         bool paymentSuccessful = BUSD.transferFrom(msg.sender, address(this), amount);         require(paymentSuccessful, "Payment was not successful");         bool success = DVE.transfer(msg.sender, amount);         require(success, "Sending failed");         giveReferrals(ref, amount);         amountPurchsed = amountPurchsed + amount;         emit BuyTokens(msg.sender, amount);     } Now the problem is, tokens that are allocated to referrals will also be sold to new users because buyTokens() uses the `balanceOf(address(this))` while selling the DVE tokens. This doesn't separate/reserves the tokens that are already allocated/vested to the referrals. 1. Suppose there are 100 DVE tokens & user1 bought 50 DVE tokens. 2. His referrals get 5 DVE tokens, vested over 1 year period 3. Now, user2 should only be able to buy 45 DVE tokens but he can buy complete 50 DVE tokens ie including referral's 5 DVE tokens

MediumNo withdraw function for withdrawing DVE tokens from DVESale.solFixed

`DVESale` contract is used for selling DVE tokens using buyTokens(). However there can be situations when some DVE tokens are left `unsold` then there is no withdraw function for owner to withdraw those extra DVE tokens from the contract.Impact would be such that unsold DVE tokens will be `stuck` in the contract

Mediumreferees will receive referral DVE amount instead of 10 in buyTokens()Fixed

When a user buys DVE tokens then referrals receive some percentage of purchased DVE amount. Only first 10 level2 & level3 referrals should receive the referral DVE tokens. But due to wrong position of if-statement(which breaks the loop), 11 referrals recives the DVE token amount instead of 10.```solidity     function giveReferrals(address l1Ref, uint256 amount) internal { ...         address[] memory l2Refs = previousReferrals[l1Ref];         for (uint256 i = 0; i < l2Refs.length; i++) {             address l2Ref = l2Refs[i];             addClaim(l2Ref, l2Amount);             total += l2Amount;             address[] memory l3Refs = previousReferrals[l2Ref];             for (uint256 j = 0; j < l3Refs.length; j++) {                 address l3Ref = l3Refs[j];                 addClaim(l3Ref, l3Amount);                 total += l3Amount;                 // Safety check to prevent gas limit issues @>              if (j >= 10) {                     break;                 }             }             // Safety check to prevent gas limit issues @>          if (i >= 10) {                 break;             }         }     } ``` Due to the `=` sign & nature of array, loop will run form 0 to 11 ie [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

MediumStale price is not checked in DVE:getLatestBnbToUsd()Fixed

AggregatorV3Interface(bnbUsdFeed).latestRoundData() returns a variable `updatedAt`, which is the last timestamp when price was updated. For bnb/usd price oracle, heartbeat is 27s ie after every 27s price of bnb is updated.```solidity   function getLatestBnbToUsd() public view returns (uint256) {         (, int256 price,,,) = AggregatorV3Interface(bnbUsdFeed).latestRoundData();         return uint256(price); // 8 decimals     } ``` If stale price is not checked, code will execute with prices that don’t reflect the current pricing.

Lowdividend mapping is not used in DVESale.solFixed

dividend mapping is not used in DVESale.sol```solidity     mapping(address => uint256) public dividend;

LowDouble check for address(0) & sale in recalculateClaim()Fixed

When recalculateClaim() is called, it checks for address(0) & sale address. But when it calls calculateDividend() internally, it also checks the for address(0) & sale address.```solidity  function recalculateClaim(address who) internal {         // null user doesn't get dividends @>      if (who == address(0) || who == sale) {             return;         } ...         uint256 oldDividend = claim.unclaimed; @>      uint256 newDividend = calculateDividend(who, claim); ...     } ``` ```solidity function calculateDividend(address who, Claim storage claim) internal view returns (uint256 dividend) {         // null and the sale contract don't get dividends @>      if (who == address(0) || who == sale) {             return 0;         } ...     } ```

LowFull DVE tokens can't be sold in DVESale:buyTokens()Fixed

Full DVE tokens can't be sold in DVESale:buyTokens() due to use of `<` instead of `<=````solidity  function buyTokens(address ref, uint256 amount) external whenNotPaused {         require(ref != msg.sender, "Cannot refer yourself");         require(ref != address(0), "Referral have to be entered");         require(amount > 0, "Must purchase a positive number of tokens"); @>      require(amount < DVE.balanceOf(address(this)), "There are not enough tokens left to purchase");         bool paymentSuccessful = BUSD.transferFrom(msg.sender, address(this), amount);         require(paymentSuccessful, "Payment was not successful"); ....     } ```

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (4)

  • ts/DVESale.sol
  • com/parlour-dev/dayvidende-contracts-audit/blob/main/contracts/DVE.sol
  • ts/DVE.sol
  • DVESale.sol

Part of TAC2.0’s security record

TAC2.0
Audits4 audits by 2 firmsLast audit Nov 2024, by QuillAudits.
Critical findingsNo open critical findingsAcross 4 reports.
Open TAC2.0’s security record

Security firm

QuillAudits

350 projects reviewed · 459 reports · latest Apr 2025

See QuillAudits’s audits

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us