Fewer tokens sent than required in migrate_staking
Description
The migrate_staking
function distributes tokens to the new staking contract so that the new contract has enough funds. It does this by calculating how many funds have already been distributed, and then, subtracting that from the total amount of funds, the remaining amount is sent to the new contract.
However, it assumes all distribution schedules have had some bond in them and consequently some reward distributed; if a distribution schedule had no bond, then it would not have distributed any rewards, and thus more funds could be retained.
pub fn migrate_staking(
deps: DepsMut,
env: Env,
info: MessageInfo,
new_staking_contract: String,
) -> StdResult<Response> {
...
let mut distributed_amount = Uint128::zero();
for s in config.distribution_schedule.iter_mut() {
if s.1 < block_time {
// all distributed
distributed_amount += s.2;
} else {
// partially distributed slot
let whole_time = s.1 - s.0;
let distribution_amount_per_second: Decimal = Decimal::from_ratio(s.2, whole_time);
let passed_time = block_time - s.0;
let distributed_amount_on_slot =
distribution_amount_per_second * Uint128::from(passed_time as u128);
distributed_amount += distributed_amount_on_slot;
// modify distribution slot
s.1 = block_time;
s.2 = distributed_amount_on_slot;
}
}
...
let remaining_anc = total_distribution_amount.checked_sub(distributed_amount)?;
...
}
Impact
Fewer funds than expected would be sent to the new staking contract, resulting in a nonzero balance of dojo_token
s in the old staking contract.
Recommendations
Ensure there is always some bond when deploying a schedule, or account for the cumulative sum of undistributed rewards when total_bond_amount
is zero in compute_reward
.
Remediation
Dojoswap Labs, PTE provided the following response:
Noted on this. Currently, all staking contracts do indeed have bonds resulting in distribution.