Problem
The contract admin can set the upgrade timelock to zero and execute a new
WASM implementation immediately, defeating the purpose of the timelock
safeguard entirely.
Severity: High
Location: contracts/batch-vesting/src/lib.rs:774-782,1243-1277
Description
set_config writes any supplied Config, including upgrade_timelock,
directly to storage via set_config_internal with no minimum-value check.
propose_upgrade computes execute_at = timestamp() + config.upgrade_timelock,
and execute_upgrade only rejects execution if timestamp() < execute_at.
With upgrade_timelock == 0, execute_at equals the proposal timestamp, so
that check never triggers — the same admin can propose and execute a new
WASM hash in immediate succession, with no window for anyone to react to a
compromised or malicious admin.
Steps to Reproduce
- As the current admin, call
set_config with upgrade_timelock: 0.
- Call
propose_upgrade with an arbitrary replacement WASM hash.
- Call
execute_upgrade — it succeeds immediately since
timestamp() < execute_at is false when they're equal.
Expected Behavior
Every upgrade should retain a non-bypassable minimum review delay,
regardless of what the admin sets in configuration.
Suggested Fix Approach
Enforce a hard-coded minimum upgrade_timelock in set_config (reject
values below it), or make timelock reductions themselves subject to the
existing timelock delay before taking effect.
Acceptance Criteria
Problem
The contract admin can set the upgrade timelock to zero and execute a new
WASM implementation immediately, defeating the purpose of the timelock
safeguard entirely.
Severity: High
Location:
contracts/batch-vesting/src/lib.rs:774-782,1243-1277Description
set_configwrites any suppliedConfig, includingupgrade_timelock,directly to storage via
set_config_internalwith no minimum-value check.propose_upgradecomputesexecute_at = timestamp() + config.upgrade_timelock,and
execute_upgradeonly rejects execution iftimestamp() < execute_at.With
upgrade_timelock == 0,execute_atequals the proposal timestamp, sothat check never triggers — the same admin can propose and execute a new
WASM hash in immediate succession, with no window for anyone to react to a
compromised or malicious admin.
Steps to Reproduce
set_configwithupgrade_timelock: 0.propose_upgradewith an arbitrary replacement WASM hash.execute_upgrade— it succeeds immediately sincetimestamp() < execute_atis false when they're equal.Expected Behavior
Every upgrade should retain a non-bypassable minimum review delay,
regardless of what the admin sets in configuration.
Suggested Fix Approach
Enforce a hard-coded minimum
upgrade_timelockinset_config(rejectvalues below it), or make timelock reductions themselves subject to the
existing timelock delay before taking effect.
Acceptance Criteria
set_configrejects (or the contract otherwise prevents) aneffective upgrade delay below a defined minimum
execute_upgradecannot succeed in the same or aninsufficient interval after
propose_upgraderegardless ofupgrade_timelockvalue supplied