# v2.4.0 Release Note ## Summary v2.4.0 is a **mandatory** release. It activates the **Yap hardfork**, which brings the Pectra EVM upgrade (IIP-60) and the candidate exit queue mechanism to IoTeX. ## Changes ### Feat: Pectra EVM Upgrade (IIP-60) Implements four EIPs from the Ethereum Pectra upgrade. All features are activated at `yapHeight`. #### EIP-7702: Set EOA Account Code Introduces transaction type `0x04`, allowing an EOA to temporarily delegate its code execution to a smart contract by signing authorization tuples. Each authorization costs 12,500 gas; creating a new delegated account costs 25,000 gas. Delegated accounts are identified by the prefix `0xef0100 || address`. An abuse-prevention blacklist is applied on top of the standard Ethereum behavior. #### EIP-7623: Increase Calldata Cost Raises the cost floor for data-heavy transactions to reduce the maximum possible block size. IoTeX sets `TX_COST_FLOOR_PER_TOKEN = 250` instead of Ethereum's value of 40, reflecting IoTeX's existing calldata baseline of 100 gas/byte versus Ethereum's 16 gas/byte, so that the relative cost increase is proportional. #### EIP-2935: Historical Block Hashes from State Stores the most recent 8,191 block hashes in a system contract at `0x0000F90827F1C53a10cb7A02335B175320002935`, extending hash accessibility beyond the standard 256-block EVM window. Useful for rollups and cross-chain applications that need to reference older block hashes. #### EIP-2537: BLS12-381 Precompiles Adds seven precompile operations at addresses `0x0b`–`0x11` for BLS12-381 curve operations, enabling efficient on-chain BLS signature verification with 120+ bits of security. Primarily benefits bridges and cross-chain protocols. --- ### Feat: Candidate Exit Queue Replaces the previous immediate-deactivation model with a queue-based mechanism that enforces a notice period before a candidate can fully exit. The change is designed to give the network visibility into upcoming validator exits and prevent sudden stake withdrawals. **Three-stage lifecycle:** 1. **Request** — The candidate owner calls `CandidateDeactivate(OpRequest)`. The self-stake bucket is locked (cannot be unstaked) and `DeactivatedAt` is set to a sentinel value indicating the exit has been requested. 2. **Schedule** — At each epoch boundary, the protocol automatically scans for pending requests. At most one candidate is admitted per `ExitAdmissionInterval` epochs (default: 24 epochs). When admitted, the protocol generates a system `ScheduleCandidateDeactivation` action and sets `DeactivatedAt` to a specific future block height (`currentHeight + ExitAdmissionInterval × blocksPerEpoch`). 3. **Confirm** — Once `currentHeight >= DeactivatedAt`, the candidate owner calls `CandidateDeactivate(OpConfirm)`. The self-stake is cleared (set to 0), the self-stake bucket index is removed from the candidate record, and the candidate is fully deactivated. The former self-stake bucket reverts to a regular vote bucket. **Key constraints:** - The self-stake bucket cannot be unstaked between request and confirmation. - Only one candidate per `ExitAdmissionInterval` epochs is admitted into the queue, preventing a rush of simultaneous exits. - The request cannot be cancelled once submitted. - `ScheduleCandidateDeactivation` is a zero-gas system action, not callable by users. --- ### Fix - Fixed `CandidateDeactivateOpConfirm` swallowing errors due to `:=` shadowing - Fixed `GetStorageRoot` polluting contract cache - Fixed contract staking index checking - Fixed candidate BLS public key update by operator - Fixed `CandsMap` not saved during full sync - Fixed WebSocket double-close ## Upgrade Priority v2.4.0 is a **mandatory** release for all node types. | Node type | Action | | ---------- | ------------- | | Delegate | **Mandatory** | | Fullnode | **Mandatory** | | API node | **Mandatory** | ## Commits https://github.com/iotexproject/iotex-core/compare/v2.3.8...v2.4.0