Platform: Code4rena
Start Date: 13/02/2024
Pot Size: $24,500 USDC
Total HM: 5
Participants: 84
Period: 6 days
Judge: 0xA5DF
Id: 331
League: ETH
Rank: 56/84
Findings: 1
Award: $25.73
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: nuthan2x
Also found by: 0x0bserver, AM, CaeraDenoir, DanielArmstrong, JrNet, Kirkeelee, KmanOfficial, Krace, Limbooo, Meera, SovaSlava, SpicyMeatball, TheSavageTeddy, agadzhalov, aslanbek, atoko, csanuragjain, d3e4, imare, jesjupyter, juancito, kartik_giri_47538, kutugu, max10afternoon, offside0011, pkqs90, turvy_fuzz, xchen1130, zhaojohnson, ziyou-
25.7286 USDC - $25.73
https://github.com/code-423n4/2024-02-althea-liquid-infrastructure/blob/bd6ee47162368e1999a0a5b8b17b701347cf9a7d/liquid-infrastructure/contracts/LiquidInfrastructureERC20.sol#L441-L445 https://github.com/code-423n4/2024-02-althea-liquid-infrastructure/blob/bd6ee47162368e1999a0a5b8b17b701347cf9a7d/liquid-infrastructure/contracts/LiquidInfrastructureERC20.sol#L257-L281 https://github.com/code-423n4/2024-02-althea-liquid-infrastructure/blob/bd6ee47162368e1999a0a5b8b17b701347cf9a7d/liquid-infrastructure/contracts/LiquidInfrastructureERC20.sol#L198-L237
The inconsistency of ‘distributableERC20s’ within the ‘distribute’ function can occur when the ‘setDistributableERC20s’ function modifies the parameter ‘distributableERC20s’. This inconsistency may lead to malicious impacts, as the ‘distributableERC20s’ within the ‘_beginDistribution’ function and the ‘distributableERC20s’ within the ‘distribute’ function may differ.
function setDistributableERC20s( address[] memory _distributableERC20s ) public onlyOwner {
@ distributableERC20s = _distributableERC20s; } https://github.com/code-423n4/2024-02-althea-liquid-infrastructure/blob/bd6ee47162368e1999a0a5b8b17b701347cf9a7d/liquid-infrastructure/contracts/LiquidInfrastructureERC20.sol#L441-L445
function _beginDistribution() internal { require( !LockedForDistribution, "cannot begin distribution when already locked" ); LockedForDistribution = true; // clear the previous entitlements, if any if (erc20EntitlementPerUnit.length > 0) { delete erc20EntitlementPerUnit; } // Calculate the entitlement per token held uint256 supply = this.totalSupply(); for (uint i = 0; i < distributableERC20s.length; i++) {
@ uint256 balance = IERC20(distributableERC20s[i]).balanceOf( address(this) ); uint256 entitlement = balance / supply; erc20EntitlementPerUnit.push(entitlement); }
nextDistributionRecipient = 0; emit DistributionStarted(); }
function distribute(uint256 numDistributions) public nonReentrant { require(numDistributions > 0, "must process at least 1 distribution"); if (!LockedForDistribution) { require( _isPastMinDistributionPeriod(), "MinDistributionPeriod not met" ); _beginDistribution(); } uint256 limit = Math.min( nextDistributionRecipient + numDistributions, holders.length ); uint i; for (i = nextDistributionRecipient; i < limit; i++) { address recipient = holders[i]; if (isApprovedHolder(recipient)) { uint256[] memory receipts = new uint256[]( distributableERC20s.length ); for (uint j = 0; j < distributableERC20s.length; j++) {
@ IERC20 toDistribute = IERC20(distributableERC20s[j]); uint256 entitlement = erc20EntitlementPerUnit[j] * this.balanceOf(recipient); if (toDistribute.transfer(recipient, entitlement)) { receipts[j] = entitlement; } }
emit Distribution(recipient, distributableERC20s, receipts); } } nextDistributionRecipient = i; if (nextDistributionRecipient == holders.length) { _endDistribution(); } }
vs
It is recommended to add a check to determine whether the ‘distribute’ function is currently being executed.
Other
#0 - c4-pre-sort
2024-02-20T04:22:20Z
0xRobocop marked the issue as duplicate of #151
#1 - c4-pre-sort
2024-02-20T04:38:13Z
0xRobocop marked the issue as duplicate of #260
#2 - c4-judge
2024-03-04T15:07:18Z
0xA5DF marked the issue as satisfactory
#3 - c4-judge
2024-03-08T15:13:03Z
0xA5DF changed the severity to 3 (High Risk)
#4 - c4-judge
2024-03-08T15:26:19Z
0xA5DF changed the severity to 2 (Med Risk)