Contract fails to deliver promised returns, but doesn't lose value
Description
Brief/Intro
The setMigrationPermit function enforces that the _migrator must currently hold MIGRATOR_ROLE for both granting and revoking permissions.
As a result, if a migrator’s role is revoked, users are unable to revoke previously granted migration permissions, since any attempt to call:
setMigrationPermit(migrator,false)
will revert.
This creates a scenario where user approvals become non-revocable, leading to a loss of control over previously granted permissions.
Vulnerability Details
This check applies universally, regardless of whether the user is:
granting permission (true), or
revoking permission (false)
Thus, revocation is blocked when the migrator does not currently hold the role.
Additionally, migration permissions are not cleared after migration, meaning approvals persist even after a user’s positions have already been migrated. Combined with the inability to revoke permissions when the role is revoked, this leads to long-lived and user-uncontrollable approvals.
Impact Details
Users cannot revoke previously granted migration permissions once a migrator loses its role
Migration permissions may persist indefinitely, including after migration is completed
Users lose the ability to manage or invalidate their approvals
If the same migrator address later regains MIGRATOR_ROLE, previously granted permissions may still be active without any opportunity for the user to revoke them beforehand
This results in persistent, user-uncontrollable approvals, which can lead to unexpected migration behavior in the future.