Summary
Players can generate free troops in public matches by sending multiple fractional attack intents in the same server turn.
Steps to reproduce
- Join a public match and wait until spawn immunity ends.
- Choose a non-adjacent opponent and obtain their simulation Player.id().
- Send this WebSocket intent 10 times in a burst before the next server turn:
{
"type": "intent",
"intent": {
"type": "attack",
"targetID": "TARGET_PLAYER_ID",
"troops": 0.999
}
}
- Because the target is non-adjacent, the attack has no reachable border and automatically retreats.
What happens
Each 0.999 request deducts 0 troops because troop removal is floored. The attacks then combine into a single 9.99-troop attack. On
retreat, the game refunds floor(9.99) = 9 troops.
Observed result:
Before: 25000 troops
After attack creation: 25000 troops
Combined attack: 9.99 troops
After auto-retreat: 25009 troops
Net gain: +9 free troops
The server accepts and queues all 10 intents, and identical client simulations produce the same game hash, so this affects the
synchronized public-match state.
At the current rate limits, this can generate approximately 135 free troops per minute when repeated in bursts.
cause
AttackIntentSchema accepts fractional troop amounts. AttackExecution floors each troop deduction individually, combines attacks afterward,
and then floors the combined amount again during retreat.
The attack amount should be normalized to the amount actually deducted, or multiple attacks should be aggregated before resource
deduction.
Summary
Players can generate free troops in public matches by sending multiple fractional attack intents in the same server turn.
Steps to reproduce
{
"type": "intent",
"intent": {
"type": "attack",
"targetID": "TARGET_PLAYER_ID",
"troops": 0.999
}
}
What happens
Each 0.999 request deducts 0 troops because troop removal is floored. The attacks then combine into a single 9.99-troop attack. On
retreat, the game refunds floor(9.99) = 9 troops.
Observed result:
Before: 25000 troops
After attack creation: 25000 troops
Combined attack: 9.99 troops
After auto-retreat: 25009 troops
Net gain: +9 free troops
The server accepts and queues all 10 intents, and identical client simulations produce the same game hash, so this affects the
synchronized public-match state.
At the current rate limits, this can generate approximately 135 free troops per minute when repeated in bursts.
cause
AttackIntentSchema accepts fractional troop amounts. AttackExecution floors each troop deduction individually, combines attacks afterward,
and then floors the combined amount again during retreat.
The attack amount should be normalized to the amount actually deducted, or multiple attacks should be aggregated before resource
deduction.