@@ -42,7 +42,7 @@ contract ValidatorFactory is ReentrancyGuard {
4242 mapping (address => address ) public validatorToProxy; // user to proxy
4343 mapping (address => bool ) public isValidator;
4444 address [] public validators;
45-
45+
4646 // Custom errors
4747 error SenderNotValidator ();
4848 error InsufficientStakeAmount ();
@@ -71,14 +71,20 @@ contract ValidatorFactory is ReentrancyGuard {
7171 * @dev Stake tokens as a validator. Deploys proxy if not already present.
7272 */
7373 function stake (uint256 amount ) external nonReentrant {
74- require (amount >= minimumStake, "Stake below minimum " );
75- require (! isValidator[msg .sender ], "Already validator " );
76- require (validators.length < maxValidators, "Max validators reached " );
74+ if (amount < minimumStake) {
75+ revert InsufficientStakeAmount ();
76+ }
77+ if (isValidator[msg .sender ]) {
78+ revert AlreadyValidator ();
79+ }
80+ if (validators.length >= maxValidators) {
81+ revert MaxValidatorsReached ();
82+ }
7783
7884 // Compute proxy address
7985 address proxy = computeProxyAddress (msg .sender , amount);
8086 // Pre-fund the proxy
81- require ( stakingToken.transferFrom (msg .sender , proxy, amount), " Transfer failed " );
87+ stakingToken.safeTransferFrom (msg .sender , proxy, amount);
8288
8389 // Deploy proxy with CREATE2
8490 bytes memory data = abi.encodeWithSelector (
@@ -107,19 +113,22 @@ contract ValidatorFactory is ReentrancyGuard {
107113 */
108114 function unstake (uint256 amount ) external nonReentrant onlyValidator {
109115 address proxy = validatorToProxy[msg .sender ];
110- uint256 unstaked = ValidatorLogic (proxy).unstake (amount);
111- require (stakingToken.transfer (msg .sender , unstaked), "Transfer failed " );
112- emit Unstaked (msg .sender , unstaked);
116+ uint256 currentStake = ValidatorLogic (proxy).getStakeAmount ();
113117
114- uint256 remainingStake = ValidatorLogic (proxy).getStakeAmount ();
115- if (remainingStake < minimumStake && remainingStake > 0 ) {
116- // Unstake the residual below minimum
117- uint256 residual = remainingStake;
118- uint256 unstakedResidual = ValidatorLogic (proxy).unstake (residual);
119- require (stakingToken.transfer (msg .sender , unstakedResidual), "Transfer failed " );
120- emit Unstaked (msg .sender , unstakedResidual);
121- remainingStake = 0 ;
118+ if (currentStake < amount) {
119+ revert InsufficientStakeAmount ();
120+ }
121+
122+ if (currentStake - amount < minimumStake) {
123+ amount = currentStake;
124+ }
125+
126+ uint256 unstaked = ValidatorLogic (proxy).unstake (amount);
127+ if (unstaked > 0 ) {
128+ emit Unstaked (msg .sender , unstaked);
122129 }
130+
131+ uint256 remainingStake = ValidatorLogic (proxy).getStakeAmount ();
123132 if (remainingStake == 0 ) {
124133 _removeValidatorFromArray (msg .sender );
125134 isValidator[msg .sender ] = false ;
@@ -228,23 +237,23 @@ contract ValidatorFactory is ReentrancyGuard {
228237
229238 return i;
230239 }
231-
240+
232241 /**
233242 * @dev Get all validators
234243 * @return allValidators Array of all validator addresses
235244 */
236245 function getAllValidators () external view returns (address [] memory ) {
237246 return validators;
238247 }
239-
248+
240249 /**
241250 * @dev Get validator count
242251 * @return count Number of validators
243252 */
244253 function getValidatorCount () external view returns (uint256 ) {
245254 return validators.length ;
246255 }
247-
256+
248257 /**
249258 * @dev Check if address is validator
250259 * @param validator Address to check
@@ -264,7 +273,7 @@ contract ValidatorFactory is ReentrancyGuard {
264273 address proxy = validatorToProxy[validator];
265274 return ValidatorLogic (proxy).getStakeAmount ();
266275 }
267-
276+
268277 /**
269278 * @dev Check if validator can unstake (bonding period expired)
270279 * @param validator Validator address
0 commit comments