Popcorn contest - jasonxiale's results

A multi-chain regenerative yield-optimizing protocol.

General Information

Platform: Code4rena

Start Date: 31/01/2023

Pot Size: $90,500 USDC

Total HM: 47

Participants: 169

Period: 7 days

Judge: LSDan

Total Solo HM: 9

Id: 211

League: ETH

Popcorn

Findings Distribution

Researcher Performance

Rank: 64/169

Findings: 3

Award: $147.60

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: GreedyGoblin

Also found by: 0xNineDec, chaduke, jasonxiale, peakbolt

Labels

bug
2 (Med Risk)
partial-50
sponsor confirmed
duplicate-466

Awards

76.1325 USDC - $76.13

External Links

Lines of code

https://github.com/code-423n4/2023-01-popcorn/blob/d95fc31449c260901811196d617366d6352258cd/src/vault/Vault.sol#L429-L439 https://github.com/code-423n4/2023-01-popcorn/blob/d95fc31449c260901811196d617366d6352258cd/src/vault/Vault.sol#L87

Vulnerability details

Impact

accruedManagementFee calculate managementFee incorrectly

Proof of Concept

Supposed during initialize, fees.management is 0, and feesUpdatedAt is set to block.timestamp. Then after 10 years, the owner calls proposeFees to set management > 0, and then Vault.changeFees is called after Vault.proposedFeeTime + Vault.quitPeriod.

When called Vault.accruedManagementFee to calculate management fee,

function accruedManagementFee() public view returns (uint256) { uint256 managementFee = fees.management; return managementFee > 0 ? managementFee.mulDiv( totalAssets() * (block.timestamp - feesUpdatedAt), SECONDS_PER_YEAR, Math.Rounding.Down ) / 1e18 : 0; }

in the code above, block.timestamp - feesUpdatedAt == 10 years, which I don't think it's correct. And I think feesUpdatedAt should be the block.timestamp when Vault.changeFees is called

Tools Used

Foundry

update Vault.feesUpdatedAt properly

#0 - c4-judge

2023-02-16T08:18:29Z

dmvt marked the issue as duplicate of #93

#1 - c4-sponsor

2023-02-18T12:17:58Z

RedVeil marked the issue as sponsor confirmed

#2 - c4-judge

2023-02-23T00:55:47Z

dmvt marked the issue as partial-50

Findings Information

🌟 Selected for report: gjaldon

Also found by: 0xMirce, Kenshin, Kumpa, chaduke, jasonxiale, joestakey, rvierdiiev

Labels

bug
2 (Med Risk)
partial-50
sponsor confirmed
duplicate-165

Awards

34.6879 USDC - $34.69

External Links

Lines of code

https://github.com/code-423n4/2023-01-popcorn/blob/d95fc31449c260901811196d617366d6352258cd/src/utils/MultiRewardStaking.sol#L171 https://github.com/code-423n4/2023-01-popcorn/blob/d95fc31449c260901811196d617366d6352258cd/src/utils/MultiRewardStaking.sol#L373

Vulnerability details

Impact

When calling MultiRewardStaking.addRewardToken, there is no limit how many tokens can be created, so it's possible that MultiRewardStaking. rewardTokens's length is large than 256. In such case, uint8 in MultiRewardStaking.accrueRewards will be overflow.

