Badger Citadel contest - hickuphh3's results

Bringing BTC to DeFi

General Information

Platform: Code4rena

Start Date: 04/02/2022

Pot Size: $30,000 USDC

Total HM: 3

Participants: 37

Period: 3 days

Judge: leastwood

Id: 84

League: ETH

BadgerDAO

Findings Distribution

Researcher Performance

Rank: 13/37

Findings: 1

Award: $625.19

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: WatchPug

Also found by: 0x1f8b, Czar102, cccz, cmichel, gellej, harleythedog, hickuphh3, hyh, pauliax, sirhashalot

Labels

bug
duplicate
2 (Med Risk)

Awards

625.1882 USDC - $625.19

External Links

Lines of code

https://github.com/code-423n4/2022-02-badger-citadel/blob/main/contracts/TokenSaleUpgradeable.sol#L251-L265

Vulnerability details

Impact

Sale participants will only be able to claim their CTDL tokens once the sale is finalized. However, there is no guarantee that it ever will be, because:

  • Sale finalisation can only be performed by the owner
  • The owner is able to change the sale parameters (sale start time, duration, tokenInLimit) anytime before the finalization of the sale, such that saleEnded() will always be false. Eg. setting long sale duration or a very distant future sale start time.
  • There is no guarantee that the contract will have sufficient CTDL for the finalization of the sale.
function finalize() external onlyOwner {
  require(!finalized, "TokenSale: already finalized");
  require(saleEnded(), "TokenSale: not finished");
  require(
      tokenOut.balanceOf(address(this)) >= totalTokenOutBought,
      "TokenSale: not enough balance"
  );

  finalized = true;

	emit Finalized();
}

The core issue is that users’ funds are immediately accessible by the sale recipient at the moment of purchase while they have to wait for the sale to be complete before receiving their tokens. From a sale participant’s POV, he will feel that the organization can at anytime choose not to fulfil their end of the sale (ie. get rugged).

  1. Only allow critical sale parameters (especially start time) to be changed before the start of the token sale.
// have following require statement in setSaleStart()
// possibly in setSaleDuration() and setTokenInLimit() as well
// but it might be intended to have the sale extended / ended prematurely
require(block.timestamp < saleStart, "TokenSale: sale has already begun");
  1. Have a sanity limit on the sale duration
uint64 internal LIMIT = 1 year;
// in setSaleDuration()
require(_saleDuration < LIMIT, "TokenSale: exceed limit");
  1. Allow sale finalisation to be permissionless; remove the onlyOwner restriction.

Scenario 1: CTDL tokens can be transferred before sale commences

While token claiming can still be done after the sale, a check can be added to ensure the CTDL balance of the contract is at least the totalTokenOutBought in the purchase.

function buy() {
	...
totalTokenOutBought += tokenOutAmount_;
require(tokenOut.balanceOf(address(this)) >= totalTokenOutBought, "insufficient balance");
	...
}

Scenario 2: CTDL tokens can only be transferred after sale ends

In this less ideal scenario, have the funds transferred to an escrow contract. Should users not receive CTDL tokens after a certain time, users are entitled to reclaim their funds.

#0 - GalloDaSballo

2022-02-14T13:07:26Z

This ultimately is a DOS / Hostage of funds that can happen. I believe this is simply because of the permission call to finalize Arguably that means this is admin privilege so I'd downgrade to medium, but fully acknowledge the finding

#1 - 0xleastwood

2022-03-14T10:57:20Z

Duplicate of #50

#2 - 0xleastwood

2022-03-16T12:45:50Z

Duplicate of #61

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter