Assessment reports>Palmy Finance>Medium findings>Collected fees cannot be claimed after withdrawing the locked amount
Category: Coding Mistakes

Collected fees cannot be claimed after withdrawing the locked amount

Medium Severity
Medium Impact
Medium Likelihood

Description

The collected fees are distributed in the FeeDistributor and Voter contracts. They use ownerToId of the VotingEscrow function to process claims for the collected fees:

// FeeDistributor:
function claim() external returns (uint256) {
	_checkpointToken();
	address _for = msg.sender;
	uint256 _lockerId = IVotingEscrow(votingEscrow).ownerToId(_for);
	require(_lockerId != 0, "No lock associated with address");
	// ...
}

// Voter:
function claim() external returns (uint256[] memory) {
	address _owner = msg.sender;
	uint256 _lockerId = Ve(_ve).ownerToId(_owner);
	require(_lockerId != 0, "No lock associated with address");
	// ...
}

However, when the locked asset is withdrawn from the locker, the ownerToId variable of the address is cleared:

// VotingEscrow:
function withdraw() external nonreentrant {
	// ...
	_removeLockerId(_lockerId);
	// ...
}

function _removeLockerId(uint256 _lockerId) internal {
	// ...
	_removeLockerIdFrom(msg.sender, _lockerId);
}

function _removeLockerIdFrom(address _from, uint256 _lockerId) internal {
	// ...
	idToOwner[_lockerId] = address(0);
	ownerToId[_from] = 0;
}

Impact

After a user withdraws their asset from the locker, they cannot claim the collected fees for the locker.

Recommendations

Consider refactoring the contracts not to depend on ownerToId after the first vote, such as saving the list of lockers of a user in the FeeDistributor and Voter contracts.

Remediation

This issue has been acknowledged by Familia Labs Ltd.. Familia Labs Ltd. stated they plan to document this behavior and encourage users to claim the collected fees before withdrawing assets from the locker in their UI.

Zellic © 2025Back to top ↑