Misleading MoveStake event when moving stake from UNDELEGATED to UNDELEGATED
Although moving stake between the same status (UNDELEGATED <=> UNDELEGATED) should be a no-op, calls to `moveStake` succeed even for invalid `amount` and nonsensical `poolId`. The resulting `MoveStake` event can log garbage, potentially confusing those observing events.\\nWhen moving between `UNDELEGATED` and `UNDELEGATED`, each check and function call results in a no-op, save the final event:\\nNeither `from` nor `to` are `StakeStatus.DELEGATED`, so these checks are passed:\\n```\\nif (from.status == IStructs.StakeStatus.DELEGATED) {\\n    \\_undelegateStake(\\n        from.poolId,\\n        staker,\\n        amount\\n    );\\n}\\n  \\nif (to.status == IStructs.StakeStatus.DELEGATED) {\\n    \\_delegateStake(\\n        to.poolId,\\n        staker,\\n        amount\\n    );\\n}\\n```\\n\\nThe primary state changing function, `_moveStake`, immediately returns because the `from` and `to` balance pointers are equivalent:\\n```\\nif (\\_arePointersEqual(fromPtr, toPtr)) {\\n    return;\\n}\\n```\\n\\nFinally, the `MoveStake` event is invoked, which can log completely invalid values for `amount`, `from.poolId`, and to.poolId:\\n```\\nemit MoveStake(\\n    staker,\\n    amount,\\n    uint8(from.status),\\n    from.poolId,\\n    uint8(to.status),\\n    to.poolId\\n);\\n```\\n
If `amount` is 0 or if moving between `UNDELEGATED` and `UNDELEGATED`, this function should no-op or revert. An explicit check for this case should be made near the start of the function.
```\\nif (from.status == IStructs.StakeStatus.DELEGATED) {\\n    \\_undelegateStake(\\n        from.poolId,\\n        staker,\\n        amount\\n    );\\n}\\n  \\nif (to.status == IStructs.StakeStatus.DELEGATED) {\\n    \\_delegateStake(\\n        to.poolId,\\n        staker,\\n        amount\\n    );\\n}\\n```\\n