The current implementation requires the rewarder (usually the platform) to transfer the rewards (XDEFI tokens) to the contract and calls updateDistribution() to increase _pointsPerUnit, which will distribute the newly added rewards to all existing users according to the uints.
However, every unlock() transaction will call the internal function _updateXDEFIBalance(), which will then update the distributableXDEFI.
Therefore, when a unlock() transaction happened in between the transfer and the updateDistribution() transaction, the newly added rewards will not be recognized.
Actually, there is no way to get back these reward tokens. These tokens are frozen in the contract.
This can happen quite likely if the network is congested.
PoC
The rewarder transferred 1M XDEFI to the XDEFIDistribution contract;
A unlock() transaction by a regular user;
The rewarder calls updateDistribution().
Expected Results: 1M XDEFI get distributed to the users by increasing the _pointsPerUnit.
Actual Results: _pointsPerUnit remain unchanged. The 1M XDEFI sent by the rewarder in step 1 is now frozen in the contract.
Recommendation
Consider changing updateDistribution() to addRewards(uint amount), and use transferFrom() to pull tokens from the caller.
Handle
WatchPug
Vulnerability details
The current implementation requires the rewarder (usually the platform) to transfer the rewards (XDEFI tokens) to the contract and calls
updateDistribution()
to increase_pointsPerUnit
, which will distribute the newly added rewards to all existing users according to theuints
.https://github.com/XDeFi-tech/xdefi-distribution/blob/3856a42df295183b40c6eee89307308f196612fe/contracts/XDEFIDistribution.sol#L332
However, every
unlock()
transaction will call the internal function_updateXDEFIBalance()
, which will then update thedistributableXDEFI
.Therefore, when a
unlock()
transaction happened in between the transfer and theupdateDistribution()
transaction, the newly added rewards will not be recognized.Actually, there is no way to get back these reward tokens. These tokens are frozen in the contract.
This can happen quite likely if the network is congested.
PoC
1M XDEFI
to theXDEFIDistribution
contract;unlock()
transaction by a regular user;updateDistribution()
.Expected Results:
1M XDEFI
get distributed to the users by increasing the_pointsPerUnit
.Actual Results:
_pointsPerUnit
remain unchanged. The1M XDEFI
sent by the rewarder in step 1 is now frozen in the contract.Recommendation
Consider changing
updateDistribution()
toaddRewards(uint amount)
, and usetransferFrom()
to pull tokens from the caller.