Skip to content

Commit cf3ce62

Browse files
authored
Merge pull request #824 from neutron-org/fix/cron
fix: off-by-one error in cron periods #ntrn-451
2 parents 363ec32 + 11d4449 commit cf3ce62

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

x/cron/keeper/keeper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ func (k *Keeper) scheduleExists(ctx sdk.Context, name string) bool {
231231
}
232232

233233
func (k *Keeper) intervalPassed(ctx sdk.Context, schedule types.Schedule) bool {
234-
return uint64(ctx.BlockHeight()) > (schedule.LastExecuteHeight + schedule.Period) //nolint:gosec
234+
return uint64(ctx.BlockHeight()) >= (schedule.LastExecuteHeight + schedule.Period) //nolint:gosec
235235
}
236236

237237
func (k *Keeper) changeTotalCount(ctx sdk.Context, incrementAmount int32) {

x/cron/keeper/keeper_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,93 @@ func TestKeeperExecuteReadySchedules(t *testing.T) {
203203
require.Equal(t, uint64(4), unready2.LastExecuteHeight)
204204
require.Equal(t, uint64(6), ready3.LastExecuteHeight)
205205
require.Equal(t, uint64(7), ready4.LastExecuteHeight)
206+
207+
// reset context to 0 block
208+
ctx = ctx.WithBlockHeight(0)
209+
everyTimeSchedule := types.Schedule{
210+
Name: "every_block",
211+
Period: 1,
212+
Msgs: []types.MsgExecuteContract{
213+
{
214+
Contract: "every_block",
215+
Msg: "every_block",
216+
},
217+
},
218+
LastExecuteHeight: 0,
219+
ExecutionStage: types.ExecutionStage_EXECUTION_STAGE_BEGIN_BLOCKER,
220+
}
221+
err = k.AddSchedule(ctx, everyTimeSchedule.Name, everyTimeSchedule.Period, everyTimeSchedule.Msgs, everyTimeSchedule.ExecutionStage)
222+
223+
s, _ := k.GetSchedule(ctx, "every_block")
224+
require.Equal(t, s.LastExecuteHeight, uint64(0))
225+
require.NoError(t, err)
226+
227+
// expect it to not executed right away
228+
229+
k.ExecuteReadySchedules(ctx, types.ExecutionStage_EXECUTION_STAGE_BEGIN_BLOCKER)
230+
// LastExecuteHeight should still be at 0
231+
s, _ = k.GetSchedule(ctx, "every_block")
232+
require.Equal(t, s.LastExecuteHeight, uint64(0))
233+
234+
ctx = ctx.WithBlockHeight(1)
235+
// expect it to be executed again
236+
wasmMsgServer.EXPECT().ExecuteContract(gomock.Any(), &wasmtypes.MsgExecuteContract{
237+
Sender: testutil.TestOwnerAddress,
238+
Contract: "every_block",
239+
Msg: []byte("every_block"),
240+
Funds: sdk.NewCoins(),
241+
}).Return(&wasmtypes.MsgExecuteContractResponse{}, nil)
242+
k.ExecuteReadySchedules(ctx, types.ExecutionStage_EXECUTION_STAGE_BEGIN_BLOCKER)
243+
// last execute height changed to 1
244+
s, _ = k.GetSchedule(ctx, "every_block")
245+
require.Equal(t, s.LastExecuteHeight, uint64(1))
246+
247+
k.RemoveSchedule(ctx, "every_block")
248+
249+
// test schedule with period 2
250+
ctx = ctx.WithBlockHeight(0)
251+
onceTwoBlocksSchedule := types.Schedule{
252+
Name: "once_in_two",
253+
Period: 2,
254+
Msgs: []types.MsgExecuteContract{
255+
{
256+
Contract: "once_in_two",
257+
Msg: "once_in_two",
258+
},
259+
},
260+
LastExecuteHeight: 0,
261+
ExecutionStage: types.ExecutionStage_EXECUTION_STAGE_BEGIN_BLOCKER,
262+
}
263+
err = k.AddSchedule(ctx, onceTwoBlocksSchedule.Name, onceTwoBlocksSchedule.Period, onceTwoBlocksSchedule.Msgs, onceTwoBlocksSchedule.ExecutionStage)
264+
265+
s, _ = k.GetSchedule(ctx, "once_in_two")
266+
require.Equal(t, s.LastExecuteHeight, uint64(0))
267+
require.NoError(t, err)
268+
269+
// expect it to not executed on 0 and 1 blocks
270+
k.ExecuteReadySchedules(ctx, types.ExecutionStage_EXECUTION_STAGE_BEGIN_BLOCKER)
271+
// LastExecuteHeight should still be at 0
272+
s, _ = k.GetSchedule(ctx, "once_in_two")
273+
require.Equal(t, s.LastExecuteHeight, uint64(0))
274+
275+
ctx = ctx.WithBlockHeight(1)
276+
k.ExecuteReadySchedules(ctx, types.ExecutionStage_EXECUTION_STAGE_BEGIN_BLOCKER)
277+
s, _ = k.GetSchedule(ctx, "once_in_two")
278+
require.Equal(t, s.LastExecuteHeight, uint64(0))
279+
280+
// expect it to be executed on 2 block
281+
ctx = ctx.WithBlockHeight(2)
282+
// expect it to be executed again
283+
wasmMsgServer.EXPECT().ExecuteContract(gomock.Any(), &wasmtypes.MsgExecuteContract{
284+
Sender: testutil.TestOwnerAddress,
285+
Contract: "once_in_two",
286+
Msg: []byte("once_in_two"),
287+
Funds: sdk.NewCoins(),
288+
}).Return(&wasmtypes.MsgExecuteContractResponse{}, nil)
289+
k.ExecuteReadySchedules(ctx, types.ExecutionStage_EXECUTION_STAGE_BEGIN_BLOCKER)
290+
// last execute height changed to 2
291+
s, _ = k.GetSchedule(ctx, "once_in_two")
292+
require.Equal(t, s.LastExecuteHeight, uint64(2))
206293
}
207294

208295
func TestAddSchedule(t *testing.T) {

0 commit comments

Comments
 (0)