modifier accrueRewards(address _caller, address _receiver) { IERC20[] memory _rewardTokens = rewardTokens; for (uint8 i; i < _rewardTokens.length; i++) { IERC20 rewardToken = _rewardTokens[i]; RewardInfo memory rewards = rewardInfos[rewardToken]; if (rewards.rewardsPerSecond > 0) _accrueRewards(rewardToken, _accrueStatic(rewards)); _accrueUser(_receiver, rewardToken); // If a deposit/withdraw operation gets called for another user we should accrue for both of them to avoid potential issues like in the Convex-Vulnerability if (_receiver != _caller) _accrueUser(_caller, rewardToken); } _; }

Same issue might happens in MultiRewardStaking.claimRewards

Proof of Concept

put the code below into MultiRewardStaking.t.sol, and run

function testMultipleRewardsToken() public { MockERC20[257] memory rewardTokenLarge; IERC20[257] memory iRewardTokenLarge; for(uint256 i; i < 257; i++) { rewardTokenLarge[i] = new MockERC20("RewardsTokenLarge", "RTKNL", 18); iRewardTokenLarge[i] = IERC20(address(rewardTokenLarge[i])); } for(uint256 i; i < 257; i++) { _addRewardToken(rewardTokenLarge[i]); } stakingToken.mint(ada, 5 ether); vm.startPrank(ada); stakingToken.approve(address(staking), 5 ether); staking.deposit(1 ether); }

Tools Used

Foundry

diff --git a/src/utils/MultiRewardStaking.sol b/src/utils/MultiRewardStaking.sol index 95ebefd..253d12f 100644 --- a/src/utils/MultiRewardStaking.sol +++ b/src/utils/MultiRewardStaking.sol @@ -168,7 +168,7 @@ contract MultiRewardStaking is ERC4626Upgradeable, OwnedUpgradeable { * @dev A percentage of each reward can be locked in an escrow contract if this was previously configured. */ function claimRewards(address user, IERC20[] memory _rewardTokens) external accrueRewards(msg.sender, user) { - for (uint8 i; i < _rewardTokens.length; i++) { + for (uint i; i < _rewardTokens.length; i++) { uint256 rewardAmount = accruedRewards[user][_rewardTokens[i]]; if (rewardAmount == 0) revert ZeroRewards(_rewardTokens[i]); @@ -370,7 +370,7 @@ contract MultiRewardStaking is ERC4626Upgradeable, OwnedUpgradeable { /// @notice Accrue rewards for up to 2 users for all available reward tokens. modifier accrueRewards(address _caller, address _receiver) { IERC20[] memory _rewardTokens = rewardTokens; - for (uint8 i; i < _rewardTokens.length; i++) { + for (uint i; i < _rewardTokens.length; i++) { IERC20 rewardToken = _rewardTokens[i]; RewardInfo memory rewards = rewardInfos[rewardToken];

#0 - c4-judge

2023-02-16T03:46:04Z

dmvt marked the issue as duplicate of #151

#1 - c4-sponsor

2023-02-18T11:55:30Z

RedVeil marked the issue as sponsor confirmed

#2 - c4-judge

2023-02-23T22:50:08Z

dmvt marked the issue as partial-50

Findings Information

Labels

bug
2 (Med Risk)
satisfactory
sponsor confirmed
edited-by-warden
duplicate-78

Awards

36.7818 USDC - $36.78

External Links

Lines of code

https://github.com/code-423n4/2023-01-popcorn/blob/d95fc31449c260901811196d617366d6352258cd/src/vault/Vault.sol#L88 https://github.com/code-423n4/2023-01-popcorn/blob/d95fc31449c260901811196d617366d6352258cd/src/vault/Vault.sol#L540-L546 https://github.com/code-423n4/2023-01-popcorn/blob/d95fc31449c260901811196d617366d6352258cd/src/vault/Vault.sol#L578

Vulnerability details

Impact

Vault.fees can be overwritten by Vault.changeFees, which will affect the whole reward logic

Proof of Concept

in initialize, fee is set to fees_, if fees_ is not empty(say VaultFees({ deposit: 1e17, withdrawal: 2e17, management: 3e17, performance: 4e17 })), after quitPeriod, any user can calll function changeFees, in such case, proposedFees is empty, so fees will be overwritten to empty The same issue in (Vault.sol#L578)[https://github.com/code-423n4/2023-01-popcorn/blob/d95fc31449c260901811196d617366d6352258cd/src/vault/Vault.sol#L578], proposedAdapter can be address(0)

function setUp() public { vm.label(feeRecipient, "feeRecipient"); vm.label(alice, "alice"); asset = new MockERC20("Mock Token", "TKN", 18); adapter = new MockERC4626(IERC20(address(asset)), "Mock Token Vault", "vwTKN"); address vaultAddress = address(new Vault()); vm.label(vaultAddress, "vault"); vault = Vault(vaultAddress); vault.initialize( IERC20(address(asset)), IERC4626(address(adapter)), VaultFees({ deposit: 1e17, withdrawal: 2e17, management: 3e17, performance: 4e17 }), feeRecipient, address(this) ); } function testChangeFeesNonOwner() public { { (uint256 deposit, uint256 withdrawal, uint256 management, uint256 performance) = vault.fees(); emit log_named_uint("deposit : ", deposit); emit log_named_uint("withdrawal : ", withdrawal); emit log_named_uint("management : ", management); emit log_named_uint("performance: ", performance); } vm.warp(block.timestamp + 3 days); vm.prank(alice); vault.changeFees(); { (uint256 deposit, uint256 withdrawal, uint256 management, uint256 performance) = vault.fees(); emit log_named_uint("deposit : ", deposit); emit log_named_uint("withdrawal : ", withdrawal); emit log_named_uint("management : ", management); emit log_named_uint("performance: ", performance); } }

Tools Used

foundry

add some check

#0 - c4-judge

2023-02-16T08:09:12Z

dmvt marked the issue as duplicate of #78

#1 - c4-sponsor

2023-02-18T12:16:37Z

RedVeil marked the issue as sponsor confirmed

#2 - c4-judge

2023-02-23T00:26:27Z

dmvt marked the issue as satisfactory

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