Releases: casper-network/casper-node
v2.2.0
Casper v2.2.0 Release Notes
Summary
This Minor release 2.2.0 adds two new chainspec settings to address the validator proposals CVV006 and CVV008, both of which were voted on and passed through community governance.
Specifically, a new chainspec setting minimum_delegation_rate is introduced to fulfill the requirement specified in CVV006, and a new chainspec setting reward_handling is added to fulfill the requirements of CVV008.
We have added various new types to the casper-types crate in order to support these new features for new networks as well.
This release also includes a new bug fix introduced in Casper v2.0.0, which affected the genesis process of the calculation of total supply.
Lastly, changes specific to the Casper Mainnet are discussed in a dedicated section below.
Rewards Handling
One of the requirements of proposal CVV008 was to transfer a percentage of the newly minted token rewards to a purse.
The minor release 2.2.0 extends the core config section of the chainspec with an additional setting named rewards_handling. Currently, a network can be configured to be one of two settings.
Rewards Handling: Standard
This setting preserves the behavior of the pre-v2.2.0 rewards distribution. An example configuration is
rewards_handling = { type = 'standard' }Rewards Handling: Sustain
This setting for rewards handling has been introduced in the release to support the sustain purse
requirement as specified in validator proposal CVV008. When a network is configured to run in sustain
mode, a certain ratio of the newly minted reward token is transferred to a purse. An example setting
as defined in a chainspec.toml file is:
rewards_handling = { type = 'sustain', ratio = [2,8], purse_address = "uref-a0e6202f24f9fb165711ebe5ea28518b5549cfc8f9d2ad1444b40b13d2474c05-007" }The first field type defines which setting the network will run, in the above example it is sustain.
The second field ratio defines the ratio of newly minted tokens that is transferred to the sustain purse. As the ratio is inherently a percentage, any ratio where the numerator is strictly
greater than the denominator is invalid. Attempting to run a node with such a ratio will return an error.
The third field purse_address specifies the purse that receives the transferred tokens, called the sustain purse. This purse must be a pre-existing purse. The sustain purse is a regular purse, this means that unlike a staking purse, where the token is illiquid, the tokens in a sustain purse is liquid and can be transferred out.
New Global State Entries
As both the ratio and the sustain purse may change from upgrade to upgrade, it becomes necessary to record both the ratio and sustain purse to global state for any historical queries. In order to support this, we have expanded the Key space within global state to include a new stable address variant RewardsHandling. At the time of upgrade, the ratio expressed as a u64 is serialized and written to a map in global state under this new Key variant. When a network is configured to run with sustain, the sustain purse is added to the Mint system contract's named keys under the sustain_purse name. Additionally, the rewards handling setting can be toggled, this means any network that switches from one modality to the other can switch back in the following upgrade.
For pre-existing networks like the Casper Mainnet or Testnet, the sustain handling can be turned on only by staging a protocol upgrade with a chainspec that has the sustain setting with the desired ratio and purse_address parameters.
New networks that wish to set rewards_handling to sustain at genesis, can set up their chainspec as explained above. However, since the sustain purse has to be a known purse, and no purse can be known before the genesis process, the purse_address is ignored at genesis. Instead, for new networks, the accounts.toml file must contain a single entry of
[accounts.sustain]
public_key = "013e3bbc876951c66c6f41956d3c7bde9291f529954fc9f3b2e6cca0ee0335bd1f"This binds the main purse of the account linked by the public key as specified in the accounts.toml to be the sustain purse for the network.
Minimum Delegation Rate
The v2.2.0 release extends the core section of the chainspec to include a new setting minimum_delegation_rate which represents the minimum delegation rate any validator can set on that given network. This fulfills the requirements voted on by the community in CVV006.
For new networks, minimum_delegation_rate will be enforced from genesis, and any bids with rate strictly less than the minimum will fail. For pre-existing networks, all validator bids that have a delegate rate less than the minimum will not be affected during the protocol upgrade. However, any attempt to modify the validator's pre-existing stake either through add_bid or withdraw_bid will require the validator to set a delegation rate to at least the minimum. The same applies when a validator attempts to modify their reservations.
The newly added chainspec setting is written to the Auction system contract's named keys under the entry minimum_delegation_rate. minimum_delegation_rate will be set to 0 with this release, which keeps behavior inert (as mandated by the CVV006 vote). A future community vote will select a value to be set in a future network upgrade.
Recalculation of total supply
The v2.2.0 release also includes an internal change to protocol upgrade logic that recalculates the total supply of the chain by iterating over the balance records in global state upon upgrade. If the value after tallying the sum of balances differs from the value tracked by the Mint system contract, the logic will set the total supply to the sum obtained after iterating over the balance. This action is emitted as a WARN level message.
This message will always be emitted if there is a modification to balance records during a protocol upgrade with the global_state.toml
BUGFIX: Incorrect total supply tally during Genesis
The v2.2.0 release contains a modification to the protocol upgrade logic that re-calculates the total supply by iterating over the balances in the network.
Casper Mainnet
While release 2.1.2 was published in January 28th of 2026 and promoted to Testnet, this version of the protocol was never applied to Mainnet. However with the application of the v2.2.0 binary as part of the v2.2.0 protocol upgrade, the Casper mainnet will also receive the following changes that were applied to other networks.
Additionally, in compliance with the Mainnet community's mandate dictated in CVV008, the application of this protocol version will also include a one time token issuance via a global_state.toml file.
Change to the behavior of withdraw bid
The release includes a change to the behavior of withdraw_bid. Historically, when a validator would attempt to reduce their bid by an amount larger than their staked amount, the system would return an error. Post v2.0.0, the behavior was changed to trigger an unbonding instead of returning an error. This release restores the behavior of withdraw_bid to returning an error if a validator reduces their bid by an amount exceeding their staked amount. Additionally to further reduce unintentional unbondings as a result of validator error, the minimum_bid_amount threshold has been reduced to 500 CSPR as part of the protocol upgrade, matching the minimum delegation amount for delegators in the current chainspec.
BUGFIX: Prevent delegator from exceeding delegation limits set by their validator
V2.1.2 also contained a bug fix that prevented delegators from being able to exceed the limits of their delegation as set by their validator. In the previous binary versions, when a delegator would stake their tokens, the system would only compare the amount sent as part of the delegation, and not the amount they may have previously staked. As a result, a delegator could exceed the validator-set maximum by sending multiple delegations that when summed, exceeded the maximum, even when individually none of them did. In this release, the system considers the sum of any previously staked tokens and the current amount. If the final delegated amount does not lie between the limits as set by the validator, an error is thrown. When the protocol version containing this fix is applied, any delegators that then fall under the minimum will be unbonded. Conversely, any delegations that exceed the maximum will be partially unbonded to reduce their delegated amount to the maximum limit.
One time issuance
As required by CVV008, when v2.2.0 gets activated on Mainnet, a one-time-issuance will be applied whereby new token equivalent to maximally 33% of the supply at the time of the upgrade will be minted to a designated purse as defined by the global_state.toml that is included with the upgrade package. On other networks, a global_state.toml may be included for testing purposes.
v2.1.2
2.1.2 casper-node
Fixed
- Fixed an issue in the storage create which allowed delegators to exceed the maximum limit set by the validator for the validator's bid
Changed
- Changed the behavior of withdraw bid to return an UnbondAmountTooLarge error instead of triggering a unbonding of the validator and their delegators.
4.0.1 casper-storage
Changed
- Changed the withdraw bid behavior to return an UnbondingAmountTooLarge error instead of forcing a unbonding of the valdiator's bid
Fixed
- Fixed an issue in the storage create which allowed delegators to exceed the maximum limit set by the validator for the validator's bid
network configs
Changed
- Updated known_addresses to sync with node changes for config-example.toml for multiple networks.
v2.1.1
casper-node binary 2.1.1 corrected issues with minimum_delegation_amount applying due to logic error.
Configuration speeds chain up to 8 seconds blocks and modifies settings to double windows and half capacity of blocks to keep throughput similar while dropping latency.
v2.1.0
This release is a configuration only update. Staging will use the 2.0.4 binary.
Configurations for networks have been moved inside resources directory. This allows a nearly complete for release configuration in the casper-node repo for easier reference. A few fields will be modified as needed for staging the upgrade.
Major configuration changes:
- changes settings to optimize network operation at a block time of 8 seconds.
- Implementation of burn mechanism for fees on transaction
v2.0.4
v2.0.3
Summary
The Patch release 2.0.3 resolves a known bug identified at the time of the 2.0.0 release, a reported low impact bug, continuing precursor work for an upcoming feature, and some tech debt cleanup.
Bug:
- There was a design assumption that contract maintainers would choose to disable 1.x version(s) of their contracts when they upgrade them to 2.x versions, but this assumption was unfounded and the expected outcome isn’t required or enforced by the host. Thus in the case where there is both an enabled 1.x and 2.x contract version, an attempt to call a 1.x version would result in the loading of an applicable 2.x version of the contract (if any).
Impact:
- LOW - A relatively rare edge case. It was detected in testnet hours before mainnet upgrade to 2.0. However, initial assessment was that the potential impact which was insufficient to stop and unwind the release. Ecosystem impact is a little higher as this bug discourages the upgrading of some 1.x smart contracts, depending upon existent and intended usage.
- If a contract maintainer disables prior 1.x version(s) of their preexisting contract as part of upgrading the contract to 2.x, then they are not affected by this bug. Disabling the prior version of a contract upon upgrade is the preferred practice.
Root Cause:
- Contract major versions (e.g., 1.x vs 2.x) there was no way via the existing interfaces for a caller to specify major version for a specific contract version invocation. Instead, the logic defaulted to the
protocol_version_majorof the highest enabled version.
Change: The transaction structure and the ffi were extended to allow users to precisely identify a specific contract version:
- FFI - new function:
casper_call_package_version, which includes args formajor_version_ptrandmajor_version_size:-
pub fn casper_call_package_version( contract_package_hash_ptr: *const u8, contract_package_hash_size: usize, major_version_ptr: *const u8, major_version_size: usize, contract_version_ptr: *const u8, contract_version_size: usize, entry_point_name_ptr: *const u8, entry_point_name_size: usize, runtime_args_ptr: *const u8, runtime_args_size: usize, result_size: *mut usize, ) -> i32;
-
- Transaction v1
TransactionInvocationTargetByPackageHash&ByPackageNamevariants:- new field:
protocol_version_major: Option<ProtocolVersionMajor>
- new field:
Default Behavior:
- When
protocol_version_majorisNone, the system uses the current major protocol version - When
versionisNone, the system uses the highest enabled version of the contract - All combinations for these two fields are supported by default ( some + some, some + none, none + some, none + none).
Bug:
- Inconsistent enforcement of minimum bid amount between native
withdraw_bidand vm1 initiatedwithdraw_bid. Native logic was correct.
Impact:
- LOW - Inconsistent but basically harmless.
Root Cause:
- Contract runtime instantiation of the vm1 execution engine did not inject the chainspec defined minimum bid, resulting in the value being defaulted to a lower number. Instantiation of native runtime did use the chainspec value.
Fix:
- Changed contract runtime instantiation of vm1 execution engine to inject the chainspec specified value.
Misc:
- ONGOING: Continuing work on vm2 (enabled in some test environments but not intended to be turned on for mainnet as part of this rollout).
- TECH DEBT: Removed several unwraps in
tracking_copyimplementation. Components and utilities should not be allowed to panic if avoidable, such as in this case. Instead, they should either return a message or error code, or raise an event and allow the node to shutdown gracefully, or be made infallible.