2026-01-06 11:27:50 +00:00
|
|
|
{
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"33": {
|
|
|
|
|
"address": "0x9A676e781A523b5d0C0e43731313A708CB607508",
|
|
|
|
|
"code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c657665
|
2026-01-22 12:48:27 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000a85233c63b9ee964add6f2cffe00fd84eb32338f",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65",
|
|
|
|
|
"0xedc9a600799bdec0e14ee5042ef794e1b4738abf52d225059d6b470373867218": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x00000000000000000000000000000000000000000000000000000000000000cb": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc"
|
2026-01-22 12:48:27 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"19": {
|
|
|
|
|
"address": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b5060043610610148575f3560e01c8063a1060c88116100bf578063dce974b911610079578063dce974b914610334578063df5cf7231461035b578063ec76f44214610382578063f2fde38b146103b5578063f698da25146103c8578063fabc1cbc146103d0575f5ffd5b8063a1060c881461029a578063a364f4da146102ad578063a98fb355146102c0578063c825fe68146102d3578063cd6dc687146102fa578063d79aceab1461030d575f5ffd5b80635ac86ab7116101105780635ac86ab7146101fa5780635c975abb1461021d578063715018a61461022f578063886f1195146102375780638da5cb5b146102765780639926ee7d14610287575f5ffd5b8063136439dd1461014c578063374823b51461016157806349075da3146101a357806354fd4d50146101dd578063595c6a67146101f2575b5f5ffd5b61015f61015a3660046110dc565b6103e3565b005b61018e61016f366004611107565b609960209081525f928352604080842090915290825290205460ff1681565b60405190151581526020015b60405180910390f35b6101d06101b1366004611131565b609860209081525f928352604080842090915290825290205460ff1681565b60405161019a919061117c565b6101e561041d565b60405161019a91906111d0565b61015f61044d565b61018e6102083660046111e9565b606654600160ff9092169190911b9081161490565b6066545b60405190815260200161019a565b61015f610461565b61025e7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6040516001600160a01b03909116815260200161019a565b6033546001600160a01b031661025e565b61015f610295366004611277565b610472565b6102216102a8366004611364565b610673565b61015f6102bb3660046113a7565b6106f2565b61015f6102ce3660046113c2565b6107b9565b6102217f809c5ac049c45b7a7f050a20f00c16cf63797efbf8b1eb8d749fdfa39ff8f92981565b61015f610308366004611107565b610800565b6102217fda2c89bafdd34776a2b8bb9c83c82f419e20cc8c67207f70edd58249b92661bd81565b6102217f4ee65f64218c67b68da66fd0db16560040a6b973290b9e71912d661ee53fe49581565b61025e7f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8281565b61015f6103903660046110dc565b335f90815260996020908152604080832093835292905220805460ff19166001179055565b61015f6103c33660046113a7565b61091c565b610221610995565b61015f6103de3660046110dc565b610a4e565b6103eb610ab4565b60665481811681146104105760405163c61dca5d60e01b815260040160405180910390fd5b61041982610b57565b5050565b60606104487f76312e302e300000000000000000000000000000000000000000000000000006610b94565b905090565b610455610ab4565b61045f5f19610b57565b565b610469610bd1565b61045f5f610c2b565b5f61047c81610c7c565b6001335f9081526098602090815260408083206001600160a01b038816845290915290205460ff1660018111156104b5576104b5611168565b036104d357604051631aa528bb60e11b815260040160405180910390fd5b6001600160a01b0383165f90815260996020908152604080832085830151845290915290205460ff161561051a57604051630d4c4c9160e21b815260040160405180910390fd5b6040516336b87bd760e11b81526001600160a01b0384811660048301527f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd821690636d70f7ae90602401602060405180830381865afa15801561057e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a29190611430565b6105bf57604051639f88c8af60e01b815260040160405180910390fd5b6105e3836105d7853386602001518760400151610673565b84516040860151610ca7565b6001600160a01b0383165f81815260996020908152604080832086830151845282528083208054600160ff19918216811790925533808652609885528386208787529094529382902080549094168117909355519092917ff0952b1c65271d819d39983d2abb044b9cace59bcc4d4dd389f586ebdcb15b4191610666919061117c565b60405180910390a3505050565b604080517fda2c89bafdd34776a2b8bb9c83c82f419e20cc8c67207f70edd58249b92661bd60208201526001600160a01b038087169282019290925290841660608201526080810183905260a081018290525f906106e99060c00160405160208183030381529060405280519060200120610cff565b95945050505050565b5f6106fc81610c7c565b6001335f9081526098602090815260408083206001600160a01b038716845290915290205460ff16600181111561073557610735611168565b14610753576040516352df45c960e01b815260040160405180910390fd5b335f8181526098602090815260408083206001600160a01b0387168085529252808320805460ff191690555190917ff0952b1c65271d819d39983d2abb044b9cace59bcc4d4dd389f586ebdcb15b41916107ad919061117c565b60405180910390a35050565b336001600160a01b03167fa89c1dc243d8908a96dd84944bcc97d6bc6ac00dd78e20621576be6a3c94371383836040516107f492919061144f565b604051
|
2026-01-22 12:48:27 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
2026-01-22 12:48:27 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"38": {
|
|
|
|
|
"address": "0x59b670e9fA9D0A427751Af201D676719a970857b",
|
|
|
|
|
"code": "0x6080604052600436106101bd575f3560e01c80636691954e116100f2578063b522538a11610092578063d06d558711610062578063d06d55871461063f578063dda3346c1461065e578063ee94d67c1461067d578063f074ba621461069c575f5ffd5b8063b522538a146105ce578063c44e30dc146105ed578063c490744214610601578063c4d66de814610620575f5ffd5b80637439841f116100cd5780637439841f1461053457806374cdd7981461056957806388676cad1461059c5780639b4e4634146105bb575f5ffd5b80636691954e146104d65780636c0d2d5a146104e95780636fcd0e5314610508575f5ffd5b806342ecff2a1161015d57806352396a591161013857806352396a591461043657806354fd4d501461046a578063587533571461048b57806358eaee79146104aa575f5ffd5b806342ecff2a146102f25780634665bcda1461031857806347d283721461034b575f5ffd5b80632340e8d3116101985780632340e8d31461027a5780633474aa161461028f5780633f5fa57a146102c05780633f65cf19146102d3575f5ffd5b8063039157d2146101fb5780630b18ff661461021c5780631e51553314610258575f5ffd5b366101f7576040513481527f6fdd3dbdb173299608c0aa9f368735857c8842b581f8389238bf05bd04b3bf499060200160405180910390a1005b5f5ffd5b348015610206575f5ffd5b5061021a610215366004613a3e565b6106bb565b005b348015610227575f5ffd5b5060335461023b906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610263575f5ffd5b5061026c6109f0565b60405190815260200161024f565b348015610285575f5ffd5b5061026c60395481565b34801561029a575f5ffd5b506034546001600160401b03165b6040516001600160401b03909116815260200161024f565b61021a6102ce366004613af9565b610a11565b3480156102de575f5ffd5b5061021a6102ed366004613b37565b610d49565b3480156102fd575f5ffd5b50603a546102a890600160401b90046001600160401b031681565b348015610323575f5ffd5b5061023b7f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b181565b348015610356575f5ffd5b506103db6040805160a0810182525f80825260208201819052918101829052606081018290526080810191909152506040805160a081018252603c548152603d5462ffffff811660208301526001600160401b0363010000008204811693830193909352600160581b810460070b6060830152600160981b9004909116608082015290565b60405161024f91905f60a0820190508251825262ffffff60208401511660208301526001600160401b036040840151166040830152606083015160070b60608301526001600160401b03608084015116608083015292915050565b348015610441575f5ffd5b506102a8610450366004613c0e565b603b6020525f90815260409020546001600160401b031681565b348015610475575f5ffd5b5061047e610fd2565b60405161024f9190613c57565b348015610496575f5ffd5b50603e5461023b906001600160a01b031681565b3480156104b5575f5ffd5b506104c96104c4366004613ca6565b610ffd565b60405161024f9190613d0c565b61021a6104e4366004613af9565b61105f565b3480156104f4575f5ffd5b5061026c610503366004613c0e565b611361565b348015610513575f5ffd5b50610527610522366004613d1a565b61146f565b60405161024f9190613d31565b34801561053f575f5ffd5b506104c961054e366004613d1a565b5f90815260366020526040902054600160c01b900460ff1690565b348015610574575f5ffd5b5061023b7f000000000000000000000000c7f2cf4845c6db0e1a1e91ed41bcd0fcc1b0e14181565b3480156105a7575f5ffd5b5061021a6105b6366004613d91565b61151a565b61021a6105c9366004613dac565b61160f565b3480156105d9575f5ffd5b506105276105e8366004613ca6565b61178d565b3480156105f8575f5ffd5b5061026c61187c565b34801561060c575f5ffd5b5061021a61061b366004613e41565b611898565b34801561062b575f5ffd5b5061021a61063a366004613e6b565b6119cf565b34801561064a575f5ffd5b5061021a610659366004613e6b565b611b19565b348015610669575f5ffd5b5061021a610678366004613f56565b611bad565b348015610688575f5ffd5b50603a546102a8906001600160401b031681565b3480156106a7575f5ffd5b5061021a6106b6366004614028565b611d0c565b604051635ac86ab760e01b8152600660048201819052907f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b031690635ac86ab790602401602060405180830381865afa158015610721573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610745919061408f565b156107635760405163840a48d560e01b815260040160405180910390fd5b604051635ac86ab760e01b8152600860048201819052907f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b031690635ac86ab790602401602060405180830381865afa1580156107c9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ed919061408f565b1561080b576040516384
|
|
|
|
|
"storage": {
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
|
|
|
|
}
|
2026-01-22 12:48:27 +00:00
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"26": {
|
|
|
|
|
"address": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
|
2026-01-22 12:48:27 +00:00
|
|
|
"code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c657665
|
|
|
|
|
"storage": {
|
|
|
|
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788",
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000004a679253410272dd5232b3ff7cf5dbb88f295319",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001"
|
2026-01-22 12:48:27 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"4": {
|
|
|
|
|
"address": "0x1111111111111111111111111111111111111111",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80632baeceb71461004e5780638381f58a146100585780638da5cb5b14610073578063d826f88f1461009e575b5f5ffd5b6100566100a6565b005b6100605f5481565b6040519081526020015b60405180910390f35b600154610086906001600160a01b031681565b6040516001600160a01b03909116815260200161006a565b61005661010d565b5f5f54116100fb5760405162461bcd60e51b815260206004820152601f60248201527f4e756d6265722073686f756c642062652067726561746572207468616e20300060448201526064015b60405180910390fd5b60015f54610109919061016d565b5f55565b6001546001600160a01b031633146101675760405162461bcd60e51b815260206004820152601760248201527f4f6e6c792063616c6c61626c65206279206f776e65722100000000000000000060448201526064016100f2565b600a5f55565b8181038181111561018c57634e487b7160e01b5f52601160045260245ffd5b9291505056fea2646970667358221220ac5899491afd834afd223fd632497d1c0c7593961eda22f04c58db4b504999cf64736f6c634300081c0033000000",
|
2026-01-22 12:48:27 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000000000000000000000000000000000000000000a"
|
2026-01-22 12:48:27 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"36": {
|
|
|
|
|
"address": "0xdf077F5F72071dF6e8B0a78071E496bA17b5Ee0c",
|
|
|
|
|
"code": "0x608060405260043610610036575f3560e01c8063338c5371146100415780639bb66b2814610091578063e905182a146100be575f5ffd5b3661003d57005b5f5ffd5b34801561004c575f5ffd5b506100747f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f8168881565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561009c575f5ffd5b506100b06100ab3660046101ae565b6100ff565b604051610088929190610239565b3480156100c9575f5ffd5b506100f17f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b7981565b604051908152602001610088565b5f6060336001600160a01b037f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f81688161461014a576040516282b42960e81b815260040160405180910390fd5b846001600160a01b03168484604051610164929190610277565b5f60405180830381855af49150503d805f811461019c576040519150601f19603f3d011682016040523d82523d5f602084013e6101a1565b606091505b5091509150935093915050565b5f5f5f604084860312156101c0575f5ffd5b83356001600160a01b03811681146101d6575f5ffd5b9250602084013567ffffffffffffffff8111156101f1575f5ffd5b8401601f81018613610201575f5ffd5b803567ffffffffffffffff811115610217575f5ffd5b866020828401011115610228575f5ffd5b939660209190910195509293505050565b8215158152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b818382375f910190815291905056fea26469706673582212208fe760f358faedf4a90fd4b23c39c8397def11c5b035ea1406af976ecc426bbf64736f6c634300081c00330000000000",
|
|
|
|
|
"storage": {}
|
|
|
|
|
},
|
|
|
|
|
"24": {
|
|
|
|
|
"address": "0x0000BBdDc7CE488642fb579F8B00f3a590007251",
|
|
|
|
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460d35760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f82111560685781019083028483029004916001019190604d565b9093900492505050366060146088573661019a573461019a575f5260205ff35b341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060021160e7575060025b5f5b8181146101295782810160040260040181607402815460601b815260140181600101548152602001816002015481526020019060030154905260010160e9565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd00",
|
|
|
|
|
"storage": {}
|
|
|
|
|
},
|
|
|
|
|
"41": {
|
|
|
|
|
"address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9",
|
|
|
|
|
"code": "0x73dc64a140aa3e981100a9beca4e685f962f0cf6c93014608060405260043610610090575f3560e01c8063741fad8811610063578063741fad88146101125780638257f3d514610131578063ae8a4d9814610150578063c31308d11461016f575f5ffd5b80630c86ea461461009457806325394645146100b55780635b2e9c4c146100d457806365529675146100f3575b5f5ffd5b81801561009f575f5ffd5b506100b36100ae366004610a3a565b61018e565b005b8180156100c0575f5ffd5b506100b36100cf366004610a3a565b610229565b8180156100df575f5ffd5b506100b36100ee366004610a3a565b6102af565b8180156100fe575f5ffd5b506100b361010d366004610a8f565b610337565b81801561011d575f5ffd5b506100b361012c366004610adf565b6103aa565b81801561013c575f5ffd5b506100b361014b366004610a3a565b610433565b81801561015b575f5ffd5b506100b361016a366004610a3a565b6104c4565b81801561017a575f5ffd5b506100b3610189366004610a8f565b6104ee565b7f59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f65f6101bc84840185610baf565b8051835560208101516001840180546fffffffffffffffffffffffffffffffff19166001600160801b039092169190911790556040808201516002850155519091507f5e3c25378b5946068b94aa2ea10c4c1e215cc975f994322b159ddc9237a973d4905f90a150505050565b5f61023682840184610c6d565b80516020820151604080840151905163a3499c7360e01b8152939450732279b7a0a67db372996a5fab50d91eaa73d2ebe69363a3499c739361027e9390929091600401610d22565b5f6040518083038186803b158015610294575f5ffd5b505af41580156102a6573d5f5f3e3d5ffd5b50505050505050565b7f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e5f6102dd84840185610d51565b805160208201516001600160801b03908116600160801b0291161760028401556040808201516003850155519091507f4793c0cb5bef4b1fdbbfbcf17e06991844eb881088b012442af17a12ff38d5cd905f90a150505050565b5f61034482840184610d86565b90505f610353825f01516105c4565b60208301519091506001600160a01b031661038a576103858582846040015185606001516001600160801b031661061c565b6103a3565b6103a38582846020015185604001518660600151610679565b5050505050565b60408051637061726160e01b602080830191909152607d60e31b602483015282516008818403018152602890920190925280519101206103eb9084906106de565b15610408576040516282b42960e81b815260040160405180910390fd5b5f61041582840184610de4565b905061042d815f0151826020015183604001516106e9565b50505050565b7e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab5f61046084840185610e2f565b8051835491925090839060ff19166001838181111561048157610481610e7d565b021790555080516040517f4016a1377b8961c4aa6f3a2d3de830a685ddbfe0f228ffc0208eb96304c4cf1a916104b691610e91565b60405180910390a150505050565b5f6104d182840184610eb7565b905061042d815f0151826020015183604001518460600151610762565b5f6104fb82840184610f71565b90505f61050a825f01516105c4565b90508160200151515f03610531576040516309e256f760e21b815260040160405180910390fd5b5f5f836020015180602001905181019061054b919061104f565b90925090505f82801561056057610560610e7d565b036102a6575f5f5f8380602001905181019061057c919061109f565b919450925090506001600160a01b0383166105ab576105a68a8784846001600160801b031661061c565b6105b8565b6105b88a87858585610679565b50505050505050505050565b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ad60205260409020546001600160a01b0316806106175760405163d3227c9b60e01b815260040160405180910390fd5b919050565b6040516001600160a01b0383166024820152604481018290525f9060640160408051601f198184030181529190526020810180516001600160e01b03166305b1137b60e01b17905290506106718486836108ad565b505050505050565b6040516001600160a01b038085166024830152831660448201526001600160801b03821660648201525f9060840160408051601f198184030181529190526020810180516001600160e01b03166309733b7b60e21b17905290506102a68587836108ad565b818114155b92915050565b5f6106f384610939565b6040516340c10f1960e01b81526001600160a01b0385811660048301526001600160801b0385166024830152919250908216906340c10f19906044015f604051808303815f87803b158015610746575f5ffd5b505af1158015610758573d5f5f3e3d5ffd5b5050505050505050565b5f8481527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23260205260408120547f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e906001600160a01b0316156107d857604051633ea7ffd960e11b815260040160405180910390fd5b5f8585856040516107e8906109e9565b6107f4939291906110e9565b604051
|
|
|
|
|
"storage": {}
|
|
|
|
|
},
|
|
|
|
|
"17": {
|
|
|
|
|
"address": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b506004361061026b575f3560e01c80637ecebe001161014b578063ca8aa7c7116100bf578063f2fde38b11610084578063f2fde38b1461062f578063f3b4a00014610642578063f698da251461064c578063fabc1cbc14610654578063fd98042314610667578063fe243a171461067a575f5ffd5b8063ca8aa7c71461059b578063cbc2bd62146105c2578063de44acb6146105d5578063df5cf723146105f5578063e7a050aa1461061c575f5ffd5b80638da5cb5b116101105780638da5cb5b1461052b57806394f649dd1461053c578063967fc0d21461054f5780639ac01d6114610562578063b5d8b5b814610575578063c665670214610588575f5ffd5b80637ecebe001461047f578063829fca731461049e578063886f1195146104b157806388c10299146104f05780638b8aac3c14610503575f5ffd5b806350ff7225116101e25780635de08ff2116101a75780635de08ff2146103fc578063663c1de41461040f578063715018a614610431578063724af4231461043957806376fb162b1461044c5780637def15641461045f575f5ffd5b806350ff72251461037c57806354fd4d50146103a4578063595c6a67146103b95780635ac86ab7146103c15780635c975abb146103f4575f5ffd5b806332e89ace1161023357806332e89ace146102f157806336a8c500146103045780633f292b081461031a5780633fb99ca51461032f57806348825e94146103425780634b6d5d6e14610369575f5ffd5b8063136439dd1461026f5780631794bb3c146102845780632d44def6146102975780632eae418c146102bd57806331f8fb4c146102d0575b5f5ffd5b61028261027d366004612e33565b6106a4565b005b610282610292366004612e5e565b6106de565b6102aa6102a5366004612eb2565b610804565b6040519081526020015b60405180910390f35b6102826102cb366004612ef0565b6108b6565b6102e36102de366004612f3e565b610982565b6040516102b4929190612fda565b6102aa6102ff36600461304b565b610b10565b61030c610b95565b6040516102b4929190613125565b610322610cb0565b6040516102b4919061317b565b61028261033d3660046131d8565b610d98565b6102aa7f4337f82d142e41f2a8c10547cd8c859bddb92262a61058e77842e24d9dea922481565b61028261037736600461321c565b610ee0565b61038f61038a366004612e5e565b61102d565b604080519283526020830191909152016102b4565b6103ac6110a1565b6040516102b49190613265565b6102826110d1565b6103e46103cf366004613277565b609854600160ff9092169190911b9081161490565b60405190151581526020016102b4565b6098546102aa565b61028261040a366004613297565b6110e5565b6103e461041d36600461321c565b60d16020525f908152604090205460ff1681565b610282611238565b6102aa610447366004612e5e565b611249565b6102aa61045a366004612eb2565b6112a6565b61047261046d366004613306565b6112f5565b6040516102b49190613320565b6102aa61048d36600461321c565b60ca6020525f908152604090205481565b6102aa6104ac366004612f3e565b611327565b6104d87f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6040516001600160a01b0390911681526020016102b4565b6104726104fe366004612f3e565b611361565b6102aa61051136600461321c565b6001600160a01b03165f90815260ce602052604090205490565b6033546001600160a01b03166104d8565b6102e361054a36600461321c565b611498565b60cb546104d8906001600160a01b031681565b6102aa610570366004613332565b61160f565b610282610583366004613297565b6116a0565b61028261059636600461321c565b6117e7565b6104d87f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed81565b6104d86105d0366004613393565b61180a565b6105e86105e336600461321c565b61183e565b6040516102b491906133bd565b6104d87f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8281565b6102aa61062a366004612e5e565b6118b1565b61028261063d36600461321c565b6118e4565b6104d8620e16e481565b6102aa61195a565b610282610662366004612e33565b611a13565b6102aa61067536600461321c565b611a80565b6102aa6106883660046133cf565b60cd60209081525f928352604080842090915290825290205481565b6106ac611a95565b60985481811681146106d15760405163c61dca5d60e01b815260040160405180910390fd5b6106da82611b38565b5050565b5f54610100900460ff16158080156106fc57505f54600160ff909116105b806107155750303b15801561071557505f5460ff166001145b61077d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff19166001179055801561079e575f805461ff0019166101001790555b6107a782611b38565b6107b084611b75565b6107b983611bc6565b80156107fe575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020016040
|
feat: Implement EigenLayer Rewards V2 distribution (#351)
### Summary
This PR implements the EigenLayer Rewards Distribution V2 model for
DataHaven, replacing the previous merkle-root-based rewards registry
approach with EigenLayer's native `OperatorDirectedRewardsSubmission`
API. This enables direct integration with EigenLayer's
RewardsCoordinator for validator rewards distribution.
### Motivation
EigenLayer's V2 rewards model provides several advantages:
- **Direct integration**: Uses EigenLayer's native
`createOperatorDirectedOperatorSetRewardsSubmission` API
- **Per-operator rewards**: Distributes rewards proportionally to
individual operators based on their earned points
- **Simplified architecture**: Removes the need for a separate
RewardsRegistry contract
- **Better UX**: Operators receive rewards directly through EigenLayer's
established claiming mechanism
### Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ DataHaven Substrate │
├─────────────────────────────────────────────────────────────────┤
│ Era End │
│ │ │
│ ▼ │
│ external-validators-rewards pallet │
│ │ generate_era_rewards_utils() │
│ │ • Calculate individual points per validator │
│ │ • Compute total inflation amount │
│ │ │
│ ▼ │
│ RewardsSubmissionAdapter (runtime_common) │
│ │ build() → points_to_rewards() → encode_rewards_calldata() │
│ │ │
│ ▼ │
│ Snowbridge Outbound Queue │
│ │ CallContract(ServiceManager.submitRewards(...)) │
└────│────────────────────────────────────────────────────────────┘
│
▼ Cross-chain message via Snowbridge
┌─────────────────────────────────────────────────────────────────┐
│ Ethereum │
├─────────────────────────────────────────────────────────────────┤
│ DataHavenServiceManager │
│ │ submitRewards(OperatorDirectedRewardsSubmission) │
│ │ • Approve wHAVE tokens to RewardsCoordinator │
│ │ │
│ ▼ │
│ EigenLayer RewardsCoordinator │
│ │ createOperatorDirectedOperatorSetRewardsSubmission() │
│ │ │
│ ▼ │
│ Operators claim rewards via EigenLayer │
└─────────────────────────────────────────────────────────────────┘
```
### Changes Overview
#### Smart Contracts (`contracts/`)
**DataHavenServiceManager.sol**
- Added `submitRewards(OperatorDirectedRewardsSubmission)` function to
submit rewards to EigenLayer's RewardsCoordinator
- Implements `SafeERC20` for secure token approvals
- Uses `onlyRewardsInitiator` modifier for access control (Snowbridge
Agent)
- Emits `RewardsSubmitted` and `RewardsInitiatorSet` events for tracking
**IDataHavenServiceManager.sol**
- Added `submitRewards()` interface for EigenLayer rewards submission
- Added `setRewardsInitiator()` interface for configuring the authorized
caller
- Added new events: `RewardsSubmitted`, `RewardsInitiatorSet`
**New Test: RewardsSubmitter.t.sol**
- Comprehensive test suite covering:
- Access control (only rewards initiator can submit)
- Single and multiple operator rewards
- Multiple consecutive submissions
- Custom descriptions and different tokens
#### Substrate Runtime (`operator/`)
**New: `runtime/common/src/rewards_adapter.rs` (934 lines)**
A generic, configurable adapter for building EigenLayer rewards
messages:
- **`RewardsSubmissionConfig` trait**: Runtime-agnostic configuration
interface
- `OutboundQueue`: Snowbridge outbound queue type
- `rewards_duration()`: Reward period duration (typically 86400s)
- `whave_token_address()`: wHAVE ERC20 token on Ethereum
- `service_manager_address()`: ServiceManager contract address
- `rewards_agent_origin()`: Snowbridge agent origin
- **`RewardsSubmissionAdapter<C>`**: Generic implementation of
`SendMessage` trait
- **`points_to_rewards()`**: Converts validator points to token amounts
- Proportional distribution based on total points
- Returns remainder (dust) from integer division
- Arithmetic overflow/underflow protection
- **`encode_rewards_calldata()`**: ABI-encodes the `submitRewards` call
- Uses `alloy-core` for type-safe Solidity ABI encoding
- Validates `uint96` multiplier bounds
- **Comprehensive test suite** covering:
- Basic and edge-case reward calculations
- Remainder/dust handling
- Overflow/underflow protection
- ABI encoding round-trip verification
- Message building with various configurations
**Modified: `pallets/external-validators-rewards/`**
- **`types.rs`**: Extended `EraRewardsUtils` struct:
```rust
pub struct EraRewardsUtils {
pub era_index: u32, // NEW
pub rewards_merkle_root: H256,
pub leaves: Vec<H256>,
pub leaf_index: Option<u64>,
pub total_points: u128,
pub individual_points: Vec<(H160, u32)>, // NEW
pub inflation_amount: u128, // NEW
pub era_start_timestamp: u32 // NEW
}
```
- **`lib.rs`**: Updated `generate_era_rewards_utils()`:
- Now accepts `inflation_amount` parameter
- Extracts `individual_points` as `(H160, u32)` tuples for EigenLayer
- Returns `None` when `total_points` is zero (prevents inflation with no
distribution)
- **`mock.rs`**: Updated test mock to use `H160` as `AccountId`
(matching DataHaven's EVM-compatible account model)
**Modified: Runtime Configurations**
All three runtimes (mainnet, stagenet, testnet) updated:
1. **New runtime parameters** (`runtime_params.rs`):
- `ServiceManagerAddress`: DataHaven ServiceManager contract on Ethereum
- `WHAVETokenAddress`: wHAVE ERC20 token address
- `RewardsGenesisTimestamp`: EigenLayer-aligned genesis timestamp
- `RewardsDuration`: Rewards period (default: 86400 = 1 day)
2. **Refactored `RewardsSendAdapter`**:
- Replaced inline implementation with `RewardsSubmissionAdapter<Config>`
- Each runtime implements `RewardsSubmissionConfig` trait
- Cleaner, DRY configuration
## ⚠️ Breaking Changes ⚠️
- **Runtime Parameters**: New parameters must be configured via
governance before rewards submission will work:
- `ServiceManagerAddress` (replaces `RewardsRegistryAddress`)
- `WHAVETokenAddress`
- `RewardsGenesisTimestamp`
- **Contract Interface**: `submitRewards()` now accepts a full
`OperatorDirectedRewardsSubmission` struct instead of a merkle root
---------
Co-authored-by: Gonza Montiel <gonzamontiel@users.noreply.github.com>
2026-01-06 23:53:03 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
feat: Implement EigenLayer Rewards V2 distribution (#351)
### Summary
This PR implements the EigenLayer Rewards Distribution V2 model for
DataHaven, replacing the previous merkle-root-based rewards registry
approach with EigenLayer's native `OperatorDirectedRewardsSubmission`
API. This enables direct integration with EigenLayer's
RewardsCoordinator for validator rewards distribution.
### Motivation
EigenLayer's V2 rewards model provides several advantages:
- **Direct integration**: Uses EigenLayer's native
`createOperatorDirectedOperatorSetRewardsSubmission` API
- **Per-operator rewards**: Distributes rewards proportionally to
individual operators based on their earned points
- **Simplified architecture**: Removes the need for a separate
RewardsRegistry contract
- **Better UX**: Operators receive rewards directly through EigenLayer's
established claiming mechanism
### Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ DataHaven Substrate │
├─────────────────────────────────────────────────────────────────┤
│ Era End │
│ │ │
│ ▼ │
│ external-validators-rewards pallet │
│ │ generate_era_rewards_utils() │
│ │ • Calculate individual points per validator │
│ │ • Compute total inflation amount │
│ │ │
│ ▼ │
│ RewardsSubmissionAdapter (runtime_common) │
│ │ build() → points_to_rewards() → encode_rewards_calldata() │
│ │ │
│ ▼ │
│ Snowbridge Outbound Queue │
│ │ CallContract(ServiceManager.submitRewards(...)) │
└────│────────────────────────────────────────────────────────────┘
│
▼ Cross-chain message via Snowbridge
┌─────────────────────────────────────────────────────────────────┐
│ Ethereum │
├─────────────────────────────────────────────────────────────────┤
│ DataHavenServiceManager │
│ │ submitRewards(OperatorDirectedRewardsSubmission) │
│ │ • Approve wHAVE tokens to RewardsCoordinator │
│ │ │
│ ▼ │
│ EigenLayer RewardsCoordinator │
│ │ createOperatorDirectedOperatorSetRewardsSubmission() │
│ │ │
│ ▼ │
│ Operators claim rewards via EigenLayer │
└─────────────────────────────────────────────────────────────────┘
```
### Changes Overview
#### Smart Contracts (`contracts/`)
**DataHavenServiceManager.sol**
- Added `submitRewards(OperatorDirectedRewardsSubmission)` function to
submit rewards to EigenLayer's RewardsCoordinator
- Implements `SafeERC20` for secure token approvals
- Uses `onlyRewardsInitiator` modifier for access control (Snowbridge
Agent)
- Emits `RewardsSubmitted` and `RewardsInitiatorSet` events for tracking
**IDataHavenServiceManager.sol**
- Added `submitRewards()` interface for EigenLayer rewards submission
- Added `setRewardsInitiator()` interface for configuring the authorized
caller
- Added new events: `RewardsSubmitted`, `RewardsInitiatorSet`
**New Test: RewardsSubmitter.t.sol**
- Comprehensive test suite covering:
- Access control (only rewards initiator can submit)
- Single and multiple operator rewards
- Multiple consecutive submissions
- Custom descriptions and different tokens
#### Substrate Runtime (`operator/`)
**New: `runtime/common/src/rewards_adapter.rs` (934 lines)**
A generic, configurable adapter for building EigenLayer rewards
messages:
- **`RewardsSubmissionConfig` trait**: Runtime-agnostic configuration
interface
- `OutboundQueue`: Snowbridge outbound queue type
- `rewards_duration()`: Reward period duration (typically 86400s)
- `whave_token_address()`: wHAVE ERC20 token on Ethereum
- `service_manager_address()`: ServiceManager contract address
- `rewards_agent_origin()`: Snowbridge agent origin
- **`RewardsSubmissionAdapter<C>`**: Generic implementation of
`SendMessage` trait
- **`points_to_rewards()`**: Converts validator points to token amounts
- Proportional distribution based on total points
- Returns remainder (dust) from integer division
- Arithmetic overflow/underflow protection
- **`encode_rewards_calldata()`**: ABI-encodes the `submitRewards` call
- Uses `alloy-core` for type-safe Solidity ABI encoding
- Validates `uint96` multiplier bounds
- **Comprehensive test suite** covering:
- Basic and edge-case reward calculations
- Remainder/dust handling
- Overflow/underflow protection
- ABI encoding round-trip verification
- Message building with various configurations
**Modified: `pallets/external-validators-rewards/`**
- **`types.rs`**: Extended `EraRewardsUtils` struct:
```rust
pub struct EraRewardsUtils {
pub era_index: u32, // NEW
pub rewards_merkle_root: H256,
pub leaves: Vec<H256>,
pub leaf_index: Option<u64>,
pub total_points: u128,
pub individual_points: Vec<(H160, u32)>, // NEW
pub inflation_amount: u128, // NEW
pub era_start_timestamp: u32 // NEW
}
```
- **`lib.rs`**: Updated `generate_era_rewards_utils()`:
- Now accepts `inflation_amount` parameter
- Extracts `individual_points` as `(H160, u32)` tuples for EigenLayer
- Returns `None` when `total_points` is zero (prevents inflation with no
distribution)
- **`mock.rs`**: Updated test mock to use `H160` as `AccountId`
(matching DataHaven's EVM-compatible account model)
**Modified: Runtime Configurations**
All three runtimes (mainnet, stagenet, testnet) updated:
1. **New runtime parameters** (`runtime_params.rs`):
- `ServiceManagerAddress`: DataHaven ServiceManager contract on Ethereum
- `WHAVETokenAddress`: wHAVE ERC20 token address
- `RewardsGenesisTimestamp`: EigenLayer-aligned genesis timestamp
- `RewardsDuration`: Rewards period (default: 86400 = 1 day)
2. **Refactored `RewardsSendAdapter`**:
- Replaced inline implementation with `RewardsSubmissionAdapter<Config>`
- Each runtime implements `RewardsSubmissionConfig` trait
- Cleaner, DRY configuration
## ⚠️ Breaking Changes ⚠️
- **Runtime Parameters**: New parameters must be configured via
governance before rewards submission will work:
- `ServiceManagerAddress` (replaces `RewardsRegistryAddress`)
- `WHAVETokenAddress`
- `RewardsGenesisTimestamp`
- **Contract Interface**: `submitRewards()` now accepts a full
`OperatorDirectedRewardsSubmission` struct instead of a merkle root
---------
Co-authored-by: Gonza Montiel <gonzamontiel@users.noreply.github.com>
2026-01-06 23:53:03 +00:00
|
|
|
}
|
|
|
|
|
},
|
2026-01-22 12:48:27 +00:00
|
|
|
"27": {
|
|
|
|
|
"address": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
|
|
|
|
|
"code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c657665
|
|
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788",
|
2026-01-22 12:48:27 +00:00
|
|
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44",
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001"
|
2026-01-22 12:48:27 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"28": {
|
|
|
|
|
"address": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
|
2026-01-22 12:48:27 +00:00
|
|
|
"code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c657665
|
|
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000067d269191c92caf3cd7723f116c85e6e9bf55933",
|
|
|
|
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788"
|
2026-01-22 12:48:27 +00:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"39": {
|
|
|
|
|
"address": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b50600436106102b1575f3560e01c80636d70f7ae1161017b578063bb45fef2116100e4578063e4cc3f901161009e578063f698da2511610079578063f698da25146107ce578063fabc1cbc146107d6578063fd8aa88d146107e9578063fe4b84df146107fc575f5ffd5b8063e4cc3f9014610788578063eea9064b1461079b578063f0e0e676146107ae575f5ffd5b8063bb45fef2146106b9578063bfae3fd2146106e6578063c448feb8146106f9578063c978f7ac1461072d578063ca8aa7c71461074e578063da8be86414610775575f5ffd5b80639104c319116101355780639104c319146106175780639435bb431461063257806399f5371b14610645578063a178848414610665578063a33a343314610684578063b7f06ebe14610697575f5ffd5b80636d70f7ae1461057a5780636e1744481461058d578063778e55f3146105a057806378296ec5146105ca578063886f1195146105dd5780639004134714610604575f5ffd5b806354b7c96c1161021d5780635c975abb116101d75780635c975abb146104d45780635d975e88146104dc5780635dd68579146104fd57806360a0d1ce1461051e57806365da12641461053157806366d5ba9314610559575f5ffd5b806354b7c96c1461045b57806354fd4d501461046e578063595c6a6714610483578063597b36da1461048b5780635ac86ab71461049e5780635ae679a7146104c1575f5ffd5b806339b70e381161026e57806339b70e381461036a5780633c651cf2146103a95780633cdeb5e0146103bc5780633e28391d146103ea5780634657e26a1461040d5780634665bcda14610434575f5ffd5b806304a4f979146102b55780630b9f487a146102ef5780630dd8dd0214610302578063136439dd1461032257806325df922e146103375780632aa6d88814610357575b5f5ffd5b6102dc7f14bde674c9f64b2ad00eaaee4a8bed1fabef35c7507e3c5b9cfc9436909a2dad81565b6040519081526020015b60405180910390f35b6102dc6102fd366004614a7f565b61080f565b610315610310366004614b16565b610897565b6040516102e69190614b54565b610335610330366004614b8b565b610b09565b005b61034a610345366004614d20565b610b43565b6040516102e69190614dce565b610335610365366004614e30565b610ca3565b6103917f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750881565b6040516001600160a01b0390911681526020016102e6565b6103356103b7366004614e8e565b610df7565b6103916103ca366004614ed1565b6001600160a01b039081165f908152609960205260409020600101541690565b6103fd6103f8366004614ed1565b610f4a565b60405190151581526020016102e6565b6103917f0000000000000000000000003aa5ebb10dc797cac828524e59a333d0a371443c81565b6103917f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b181565b610335610469366004614eec565b610f69565b610476610fd7565b6040516102e69190614f51565b610335611007565b6102dc61049936600461501f565b61101b565b6103fd6104ac366004615050565b606654600160ff9092169190911b9081161490565b6102dc6104cf366004615084565b61104a565b6066546102dc565b6104ef6104ea366004614b8b565b6111bc565b6040516102e69291906151b9565b61051061050b366004614ed1565b6111d9565b6040516102e692919061522b565b61033561052c366004615298565b611303565b61039161053f366004614ed1565b609a6020525f90815260409020546001600160a01b031681565b61056c610567366004614ed1565b6114ae565b6040516102e69291906152d7565b6103fd610588366004614ed1565b6117ae565b6102dc61059b366004614eec565b6117e6565b6102dc6105ae366004614eec565b609860209081525f928352604080842090915290825290205481565b6103356105d83660046152e9565b611890565b6103917f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b61034a610612366004615339565b611926565b61039173beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac081565b610335610640366004615385565b6119fc565b610658610653366004614b8b565b611ab7565b6040516102e69190615421565b6102dc610673366004614ed1565b609f6020525f908152604090205481565b610315610692366004615433565b611bd3565b6103fd6106a5366004614b8b565b609e6020525f908152604090205460ff1681565b6103fd6106c736600461551a565b609c60209081525f928352604080842090915290825290205460ff1681565b6102dc6106f4366004614eec565b611beb565b60405163ffffffff7f00000000000000000000000000000000000000000000000000000000000000321681526020016102e6565b61074061073b366004615339565b611c27565b6040516102e6929190615544565b6103917f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed81565b610315610783366004614ed1565b611eb4565b610335610796366004615563565b611fdd565b6103356107a9366004615433565b612015565b6107c16107bc3660046155e1565b612080565b6040516102e6919061568e565b6102dc612125565b6103356107e4366004614b8b565b6121de565b6103156107f7366004614ed1565b
|
|
|
|
|
"storage": {
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
|
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"18": {
|
|
|
|
|
"address": "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b50600436106100f0575f3560e01c806366ae69a011610093578063a77cf3d211610063578063a77cf3d214610238578063ad209a9b1461024b578063bb51f1eb14610272578063df0dd0d514610285575f5ffd5b806366ae69a0146101b05780636f55bd32146101db5780638ab81d1314610202578063a401662b14610215575f5ffd5b806341c9634e116100ce57806341c9634e1461013e578063591d99ee146101545780635da57fe91461017b578063623b223d1461019b575f5ffd5b80630a7c8faa146100f45780632cdea7171461011e5780633666751314610136575b5f5ffd5b610100610dad60f31b81565b6040516001600160f01b031990911681526020015b60405180910390f35b61012661030f565b60405161011594939291906124a2565b610126610390565b6101465f5481565b604051908152602001610115565b6101467f000000000000000000000000000000000000000000000000000000000000000481565b61018e610189366004612572565b61040f565b60405161011591906125b9565b6101ae6101a9366004612621565b610447565b005b6001546101c3906001600160401b031681565b6040516001600160401b039091168152602001610115565b6101467f000000000000000000000000000000000000000000000000000000000000000281565b61018e610210366004612702565b6107d9565b610228610223366004612749565b6108b0565b6040519015158152602001610115565b6101ae610246366004612797565b6108bf565b6101467f000000000000000000000000000000000000000000000000000000000000001881565b6101ae6102803660046127ae565b610a37565b6102d3610293366004612797565b600a6020525f90815260409020805460018201546002909201546001600160401b0382169263ffffffff600160401b8404811693600160601b9004169185565b604080516001600160401b0396909616865263ffffffff948516602087015292909316918401919091526060830152608082015260a001610115565b6002805460035460408051600480546060602082028401810185529383018181526001600160801b0380881698600160801b9098041696948492849184018282801561037857602002820191905f5260205f20905b815481526020019060010190808311610364575b50505050508152602001600182015481525050905084565b6006805460075460408051600880546060602082028401810185529383018181526001600160801b0380881698600160801b9098041696948492849184018282801561037857602002820191905f5260205f20908154815260200190600101908083116103645750505050508152602001600182015481525050905084565b60608282101561043257604051635c85a0e760e01b815260040160405180910390fd5b61043d848484610ea1565b90505b9392505050565b5f6104518a610f2b565b8051906020012090505f61046e33835f9182526020526040902090565b905061047c818c8c8c61101d565b5f5f90505f6002905060065f015f9054906101000a90046001600160801b03166001600160801b03168d60200160208101906104b89190612843565b6001600160401b0316036104d2575060019050600661052c565b60025f015f9054906101000a90046001600160801b03166001600160801b03168d60200160208101906105059190612843565b6001600160401b03161461052c57604051636033c4fd60e11b815260040160405180910390fd5b61053b84848e8e858f8f61110c565b5f6105458e6112c2565b905082156106d657600654610564906001600160801b0316600161287d565b6001600160801b031661057d60808b0160608c01612843565b6001600160401b0316146105a3576040516263964160e91b815260040160405180910390fd5b5f6105c0826105b18c6113f4565b805190602001208b8b8b6114a8565b9050806105e05760405163128597bb60e01b815260040160405180910390fd5b60068054600160801b8082046001600160801b0390811690910291161760029081556007546003556008805460049061061c908290849061240d565b5060019182015491015550610639905060808b0160608c01612843565b600680546001600160801b0319166001600160401b039290921691909117905561066960a08b0160808c0161289c565b600680546001600160801b031663ffffffff92909216600160801b0291909117905560a08a0180356007556106b0906106a59060808d0161289c565b63ffffffff16611517565b805180516008916106c691839160200190612455565b5060208201518160010155905050505b5f8190556106e760208f018f61289c565b63ffffffff1660015f6101000a8154816001600160401b0302191690836001600160401b03160217905550600a5f8581526020019081526020015f205f5f82015f6101000a8154906001600160401b0302191690555f820160086101000a81549063ffffffff02191690555f8201600c6101000a81549063ffffffff0219169055600182015f9055600282015f905550507fd95fe1258d152dc91c81b09380498adc76ed36a6079bcb2ed31eff622ae2d0f1818f5f0160208101906107ac919061289c565b6040805192835263ffffffff90911660208301520160405180910390a15050505050505050505050505050565b60605f600a5f6107f233885f9182526020526040902090565b8152602001
|
|
|
|
|
"storage": {
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000002",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000007": "0x697ea2a8fe5b03468548a7a413424a6292ab44a82a6f5cc594c3fa7dda7ce402",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000003": "0x697ea2a8fe5b03468548a7a413424a6292ab44a82a6f5cc594c3fa7dda7ce402",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000200000000000000000000000000000000",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000002",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000200000000000000000000000000000001"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"45": {
|
|
|
|
|
"address": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
|
|
|
|
|
"code": "0x6080604052348015600e575f5ffd5b50600436106026575f3560e01c8063c298557814602a575b5f5ffd5b5f60405190815260200160405180910390f3fea26469706673582212204906941268839d569ecaf7e18f112ade90c540d0de5142ca9f7725e57df91e0964736f6c634300081c00330000000000000000",
|
|
|
|
|
"storage": {}
|
|
|
|
|
},
|
2026-01-22 12:48:27 +00:00
|
|
|
"21": {
|
|
|
|
|
"address": "0x0000F90827F1C53a10cb7A02335B175320002935",
|
|
|
|
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604657602036036042575f35600143038111604257611fff81430311604257611fff9006545f5260205ff35b5f5ffd5b5f35611fff60014303065500",
|
|
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000037": "0x7dba6cfd190cd676ceab572c0ea8a2de9f397df61f588974668e90e365110250",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000034": "0x8c4beb67b351b6f576899b2961e2e3f654a8701446181d5bb0c02bf691aac216",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003a": "0x3d3679da9629b4cbcf3faf9cd7ae517797ec91b7984eff0a4e3e2a5feec1a077",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000030": "0xd98073d4f2271bc16437511a4d4f43553358cb4faeabeaa326aa9e7fd2a343a8",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000004a": "0x50af6778675a6e30db0584111c11dccc9946048e4ef88a6794a138478fc0087d",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000024": "0xdbb108e107182aa903847566da4e97dea7c12849e41d711ff3015e7a9d7e25af",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000001d": "0xe519dc053717c8dc8dc205a65af318cdbb0e06a8a071f994e5a6bd1a1b3c825e",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000026": "0x9cdf7ab6a05c98761f73090b8f8674ed56fd9d53dc13a3e708204d8a4e87372d",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002a": "0x6c82fe27742545bd9ab2f22dbbd5dcf3bcaf06da76a88b567b4612b80c341684",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000001": "0xc2c67fb618e169cec3b5ecceb5de747ee01f36a775797dd92504163f1fa2eb1a",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000012": "0x7a21b4fb1f04fc9ee8ae2b9585f8c5248ee7adb73cad020920b34d72dcf86aa9",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000043": "0xdb64fa0b93af4865852cb32ada05816c70990f993d9565df3b806e15af7f1774",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000046": "0x4944a97eb3f2cef53621ac688fff89485c821677a6a000cb4c587c7a7cd80a30",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000020": "0xb2835abdfda964c75cb55670e70c963f945bd4ffe74453f8053d17108cc477fd",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000023": "0xa090d2b60842f14ec13240bd07bf4be2f6d3faac6c0e82d1b6e9e79c91f71ca7",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000048": "0x09cdc091ee3d28c27b1d81e24e200a415304990490f712280e7a9f5b7e528077",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000000a": "0x0c9f4bccf18f5fbe86e1891c3ea5a92f15dc928a7376dfce0aa3ed642d68af1c",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x94d0bab2834f8ad853c6d0fd6bca9a5019ff287f8607d9573cfbbaa44fa9132e",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000003": "0x508921c105d59853aa52ef7fe87433b1847a5d97d61535e3189abe8aaad908b2",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000028": "0x0327ac71308d01e45657fd4d8b343a2d6aeef00f80395f6511416274997cfcfb",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000031": "0xd10fc0bcc990f04c1a06a2b1e72bd617a020aa0d4dc89f5f98c21233a492d27a",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000004": "0x3cb864613b04eae08a873b64b3a67360f98c41ca76abf9d06bbab1e83c59a5f1",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000017": "0x3e7878505d2f5b0548009687f85e3e0491e8a193703cbffd103e9060de532e0d",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000018": "0x615a70fc83ca07e7b6fb4a9da05b734479fff08ddef45bf3dd0bbeae10410b36",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000025": "0x29030d8519c14cc30a1d3613e13a26354214da5cb8e2c750c95d2884cb17d86d",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000038": "0x15cef137d4c827121f1fbca673176fc376cad8582b90e695642b3fb913ae5e5f",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000000e": "0xd9952f05760fda1a4ca998fecf94b6a11c7a1e9ad5c10636e52b58f238948638",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000006": "0x1a4d3e4c00a8711d4b79df383d348de72fafd510cde2998cca273bb5e945634e",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000021": "0xfe1a914f738a66729c97f9a987f003733572a7032aacc5237ea73e5d1791be15",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000040": "0x872e3b28751def5dd02c04d2e37334aecd63ccdf73b529c5002608f179d81726",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000014": "0x1bebfec7364d7b14f77a125c75e06f6cb54998cc2344bcb5838e8f4ac34a799d",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000041": "0x282828ce280e5c594f5009f451d6b953dd91b234e9a371f2f5dec7d00661baf7",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000000d": "0x1c1b8f0803eeb1e1c9447df7b8c9e88817463c785e5462357fcebc7f61cc1a0c",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000001f": "0xdf915f928c9abcae4533730be221820ff4fe7f6d15364411eefc3b4cf5938d3c",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000036": "0x5237502c06660666a59cb0f6f943122ef30db0b39702d0e9b18cf75a67df705e",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000029": "0x62d466ab11e99482d3b48cb05959ca8068f8894abd45dce90b13c6a95105669f",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002b": "0xcbb14f647e27741b02ef0b47727affdd37883853eaf0a80960ed9fe2417d0155",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000011": "0xc206586970ef9cceb3ae4113133b749725d48af653dc3e32e9af6d51f1eb2a8c",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000001c": "0x247e36fad5af4cccc7207545c64b2298a49af78c7c5a01df85143a32b7be3f08",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000002": "0x7ad4f2b98894e6ba818e2d230abc7d7b8cbf85d936245a24b2a374f6a81b286f",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003d": "0x3da9512589d1256bc831a5beb801a7cc63c26b3870aaf0c191e488644d00eaf6",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000005": "0xe6bf887ab883f3817f530198a3738495cf7d121a8f2f62ee38c80fc783963b4d",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000015": "0xd4a299c088a928b0d78615b35e8b8d464fe3cd0924e1725a2549512915413888",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000022": "0xee5607c31047cd8a768e51e8ed47f2d4e00bbec79087a19fcce4122774bad68a",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003c": "0x34e05358e6d64f940d16692aae278df9fb79cd5b31b7ca6ed535c97b61c3f169",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000016": "0x459aa0106e3ca4cba1215c6e8683b5a567bdf5c99ec02e4452044c8a115e7a00",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002f": "0x07e19ac1142916f7b63663fdeb9401d54ab18eb8e7fb3204149b2a20a091b71d",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003f": "0x36a957fcb4cfb170e2e9cfce0c40bd287ea53e70b533319b1d086008df464717",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000000f": "0x1259338c2e8df334b092b9881f8ea7882b3a7c475d1979af0249c8c69ea28114",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000000c": "0x177dfa3cdf65903c0235fb12887725bcc4148ed51225be84db90e30ff36d7aaf",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000000b": "0x8e1841b9f4c6c6ea52f11ec7783a38eab6993840412f1e63773c3b168c8ee2a4",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000044": "0x41c10fdeffe6c9d73e9a769d02b02e2687efd05b4ed27ee30379437589fc7739",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002e": "0xe7365b9dcb1a93128cc1671627b2b8fb038bf002a5037066a55ce27c444cf0e4",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000001b": "0xfcd358887d6cead17a31275c7817f4be8ec2399670152736d8afab9f29857a01",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000042": "0x6a8b913bac58f095f9b55cdb2ae9e635686313b60c1a43b187aae0a2d07e0aaa",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000008": "0x890b339bb81e6d15de4e50b8abb87abd937eee6d83913a577c5e8eb73a185254",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000045": "0xc36a0aa304696f05f336fbc39393d93a6d0cc1cd0431ec9a3b09b2ace2fe4e1d",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000027": "0xa0c3168f121ede472d57a4e81a1a8e73c9199affdaaa8ec83797b0ca9e65a84a",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000019": "0x01e3a46edccdf8e4fa7ba377876c2caa4e7f20e357a7cd69802c90b0f64cd81c",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003b": "0xd98147582c214dceef19d46c0658b3b05d326254c0ef38aa875594495756b8ea",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000035": "0xb7b970a400b2c4c7f3322a9573369b865c272b6da5348cb0e032e434b33c06bd",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000010": "0x2e461dcac54d9f4f52ba077f666a5ddd431341514db0e9f369dbf5a9ae700546",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003e": "0x57530920cd762202e8ee8e2016744727f97449998791effbe34ca75314899fb7",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000007": "0xa64333f38cf6f05bf76e867e663294e79156582d738eff8997eaa7b092edead1",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000013": "0xc08e55cd55f98b08478d00b19d0fdb5aa012f2ef0bb37db6bace5143a65a4b2e",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000033": "0xbf2bc3d6b0df3ed1f839eb7050814edbbc865f4ff3543dda811bf71ea59e41ec",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000039": "0xf306e8539937696cdc87c607ed45127cba87fb213a4b0c620506d16908a03e0d",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000001a": "0x30bc181b20c968c2ea5c4b97b241f0035b237c019218eb8ca93486a439c483ba",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000009": "0xa94e1c9553391106e061daab33fcb441afa04f603106d943475777270ccfa64e",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000001e": "0xa0fc11bb768bcb3b45c699aee78a664e69b3857627b3b1a342ea80f14efb57ab",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002d": "0xa7aaf5a2b8a2feab05e51df7035f2eb5d8e32ec6f16c0086a35854e25df98670",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000047": "0xd20fca41a076819db29bd1ab62bb5489070d0656896cca9069ba181962219a87",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000049": "0x1df27bb7e07a1aad2084ccb75255169ca7d1a3e6737d0308412cb860f538192b",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000032": "0x672b80852a0a8f09cc2c2d3c9f40c1c48b88b897fff3f63bd2adc934502a92cf",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002c": "0xcc56a05b1bc445067c57c06caea96b020b02d035a9702dbfcd6a0a078be87e92"
|
2026-01-22 12:48:27 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"37": {
|
|
|
|
|
"address": "0xac06641381166cf085281c45292147f833C622d7",
|
|
|
|
|
"code": "0x608060405260043610610036575f3560e01c8063338c5371146100415780639bb66b2814610091578063e905182a146100be575f5ffd5b3661003d57005b5f5ffd5b34801561004c575f5ffd5b506100747f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f8168881565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561009c575f5ffd5b506100b06100ab3660046101ae565b6100ff565b604051610088929190610239565b3480156100c9575f5ffd5b506100f17f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610088565b5f6060336001600160a01b037f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f81688161461014a576040516282b42960e81b815260040160405180910390fd5b846001600160a01b03168484604051610164929190610277565b5f60405180830381855af49150503d805f811461019c576040519150601f19603f3d011682016040523d82523d5f602084013e6101a1565b606091505b5091509150935093915050565b5f5f5f604084860312156101c0575f5ffd5b83356001600160a01b03811681146101d6575f5ffd5b9250602084013567ffffffffffffffff8111156101f1575f5ffd5b8401601f81018613610201575f5ffd5b803567ffffffffffffffff811115610217575f5ffd5b866020828401011115610228575f5ffd5b939660209190910195509293505050565b8215158152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b818382375f910190815291905056fea26469706673582212208fe760f358faedf4a90fd4b23c39c8397def11c5b035ea1406af976ecc426bbf64736f6c634300081c00330000000000",
|
|
|
|
|
"storage": {}
|
|
|
|
|
},
|
|
|
|
|
"47": {
|
|
|
|
|
"address": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c806346fbf68e1461004e5780638568520614610085578063ce5484281461009a578063eab66d7a146100ad575b5f5ffd5b61007061005c36600461027a565b5f6020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b61009861009336600461029a565b6100d8565b005b6100986100a836600461027a565b610111565b6001546100c0906001600160a01b031681565b6040516001600160a01b03909116815260200161007c565b6001546001600160a01b031633146101035760405163794821ff60e01b815260040160405180910390fd5b61010d8282610148565b5050565b6001546001600160a01b0316331461013c5760405163794821ff60e01b815260040160405180910390fd5b610145816101cf565b50565b6001600160a01b03821661016f576040516339b190bb60e11b815260040160405180910390fd5b6001600160a01b0382165f8181526020818152604091829020805460ff19168515159081179091558251938452908301527f65d3a1fd4c13f05cba164f80d03ce90fb4b5e21946bfc3ab7dbd434c2d0b9152910160405180910390a15050565b6001600160a01b0381166101f6576040516339b190bb60e11b815260040160405180910390fd5b600154604080516001600160a01b03928316815291831660208301527f06b4167a2528887a1e97a366eefe8549bfbf1ea3e6ac81cb2564a934d20e8892910160405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160a01b0381168114610275575f5ffd5b919050565b5f6020828403121561028a575f5ffd5b6102938261025f565b9392505050565b5f5f604083850312156102ab575f5ffd5b6102b48361025f565b9150602083013580151581146102c8575f5ffd5b80915050925092905056fea2646970667358221220d968f6e7b0fa23955f1f9580db081bbf816d7e99d0b3ab6d1bf5c644ea927f8d64736f6c634300081c003300",
|
|
|
|
|
"storage": {
|
|
|
|
|
"0x723077b8a1b173adc35e5f0e7e3662fd1208212cb629f9c128551ea7168da722": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc",
|
|
|
|
|
"0x14e04a66bf74771820a7400ff6cf065175b3d7eb25805a5bd1633b161af5d101": "0x0000000000000000000000000000000000000000000000000000000000000001"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"6": {
|
|
|
|
|
"address": "0x0165878A594ca255338adfa4d48449f69242Eb8F",
|
|
|
|
|
"code": "0x730165878a594ca255338adfa4d48449f69242eb8f3014608060405260043610610034575f3560e01c8063439fab9114610038575b5f5ffd5b818015610043575f5ffd5b50610057610052366004610683565b610059565b005b5f6100827f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001600160a01b0316036100a8576040516282b42960e81b815260040160405180910390fd5b7e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab5f6100d584840185610760565b8051835491925090839060ff1916600183818111156100f6576100f6610802565b02179055505f7f03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113145f1b60405161012b90610676565b908152602001604051809103905ff08015801561014a573d5f5f3e3d5ffd5b507f03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113145f908152600285016020908152604080832080546001600160a01b0319166001600160a01b0386169081179091558151608081018352848152808401859052808301859052606081019190915260018085528089019093529220825181549495509293909291839160ff19169083818111156101ea576101ea610802565b02179055506020828101518254604080860151610100600160881b031990921661010067ffffffffffffffff9485160267ffffffffffffffff60481b191617600160481b9390921692909202178355606093840151600193840180546001600160a01b0319166001600160a01b0392831617905581516080810183525f808252818501819052818401819052918716958101959095526002815287840190925290208251815491929091839160ff199091169083818111156102ae576102ae610802565b021790555060208201518154604080850151610100600160881b031990921661010067ffffffffffffffff9485160267ffffffffffffffff60481b191617600160481b9390921692909202178255606090920151600190910180546001600160a01b0319166001600160a01b03909216919091179055515f907f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b799061035290610676565b908152602001604051809103905ff080158015610371573d5f5f3e3d5ffd5b507f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b795f908152600286016020908152604080832080546001600160a01b0319166001600160a01b038616908117909155815160808101835284815280840185905280830185905260608101919091528151637061726160e01b81850152607d60e31b6024820152825180820360080181526028909101835280519084012084526001808a019093529220825181549495509293909291839160ff191690838181111561043f5761043f610802565b021790555060208201518154604084015167ffffffffffffffff908116600160481b0267ffffffffffffffff60481b19919093166101000216610100600160881b031990911617178155606090910151600190910180546001600160a01b039092166001600160a01b03199092169190911790555f6104db7f59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f690565b60408501518155602080860151600180840180546fffffffffffffffffffffffffffffffff19166001600160801b0393841617905560c08801516002909401939093557f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22f80546001600160a01b03969096166001600160c01b031990961695909517607d60a31b1790945560a08601517f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23155606086015160808701518516600160801b02908516177f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c2305560e08601517f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23380546101009889015190961690970270ffffffffffffffffffffffffffffffffff1990951660ff9091161793909317909455505f80527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e9052507f8510b5c501cdfc97210e26067e7b0bee5b5cd43d52d902454bc5e2b62167df1d805460ff19169091179055505050565b61032e8061081783390190565b5f5f60208385031215610694575f5ffd5b823567ffffffffffffffff8111156106aa575f5ffd5b8301601f810185136106ba575f5ffd5b803567ffffffffffffffff8111156106d0575f5ffd5b8560208284010111156106e1575f5ffd5b6020919091019590945092505050565b604051610120810167ffffffffffffffff8111828210171561072157634e487b7160e01b5f52604160045260245ffd5b60405290565b803560028110610735575f5ffd5b919050565b80356001600160801b0381168114610735575f5ffd5b803560ff81168114610735575f5ffd5b5f610120828403128015610772575f5ffd5b5061077b6106f1565b61078483610727565b81526107926020840161073a565b6020820152604083810135908201526107ad6060840161073a565b60608201526107be6080840161073a565b608082015260a0838101359082015260c080840135908201526107e360e08401610750565b60e08201526107f5610100840161073a565b6101
|
|
|
|
|
"storage": {}
|
|
|
|
|
},
|
|
|
|
|
"20": {
|
|
|
|
|
"address": "0x00000000219ab540356cBB839Cbe05303d7705Fa",
|
|
|
|
|
"code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101
|
|
|
|
|
"storage": {
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"44": {
|
|
|
|
|
"address": "0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf",
|
|
|
|
|
"code": "0x60806040526004361061021d575f3560e01c8063805ce31d1161011e578063b39053c5116100a8578063d58a8be41161006d578063d58a8be4146106cb578063df4ed829146106de578063f2e500b2146106fd578063f906d30914610710578063fe61cc491461072f575f5ffd5b8063b39053c5146105f9578063be8d42c014610618578063c536218f1461066e578063c66414c51461068d578063c9bd1e5b146106ac575f5ffd5b806390ffc4f9116100ee57806390ffc4f914610561578063928bc49d14610594578063988062ea146105b357806398ea5fca146105d2578063b0a23d44146105da575f5ffd5b8063805ce31d146104d55780638450a97c146104f7578063860929ee146105165780638ce2e33914610542575f5ffd5b80633ae65d7e116101aa57806346cd27511161016f57806346cd27511461045157806352054834146104705780635c60da1b146104835780635e6dae26146104975780636a64d9fb146104b6575f5ffd5b80633ae65d7e1461038a5780633f8bb4d9146103a9578063423e69b6146103c857806342e3ccfa14610413578063439fab9114610432575f5ffd5b806327c1d325116101f057806327c1d325146102cb5780632a6c3229146102ea5780632dd677b1146103295780632fb8ac581461034857806338004f6914610367575f5ffd5b80630705f4651461022157806309824a80146102565780630b6176461461026b57806326aa101f1461029c575b5f5ffd5b34801561022c575f5ffd5b5061024061023b3660046129ee565b61074e565b60405161024d9190612a19565b60405180910390f35b610269610264366004612a47565b6107c8565b005b348015610276575f5ffd5b5061027f610843565b604080519283526001600160801b0390911660208301520161024d565b3480156102a7575f5ffd5b506102bb6102b6366004612a47565b6108b7565b604051901515815260200161024d565b3480156102d6575f5ffd5b506102696102e5366004612aa6565b610933565b3480156102f5575f5ffd5b506103096103043660046129ee565b6109bb565b604080516001600160401b0393841681529290911660208301520161024d565b348015610334575f5ffd5b50610269610343366004612aa6565b610a39565b348015610353575f5ffd5b50610269610362366004612ae4565b610a91565b348015610372575f5ffd5b505f516020613ae35f395f51905f525460ff16610240565b348015610395575f5ffd5b506102696103a4366004612aa6565b610b3e565b3480156103b4575f5ffd5b506102696103c3366004612aa6565b610bb8565b3480156103d3575f5ffd5b506103fb7f0000000000000000000000000e801d84fa97b50751dbf25036d067dcf18858bf81565b6040516001600160a01b03909116815260200161024d565b34801561041e575f5ffd5b5061026961042d366004612aa6565b610c10565b34801561043d575f5ffd5b5061026961044c366004612aa6565b610c68565b34801561045c575f5ffd5b5061026961046b366004612aa6565b610ca1565b61026961047e366004612b50565b610d1b565b34801561048e575f5ffd5b506103fb610da1565b3480156104a2575f5ffd5b506103fb6104b13660046129ee565b610dcf565b3480156104c1575f5ffd5b506102696104d0366004612ae4565b610dd9565b3480156104e0575f5ffd5b506104e9610e33565b60405190815260200161024d565b348015610502575f5ffd5b50610269610511366004612aa6565b610e9f565b348015610521575f5ffd5b5061052a610f19565b6040516001600160401b03909116815260200161024d565b34801561054d575f5ffd5b5061026961055c366004612c2f565b610f85565b34801561056c575f5ffd5b506103fb7f00000000000000000000000099bba657f2bbc93c02d617f8ba121cb8fc104acf81565b34801561059f575f5ffd5b506104e96105ae366004612ccb565b6110fd565b3480156105be575f5ffd5b506102696105cd366004612aa6565b61119c565b6102696111f4565b3480156105e5575f5ffd5b506102696105f4366004612aa6565b61122e565b348015610604575f5ffd5b506102696106133660046129ee565b611286565b348015610623575f5ffd5b506104e9610632366004612a47565b6001600160a01b03165f9081527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e602052604090206001015490565b348015610679575f5ffd5b50610269610688366004612aa6565b6112e8565b348015610698575f5ffd5b506102bb6106a7366004612d32565b611340565b3480156106b7575f5ffd5b506102696106c6366004612aa6565b611389565b6102696106d9366004612d5b565b6113e1565b3480156106e9575f5ffd5b506102696106f8366004612db4565b611438565b61026961070b366004612e3f565b61191f565b34801561071b575f5ffd5b5061026961072a366004612aa6565b6119ac565b34801561073a575f5ffd5b506103fb6107493660046129ee565b611a04565b604051630705f46560e01b8152600481018290525f9073e7f1725e7734ce288f8367e1bb143e90bb3f051290630705f46590602401602060405180830381865af415801561079e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107c29190612f00565b92915050565b5f5c156107d3575f5ffd5b60015f5d6040516213049560e71b81526001600160a01b038216600482015273e7f1725e
|
|
|
|
|
"storage": {}
|
|
|
|
|
},
|
|
|
|
|
"11": {
|
|
|
|
|
"address": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
|
|
|
|
|
"code": "0x739fe46736679d2d9a65f0992f2272de9f3c7fa6e03014608060405260043610610055575f3560e01c80634a283cd91461005957806376b1d08f1461007a578063fd10ebe514610099578063fe65a388146100d2575b5f5ffd5b818015610064575f5ffd5b50610078610073366004610aed565b6100f1565b005b610082600881565b60405160ff90911681526020015b60405180910390f35b7e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96b0546040516001600160401b039091168152602001610090565b8180156100dd575f5ffd5b506100786100ec366004610b67565b610202565b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ad60205260409020547e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab906001600160a01b0316806101e4578260405161015990610ae0565b908152602001604051809103905ff080158015610178573d5f5f3e3d5ffd5b505f84815260028401602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251878152918201529192507f7c96960a1ebd8cc753b10836ea25bd7c9c4f8cd43590db1e8b3648cb0ec4cc89910160405180910390a1505050565b604051630d82532d60e21b815260040160405180910390fd5b505050565b61028d336102448a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061029792505050565b61024e888a610c98565b87878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508992508891506102bf9050565b5050505050505050565b6040805180820182525f80825260606020928301528251808401909352825281019190915290565b6102c761056c565b6001600160801b033411156102ef576040516330e972ad60e01b815260040160405180910390fd5b6102f98183610d8e565b6001600160801b03163410156103225760405163044044a560e21b815260040160405180910390fd5b5f61034c7f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b796105c5565b90506103616001600160a01b0382163461061d565b8451600810156103845760405163df8153c760e01b815260040160405180910390fd5b5f85516001600160401b0381111561039e5761039e610c54565b6040519080825280602002602001820160405280156103e357816020015b604080518082019091525f8152606060208201528152602001906001900390816103bc5790505b5090505f5b86518110156104385761041387828151811061040657610406610dad565b6020026020010151610646565b82828151811061042557610425610dad565b60209081029190910101526001016103e8565b507e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96b0547e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab9061048f906001600160401b03166001610dc1565b816005015f6101000a8154816001600160401b0302191690836001600160401b031602179055505f6040518060e001604052808b6001600160a01b031681526020018481526020018a81526020018881526020018688346104f09190610de0565b6104fa9190610de0565b6001600160801b03908116825288811660208301528716604091820152600584015490519192507f550e2067494b1736ea5573f2d19cdc0ac95b410fff161bf16f11c6229655ec9c91610558916001600160401b0316908490610e56565b60405180910390a150505050505050505050565b7e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab80545f9060ff1660018111156105a4576105a4610f6b565b146105c257604051633ac4266d60e11b815260040160405180910390fd5b50565b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ad60205260409020546001600160a01b0316806106185760405163d3227c9b60e01b815260040160405180910390fd5b919050565b5f5f5f5f5f85875af19050806101fd57604051633d2cec6f60e21b815260040160405180910390fd5b604080518082019091525f815260606020820152602082015160ff165f819003610698575f5f848060200190518101906106809190610f7f565b925092505061068f82826106b1565b95945050505050565b604051636448d6e960e11b815260040160405180910390fd5b604080518082019091525f8152606060208201525f7f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e6001600160a01b0385165f90815260208290526040902080549192509060ff166107245760405163259ba1ad60e01b815260040160405180910390fd5b5f846001600160801b03161161074d5760405163162908e360e11b815260040160405180910390fd5b6001810154610783576001820154610770906001600160a01b0316863387610821565b61077a858561089d565b9250505061081b565b61078c81610919565b1561080257604051632770a7eb60e21b81523360048201526001600160801b03851660248201526001600160a01b03861690639dc29fac906044015f604051808303815f87803b1580156107de575f5ffd5b505af11580156107f0573d5f5f3e3d5ffd5b5050505061077a
|
|
|
|
|
"storage": {}
|
|
|
|
|
},
|
|
|
|
|
"30": {
|
|
|
|
|
"address": "0x809d550fca64d94Bd9F66E60752A544199cfAC3D",
|
2026-01-22 12:48:27 +00:00
|
|
|
"code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c657665
|
|
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000067": "0x0000000000000000000000009d4454b023096f34b160d6b654540c56a1f81688",
|
2026-01-22 12:48:27 +00:00
|
|
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788",
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000036c02da8a0983159322a80ffe9f24b1acff8b570",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000976ea74026e726554db657fa54763abd0c3a0aa9",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000014dc79964da2c08b23698b3d3cc7ca32193d9955",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"23": {
|
|
|
|
|
"address": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
|
|
|
|
|
"code": "0x6080604052600436106101f1575f3560e01c8063886f119511610108578063a6a509be1161009d578063f2fde38b1161006d578063f2fde38b1461062e578063f5d4fed31461064d578063f6848d2414610662578063fabc1cbc1461069b578063fe243a17146106ba575f5ffd5b8063a6a509be1461059c578063cd6dc687146105b1578063d48e8894146105d0578063ea4d3c9b146105fb575f5ffd5b80639ba06275116100d85780639ba062751461050b578063a1ca780b1461053f578063a38406a31461055e578063a3d75e091461057d575f5ffd5b8063886f1195146104815780638da5cb5b146104b45780639104c319146104d15780639b4e4634146104f8575f5ffd5b8063595c6a67116101895780635c975abb116101595780635c975abb146103e9578063715018a614610407578063724af4231461041b57806374cdd7981461043a57806384d810621461046d575f5ffd5b8063595c6a6714610358578063595edbcb1461036c5780635a26fbf41461038b5780635ac86ab7146103aa575f5ffd5b80632eae418c116101c45780632eae418c146102c55780633fb99ca5146102e457806350ff72251461030357806354fd4d5014610337575f5ffd5b80630d1e9de1146101f5578063136439dd146102165780632704351a14610235578063292b7b2b1461027a575b5f5ffd5b348015610200575f5ffd5b5061021461020f366004611d7e565b6106d9565b005b348015610221575f5ffd5b50610214610230366004611d99565b610736565b348015610240575f5ffd5b50609f5461025c90600160a01b900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b348015610285575f5ffd5b506102ad7f0000000000000000000000004ed7c70f96b99c776995fb64377f0d4ab3b0e1c181565b6040516001600160a01b039091168152602001610271565b3480156102d0575f5ffd5b506102146102df366004611db0565b610770565b3480156102ef575f5ffd5b506102146102fe366004611dfe565b6109c9565b34801561030e575f5ffd5b5061032261031d366004611e48565b610a6d565b60408051928352602083019190915201610271565b348015610342575f5ffd5b5061034b610b1d565b6040516102719190611e86565b348015610363575f5ffd5b50610214610b4d565b348015610377575f5ffd5b50609f546102ad906001600160a01b031681565b348015610396575f5ffd5b506102146103a5366004611ebb565b610b61565b3480156103b5575f5ffd5b506103d96103c4366004611ee2565b606654600160ff9092169190911b9081161490565b6040519015158152602001610271565b3480156103f4575f5ffd5b506066545b604051908152602001610271565b348015610412575f5ffd5b50610214610be8565b348015610426575f5ffd5b506103f9610435366004611e48565b610bf9565b348015610445575f5ffd5b506102ad7f000000000000000000000000c7f2cf4845c6db0e1a1e91ed41bcd0fcc1b0e14181565b348015610478575f5ffd5b506102ad610d3e565b34801561048c575f5ffd5b506102ad7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b3480156104bf575f5ffd5b506033546001600160a01b03166102ad565b3480156104dc575f5ffd5b506102ad73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac081565b610214610506366004611f40565b610da1565b348015610516575f5ffd5b506102ad610525366004611d7e565b60986020525f90815260409020546001600160a01b031681565b34801561054a575f5ffd5b50610214610559366004611fb3565b610e52565b348015610569575f5ffd5b506102ad610578366004611d7e565b611073565b348015610588575f5ffd5b5061025c610597366004611d7e565b611144565b3480156105a7575f5ffd5b506103f960995481565b3480156105bc575f5ffd5b506102146105cb366004611fe5565b6111a4565b3480156105db575f5ffd5b506103f96105ea366004611d7e565b609b6020525f908152604090205481565b348015610606575f5ffd5b506102ad7f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8281565b348015610639575f5ffd5b50610214610648366004611d7e565b6112c0565b348015610658575f5ffd5b506103f9609e5481565b34801561066d575f5ffd5b506103d961067c366004611d7e565b6001600160a01b039081165f9081526098602052604090205416151590565b3480156106a6575f5ffd5b506102146106b5366004611d99565b611339565b3480156106c5575f5ffd5b506103f96106d436600461200f565b6113a6565b6106e1611426565b609f80546001600160a01b0319166001600160a01b0383169081179091556040519081527f7025c71a9fe60d709e71b377dc5f7c72c3e1d8539f8022574254e736ceca01e5906020015b60405180910390a150565b61073e611480565b60665481811681146107635760405163c61dca5d60e01b815260040160405180910390fd5b61076c82611523565b5050565b336001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8216146107b95760405163f739589b60e01b815260040160405180910390fd5b6107c1611560565b6001600160a01b03831673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0146107fe57604051632711b74d60e11b81526004016040
|
|
|
|
|
"storage": {
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
2026-01-22 12:48:27 +00:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"35": {
|
2026-01-20 10:32:32 +00:00
|
|
|
"address": "0x9d4454B023096f34B160D6B654540c56A1F81688",
|
|
|
|
|
"code": "0x608060405260043610610021575f3560e01c8063439fab911461008a5761003f565b3661003f5760405163858d70bd60e01b815260040160405180910390fd5b5f6100687f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050365f5f375f5f365f845af43d5f5f3e808015610084573d5ff35b3d5ffd5b005b348015610095575f5ffd5b506100886100a43660046100bc565b6040516282b42960e81b815260040160405180910390fd5b5f5f602083850312156100cd575f5ffd5b823567ffffffffffffffff8111156100e3575f5ffd5b8301601f810185136100f3575f5ffd5b803567ffffffffffffffff811115610109575f5ffd5b85602082840101111561011a575f5ffd5b602091909101959094509250505056fea264697066735822122042eb79be1c5c1bf83d453ef1bcf09a68daefc0a952ec517c315a6e1a8ca586e264736f6c634300081c003300",
|
2026-01-13 14:03:10 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x24c230e7f96dea56c14d16c737ac85f999d444fd74b5f3f00170ca4640c77b8f": "0x000000000000000000000000beaafda2e17fc95e69dc06878039d274e0d2b21a",
|
|
|
|
|
"0x8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22f": "0x0000000000000000000003e8df077f5f72071df6e8b0a78071e496ba17b5ee0c",
|
2026-01-20 10:32:32 +00:00
|
|
|
"0x626b8e6b0a06114fed7a662a5b224ce123b32b155eef2616324caf5d9adeb4fa": "0x000000000000000000000000beaafda2e17fc95e69dc06878039d274e0d2b21a",
|
2026-01-22 12:48:27 +00:00
|
|
|
"0x8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c233": "0x0000000000000000000000000000000000000000000000000000000000000112",
|
2026-01-20 10:32:32 +00:00
|
|
|
"0x91839d9989408fbab863f2059ae80fee5216f58ec04fa3bffb021275bf7d4f24": "0x000000000000000000000000df077f5f72071df6e8b0a78071e496ba17b5ee0c",
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x173ec3ea915b0ecad49b752ec145e745446de67d464520dc696504b3980fccda": "0x000000000000000000000000ac06641381166cf085281c45292147f833c622d7",
|
|
|
|
|
"0x59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f7": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x8510b5c501cdfc97210e26067e7b0bee5b5cd43d52d902454bc5e2b62167df1d": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000008f86403a4de0bb5791fa46b8e795c547942fe4cf",
|
|
|
|
|
"0x8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c231": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
2026-01-22 12:48:27 +00:00
|
|
|
"0x8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c230": "0x0000000000000000000000000000000100000000000000000000000000000001",
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f8": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f6": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x6bd2118f0148c813209325d23233ce0b7f1042ab160c97a1c605fdedff377204": "0x000000000000000000000000df077f5f72071df6e8b0a78071e496ba17b5ee0c",
|
|
|
|
|
"0xdf92d0c198eb2c08351629e12172b863967bc505b5d2fa9fdf58f7b97e45495f": "0x000000000000000000000000beaafda2e17fc95e69dc06878039d274e0d2b21a"
|
2026-01-13 14:03:10 +00:00
|
|
|
}
|
2026-01-06 11:27:50 +00:00
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0": {
|
|
|
|
|
"address": "0x00000961Ef480Eb55e80D19ad83579A64c007002",
|
|
|
|
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460cb5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f457600182026001905f5b5f82111560685781019083028483029004916001019190604d565b909390049250505036603814608857366101f457346101f4575f5260205ff35b34106101f457600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160df575060105b5f5b8181146101835782810160030260040181604c02815460601b8152601401816001015481526020019060020154807fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252906010019060401c908160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160e1565b910180921461019557906002556101a0565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101cd57505f5b6001546002828201116101e25750505f6101e8565b01600290035b5f555f600155604c025ff35b5f5ffd00",
|
2026-01-12 15:55:46 +00:00
|
|
|
"storage": {}
|
|
|
|
|
},
|
2026-01-20 10:32:32 +00:00
|
|
|
"42": {
|
|
|
|
|
"address": "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b5060043610610148575f3560e01c80637a8b2637116100bf578063ce7c2ac211610079578063ce7c2ac2146102d7578063d9caed12146102ea578063e3dae51c146102fd578063f3e7387514610310578063fabc1cbc14610323578063fdc371ce14610336575f5ffd5b80637a8b26371461025c578063886f11951461026f5780638c871019146102965780638f6a6240146102a9578063ab5921e1146102bc578063c4d66de8146102c4575f5ffd5b8063485cc95511610110578063485cc955146101e257806354fd4d50146101f5578063553ca5f81461020a578063595c6a671461021d5780635ac86ab7146102255780635c975abb14610254575f5ffd5b8063136439dd1461014c5780632495a5991461016157806339b70e38146101915780633a98ef39146101b857806347e7ef24146101cf575b5f5ffd5b61015f61015a3660046111cb565b610349565b005b603254610174906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101747f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750881565b6101c160335481565b604051908152602001610188565b6101c16101dd3660046111f6565b610383565b61015f6101f0366004611220565b6104b2565b6101fd61059d565b6040516101889190611257565b6101c161021836600461128c565b6105cd565b61015f6105e0565b6102446102333660046112bc565b6001805460ff9092161b9081161490565b6040519015158152602001610188565b6001546101c1565b6101c161026a3660046111cb565b6105f4565b6101747f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6101c16102a43660046111cb565b61063d565b6101c16102b736600461128c565b610647565b6101fd610654565b61015f6102d236600461128c565b610674565b6101c16102e536600461128c565b61073a565b6101c16102f83660046112d7565b6107cc565b6101c161030b3660046111cb565b6108ce565b6101c161031e3660046111cb565b610905565b61015f6103313660046111cb565b61090f565b606454610174906001600160a01b031681565b61035161097c565b60015481811681146103765760405163c61dca5d60e01b815260040160405180910390fd5b61037f82610a1f565b5050565b5f5f61038e81610a5c565b336001600160a01b037f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750816146103d7576040516348da714f60e01b815260040160405180910390fd5b6103e18484610a92565b6033545f6103f16103e883611329565b90505f6103e86103ff610b4b565b6104099190611329565b90505f610416878361133c565b905080610423848961134f565b61042d9190611366565b9550855f0361044f57604051630c392ed360e11b815260040160405180910390fd5b6104598685611329565b60338190556f4b3b4ca85a86c47a098a223fffffffff101561048e57604051632f14e8a360e11b815260040160405180910390fd5b6104a7826103e86033546104a29190611329565b610bb5565b505050505092915050565b5f54610100900460ff16158080156104d057505f54600160ff909116105b806104e95750303b1580156104e957505f5460ff166001145b61050e5760405162461bcd60e51b815260040161050590611385565b60405180910390fd5b5f805460ff19166001179055801561052f575f805461ff0019166101001790555b606480546001600160a01b0319166001600160a01b03851617905561055382610c01565b8015610598575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60606105c87f76312e302e300000000000000000000000000000000000000000000000000006610d4c565b905090565b5f6105da61026a8361073a565b92915050565b6105e861097c565b6105f25f19610a1f565b565b5f5f6103e86033546106069190611329565b90505f6103e8610614610b4b565b61061e9190611329565b90508161062b858361134f565b6106359190611366565b949350505050565b5f6105da826108ce565b5f6105da61031e8361073a565b60606040518060800160405280604d8152602001611456604d9139905090565b5f54610100900460ff161580801561069257505f54600160ff909116105b806106ab5750303b1580156106ab57505f5460ff166001145b6106c75760405162461bcd60e51b815260040161050590611385565b5f805460ff1916600117905580156106e8575f805461ff0019166101001790555b6106f182610c01565b801561037f575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a15050565b60405163fe243a1760e01b81526001600160a01b0382811660048301523060248301525f917f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb6075089091169063fe243a1790604401602060405180830381865afa1580156107a8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105da91906113d3565b5f60016107d881610a5c565b336001600160a01b037f0000000000000000000000009a676e781a523b5d0c
|
2026-01-13 14:03:10 +00:00
|
|
|
"storage": {
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
|
|
|
|
}
|
feat: Implement EigenLayer Rewards V2 distribution (#351)
### Summary
This PR implements the EigenLayer Rewards Distribution V2 model for
DataHaven, replacing the previous merkle-root-based rewards registry
approach with EigenLayer's native `OperatorDirectedRewardsSubmission`
API. This enables direct integration with EigenLayer's
RewardsCoordinator for validator rewards distribution.
### Motivation
EigenLayer's V2 rewards model provides several advantages:
- **Direct integration**: Uses EigenLayer's native
`createOperatorDirectedOperatorSetRewardsSubmission` API
- **Per-operator rewards**: Distributes rewards proportionally to
individual operators based on their earned points
- **Simplified architecture**: Removes the need for a separate
RewardsRegistry contract
- **Better UX**: Operators receive rewards directly through EigenLayer's
established claiming mechanism
### Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ DataHaven Substrate │
├─────────────────────────────────────────────────────────────────┤
│ Era End │
│ │ │
│ ▼ │
│ external-validators-rewards pallet │
│ │ generate_era_rewards_utils() │
│ │ • Calculate individual points per validator │
│ │ • Compute total inflation amount │
│ │ │
│ ▼ │
│ RewardsSubmissionAdapter (runtime_common) │
│ │ build() → points_to_rewards() → encode_rewards_calldata() │
│ │ │
│ ▼ │
│ Snowbridge Outbound Queue │
│ │ CallContract(ServiceManager.submitRewards(...)) │
└────│────────────────────────────────────────────────────────────┘
│
▼ Cross-chain message via Snowbridge
┌─────────────────────────────────────────────────────────────────┐
│ Ethereum │
├─────────────────────────────────────────────────────────────────┤
│ DataHavenServiceManager │
│ │ submitRewards(OperatorDirectedRewardsSubmission) │
│ │ • Approve wHAVE tokens to RewardsCoordinator │
│ │ │
│ ▼ │
│ EigenLayer RewardsCoordinator │
│ │ createOperatorDirectedOperatorSetRewardsSubmission() │
│ │ │
│ ▼ │
│ Operators claim rewards via EigenLayer │
└─────────────────────────────────────────────────────────────────┘
```
### Changes Overview
#### Smart Contracts (`contracts/`)
**DataHavenServiceManager.sol**
- Added `submitRewards(OperatorDirectedRewardsSubmission)` function to
submit rewards to EigenLayer's RewardsCoordinator
- Implements `SafeERC20` for secure token approvals
- Uses `onlyRewardsInitiator` modifier for access control (Snowbridge
Agent)
- Emits `RewardsSubmitted` and `RewardsInitiatorSet` events for tracking
**IDataHavenServiceManager.sol**
- Added `submitRewards()` interface for EigenLayer rewards submission
- Added `setRewardsInitiator()` interface for configuring the authorized
caller
- Added new events: `RewardsSubmitted`, `RewardsInitiatorSet`
**New Test: RewardsSubmitter.t.sol**
- Comprehensive test suite covering:
- Access control (only rewards initiator can submit)
- Single and multiple operator rewards
- Multiple consecutive submissions
- Custom descriptions and different tokens
#### Substrate Runtime (`operator/`)
**New: `runtime/common/src/rewards_adapter.rs` (934 lines)**
A generic, configurable adapter for building EigenLayer rewards
messages:
- **`RewardsSubmissionConfig` trait**: Runtime-agnostic configuration
interface
- `OutboundQueue`: Snowbridge outbound queue type
- `rewards_duration()`: Reward period duration (typically 86400s)
- `whave_token_address()`: wHAVE ERC20 token on Ethereum
- `service_manager_address()`: ServiceManager contract address
- `rewards_agent_origin()`: Snowbridge agent origin
- **`RewardsSubmissionAdapter<C>`**: Generic implementation of
`SendMessage` trait
- **`points_to_rewards()`**: Converts validator points to token amounts
- Proportional distribution based on total points
- Returns remainder (dust) from integer division
- Arithmetic overflow/underflow protection
- **`encode_rewards_calldata()`**: ABI-encodes the `submitRewards` call
- Uses `alloy-core` for type-safe Solidity ABI encoding
- Validates `uint96` multiplier bounds
- **Comprehensive test suite** covering:
- Basic and edge-case reward calculations
- Remainder/dust handling
- Overflow/underflow protection
- ABI encoding round-trip verification
- Message building with various configurations
**Modified: `pallets/external-validators-rewards/`**
- **`types.rs`**: Extended `EraRewardsUtils` struct:
```rust
pub struct EraRewardsUtils {
pub era_index: u32, // NEW
pub rewards_merkle_root: H256,
pub leaves: Vec<H256>,
pub leaf_index: Option<u64>,
pub total_points: u128,
pub individual_points: Vec<(H160, u32)>, // NEW
pub inflation_amount: u128, // NEW
pub era_start_timestamp: u32 // NEW
}
```
- **`lib.rs`**: Updated `generate_era_rewards_utils()`:
- Now accepts `inflation_amount` parameter
- Extracts `individual_points` as `(H160, u32)` tuples for EigenLayer
- Returns `None` when `total_points` is zero (prevents inflation with no
distribution)
- **`mock.rs`**: Updated test mock to use `H160` as `AccountId`
(matching DataHaven's EVM-compatible account model)
**Modified: Runtime Configurations**
All three runtimes (mainnet, stagenet, testnet) updated:
1. **New runtime parameters** (`runtime_params.rs`):
- `ServiceManagerAddress`: DataHaven ServiceManager contract on Ethereum
- `WHAVETokenAddress`: wHAVE ERC20 token address
- `RewardsGenesisTimestamp`: EigenLayer-aligned genesis timestamp
- `RewardsDuration`: Rewards period (default: 86400 = 1 day)
2. **Refactored `RewardsSendAdapter`**:
- Replaced inline implementation with `RewardsSubmissionAdapter<Config>`
- Each runtime implements `RewardsSubmissionConfig` trait
- Cleaner, DRY configuration
## ⚠️ Breaking Changes ⚠️
- **Runtime Parameters**: New parameters must be configured via
governance before rewards submission will work:
- `ServiceManagerAddress` (replaces `RewardsRegistryAddress`)
- `WHAVETokenAddress`
- `RewardsGenesisTimestamp`
- **Contract Interface**: `submitRewards()` now accepts a full
`OperatorDirectedRewardsSubmission` struct instead of a merkle root
---------
Co-authored-by: Gonza Montiel <gonzamontiel@users.noreply.github.com>
2026-01-06 23:53:03 +00:00
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"46": {
|
|
|
|
|
"address": "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02",
|
|
|
|
|
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500",
|
2026-01-06 11:27:50 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000047d": "0x00000000000000000000000000000000000000000000000000000000697238d1",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002478": "0x33f4b7a22c274a253f8f047e28aa095a56cd6a25fc20519286f01d7152f92cac",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002479": "0x541fa6279d8389cb5710c10254e6d1161fa1764cf808266ae9760c247b1de184",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000461": "0x00000000000000000000000000000000000000000000000000000000697238b5",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000046f": "0x00000000000000000000000000000000000000000000000000000000697238c3",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000452": "0x00000000000000000000000000000000000000000000000000000000697238a6",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000488": "0x00000000000000000000000000000000000000000000000000000000697238dc",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002455": "0x78bb46a7cb61e6bdb34415590d3bec9407a926362a32f794b020948af31eec4b",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002487": "0xf98717faec1f38dc071ea8afde5cac7be731a7bbbfb5610c3d306105b58f7492",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002482": "0x37388147728cccc62f6c585fd5bd722e8d5579937f466782b716a335f2a04b5a",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000472": "0x00000000000000000000000000000000000000000000000000000000697238c6",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000464": "0x00000000000000000000000000000000000000000000000000000000697238b8",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000445": "0x0000000000000000000000000000000000000000000000000000000069723899",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000045a": "0x00000000000000000000000000000000000000000000000000000000697238ae",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000047b": "0x00000000000000000000000000000000000000000000000000000000697238cf",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002448": "0xbc6d08fab0741414058297acbf125161f2fdc3e5cb4b0e89d22a188e0c62d2bc",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002459": "0x928833d6bb105e2c08853e1399cada4682e4d311c5fa59df0217d934caab7022",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002469": "0x5cfddd9a87e0e4ec7bc6e94d00e5c5be95e656a711801aaf3c064e2a56a9fa11",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000486": "0x00000000000000000000000000000000000000000000000000000000697238da",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000244f": "0x180c3597be125112738bcedf70245e215065ef429e8050833554ed7cd2a38804",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000048c": "0x00000000000000000000000000000000000000000000000000000000697238e0",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000477": "0x00000000000000000000000000000000000000000000000000000000697238cb",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000456": "0x00000000000000000000000000000000000000000000000000000000697238aa",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000046c": "0x00000000000000000000000000000000000000000000000000000000697238c0",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002453": "0x66d4ea81c801cbd7fce5e6bdf29badadbae8960b164700a48974ca984f6fca28",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000246c": "0x0bfd9de6fab35b9664efe10d59fcea1a4b19f005627243935f6a52005759b3c1",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002474": "0x3a6c344872b8b6a315149265e28ab9b0ada9ea14b9c213ad25f43788a073760f",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002476": "0x6bf71b631c30d9491721b446104222470add3e9ecd9f6a761e0cc6f74ae697e3",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002481": "0x7781d8ec936c1d1c871b0552c5e39493bda7c6aec04c2ea85276a0075a2c1c23",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002472": "0x4fab78dc66e82a775d0f1e00e5730eb22c197abfb86fa74fac0c17a6ec884a10",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002471": "0x89fe746e22fbfc3e6e0fd28a16fdd025ec0a55e541c6cfb9ca4cf2e267ad36d2",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000449": "0x000000000000000000000000000000000000000000000000000000006972389d",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000467": "0x00000000000000000000000000000000000000000000000000000000697238bb",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000046d": "0x00000000000000000000000000000000000000000000000000000000697238c1",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000459": "0x00000000000000000000000000000000000000000000000000000000697238ad",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000480": "0x00000000000000000000000000000000000000000000000000000000697238d4",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000046a": "0x00000000000000000000000000000000000000000000000000000000697238be",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000246e": "0x37437855c2f7350a40a8d13cdd6997e2bc2fb5531b2ad11e3d878022bc6cc2ef",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000044b": "0x000000000000000000000000000000000000000000000000000000006972389f",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000247b": "0x62387a38188a4177d2d7954ff7dd6fa53bae25356db42cc561edb84eb2c87233",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002484": "0x964204cbfafddd69550dc66ffd8369d85247dd43ec77f913f5d941bfb1aef5a6",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000446": "0x000000000000000000000000000000000000000000000000000000006972389a",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000244d": "0x6b69c7e11c386d97a901d74d15173221785099d618a3bd905c4798591e2472a6",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000047e": "0x00000000000000000000000000000000000000000000000000000000697238d2",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000247e": "0x74eb6ef676ae8fc7c7fd21f7fc2308b496eb153a834e72c3f0890fb6bdf1027a",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002475": "0x4e0767b9e97c8b49bdd1cedeff3bacb70b9a1b0d5c008e746d8f6ca2bfe0b610",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002454": "0x6af7ccdca6c7c98a9279047724315c2a48be0f17f1c20c49296479f5d14aefbe",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000044f": "0x00000000000000000000000000000000000000000000000000000000697238a3",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000485": "0x00000000000000000000000000000000000000000000000000000000697238d9",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000045d": "0x00000000000000000000000000000000000000000000000000000000697238b1",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000046e": "0x00000000000000000000000000000000000000000000000000000000697238c2",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002449": "0x84d0222891c9e06c993a99d85ded6218fcdbc1c13c55a45e8d95851d119e4234",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000458": "0x00000000000000000000000000000000000000000000000000000000697238ac",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002457": "0x50eac8ce69fb0f0b0250d5e1690d50e928970394120694718f4bef7a5ea7ef71",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000248a": "0xd89df4ecf0e95207a664d1bec16a2e9277073f6f91a14ad8078de424e7bd8592",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000044c": "0x00000000000000000000000000000000000000000000000000000000697238a0",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000473": "0x00000000000000000000000000000000000000000000000000000000697238c7",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000455": "0x00000000000000000000000000000000000000000000000000000000697238a9",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002467": "0xbc4f7e3a7d645c90b7a096e84809e183195081de63d5d502d6bf6cc32d4eeb98",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000453": "0x00000000000000000000000000000000000000000000000000000000697238a7",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000245f": "0x361f87740b2f1b0ed2365dffa2c4f3f0eb12f5f66221cfd9aa3a568cd9abceb4",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002461": "0xf6a83841edf8fcb1e66e37743a2f869d60fe6c79f9787f0c84f68a225d0b11d4",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002444": "0x7c6c245445dbdff3e71cf089d2db408405f961c7e4d361e6570ca432cf6d55d7",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002486": "0xa201b506d37d418fdcd45dfd467c5476cdd5f96c09a1399511d48b3d4658474f",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000470": "0x00000000000000000000000000000000000000000000000000000000697238c4",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000248b": "0x2d890eaeeb3c19a7baeb9658df1db21f185a8fe4984771df4d4dd149ce6b64f9",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000045e": "0x00000000000000000000000000000000000000000000000000000000697238b2",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000247d": "0x975e0c76ac8bb18586d96588faf09997ef0a4bad33b7cf7d2a07615cbcb036d2",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000245c": "0xb24731b36d9fb45d3fd28f64bb879f2bdd27dcee352e35af2f59c2aecdfaea20",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000047f": "0x00000000000000000000000000000000000000000000000000000000697238d3",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000048a": "0x00000000000000000000000000000000000000000000000000000000697238de",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002447": "0x5fcdf63ed9ee4714d8d3b3370b4a5bd51ba0cddb4ceaad028008cc68a5c3bfe0",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000483": "0x00000000000000000000000000000000000000000000000000000000697238d7",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000044d": "0x00000000000000000000000000000000000000000000000000000000697238a1",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000245a": "0xccc53e889e3c202cf57575e55088445204e2ceebeab3987d768f831489a8e493",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000045f": "0x00000000000000000000000000000000000000000000000000000000697238b3",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000469": "0x00000000000000000000000000000000000000000000000000000000697238bd",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000244a": "0x23527ac268bd603cea37ad3ec137101dd9723dfb020e552ed86221773c947137",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000048f": "0x00000000000000000000000000000000000000000000000000000000697238e3",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002465": "0xd1c1d44101783386ccb22f699b186a5654be2f1c972688c03c8b0304a5442f42",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000247a": "0x9220ecb05dbc583364c680ac30fd504cd953b2cada6899b750b4430a5bcc6512",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000247c": "0x7d37f7705914d62e2de5f5c4ca5bbf599dbb885c225c6672466f05ee99c1fe12",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000451": "0x00000000000000000000000000000000000000000000000000000000697238a5",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000465": "0x00000000000000000000000000000000000000000000000000000000697238b9",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000244b": "0x8dc2ff3299d70c7408b8ba2bd6d72f18fba95038594bae40d704faeca438b76d",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002480": "0x78123ad8ce4dc49e0b9e5c1b998efed203276d16301231b1defe29d1c4f31409",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000487": "0x00000000000000000000000000000000000000000000000000000000697238db",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000245b": "0xf5fd7f142382a8b3036a73581409a1a81f4253976a2f45a262a4aef542b25682",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000463": "0x00000000000000000000000000000000000000000000000000000000697238b7",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000248c": "0x796c897719d317d104b3fe0e3dd718a16ccaac62a03fe792f06ab1860b020bcd",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000479": "0x00000000000000000000000000000000000000000000000000000000697238cd",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000482": "0x00000000000000000000000000000000000000000000000000000000697238d6",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002456": "0xf2329f0610d54dd62dad2ff6b2ce7e044c563f0330486248487b5649a8e57f32",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002450": "0x629f40464f808b00779cce29a20b44678ad27fbab164b52b3ce65f91c6991892",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002458": "0xe039f05481865865b1ed65b8afb07a1878e3e39841cd102fd7adc7b2d10f66a2",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000248d": "0x06a8c2d710b8466d9610c5390735fcd8cda2db8346ec894711ed34c2a44e3370",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000476": "0x00000000000000000000000000000000000000000000000000000000697238ca",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000048e": "0x00000000000000000000000000000000000000000000000000000000697238e2",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000248e": "0xe80b58c8fb6c38cee7e89906f5bc67db0c3d795ce038e20fa772838e0dfda9d9",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002452": "0x5ce6c063ba5a96a2bf7dc17a7e440256a030a76d31512d281f72f2e5fc12d212",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000245e": "0x8da6e81a5056bf532fc1b9359030ce3d92460ae7597a082499a857b25733d1c1",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000481": "0x00000000000000000000000000000000000000000000000000000000697238d5",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000474": "0x00000000000000000000000000000000000000000000000000000000697238c8",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002466": "0x5d9f43d718821f409ab035232280df2095ee3993eb0cd732051129a3a411e357",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002473": "0x1f0a9590c08c416f865a99aa629f215e81a309a9c9aba561417ad52e75cee459",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000447": "0x000000000000000000000000000000000000000000000000000000006972389b",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000246b": "0xe52553027455ae41c0df271964e3ed9620cab07cf058f391c42ad253128d9408",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000047c": "0x00000000000000000000000000000000000000000000000000000000697238d0",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000047a": "0x00000000000000000000000000000000000000000000000000000000697238ce",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000246a": "0xa4a069f58ddcd2f73c87dbfef895ba67c96701708c32924f4a6d567abc54ec19",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000460": "0x00000000000000000000000000000000000000000000000000000000697238b4",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000454": "0x00000000000000000000000000000000000000000000000000000000697238a8",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000247f": "0x4cc2003f4ae9925d2a0f1f58f9fbc34d75ee9d1b7e6271be78e4245e8405efa7",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002451": "0x5154642f458e86b9582eb0fd4aca5288cc0ea430a2e308314371da24755dd95f",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002489": "0x604959dff65a1deba1c3991c69ad92d426b51611b8ae98dc8b982968a598c82d",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000466": "0x00000000000000000000000000000000000000000000000000000000697238ba",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000045c": "0x00000000000000000000000000000000000000000000000000000000697238b0",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000468": "0x00000000000000000000000000000000000000000000000000000000697238bc",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000484": "0x00000000000000000000000000000000000000000000000000000000697238d8",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000462": "0x00000000000000000000000000000000000000000000000000000000697238b6",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000245d": "0x2a3a6a49c7046f8e971535952dd1b34f0cc33f367abfd57436a9ace6f750eba1",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002460": "0x06d272c823662455995135fa2bf92acd5ccc1f7b80373c4778d36b160e887d33",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002445": "0xfdab1d1c2672259525cd5a4526712c6c4cff3d874cbac051aee655524edda829",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000244e": "0xf8fd49a0aaf9939561aa4e3c7689c80f15c4106fd61eb3168f8ef2018b49a3e2",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002488": "0x7247670d4d2a5f80683ab9552c4d780b0dc746bda5d9a70206635391d24dd59e",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000044e": "0x00000000000000000000000000000000000000000000000000000000697238a2",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000244c": "0x89c81eba17ac01f4397bf7c932b0a1db58b2dcc4356f1c8e3bbf8a5b6e823104",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000044a": "0x000000000000000000000000000000000000000000000000000000006972389e",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002464": "0xefdbcaca82d4ad681a074d716113b0ea592ae0520b0d2cfdd0e819c4361d713f",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002485": "0x29c9375906d6d8f690b8bda099e31fc9428e27a290ba4dc471b9d271c8b7adbe",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000457": "0x00000000000000000000000000000000000000000000000000000000697238ab",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000475": "0x00000000000000000000000000000000000000000000000000000000697238c9",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000246f": "0xd9602aeb69c13b3752172f77bf144ca6d71bb21476bd90286d37c90a86239ae9",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000450": "0x00000000000000000000000000000000000000000000000000000000697238a4",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000471": "0x00000000000000000000000000000000000000000000000000000000697238c5",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002468": "0x39e3e27cf9df76ec404ce6929a4d49369c8e6e06e53d59d46697dca84b9723ba",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002477": "0x5ba2e6d3afa130be24ccb2ab8b259358c9f7cc6bb1ded34f30c2df041baa94a1",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000046b": "0x00000000000000000000000000000000000000000000000000000000697238bf",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002483": "0x695736708364ed76c3d8113c6d71e6db0ef9739a00187c59bb1c85bebf82e3fb",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000246d": "0x43d28cffdc7c4e712a02531e9a82788db2db25ae097eeb508eea647fbd66b8ac",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002463": "0x2a9e87d5c512b4eb9ab9b31b49e9ed2a138411c65f5b4332eb1f8218c338511b",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000489": "0x00000000000000000000000000000000000000000000000000000000697238dd",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000048d": "0x00000000000000000000000000000000000000000000000000000000697238e1",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002446": "0x1b0fb1d8777656036988eae201185a7e3bdd9e1d1ff66a83a28a1d3305e5d898",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002470": "0x7c1c09193652ccb5b8f78cddf7a93adfde3f1460f8a225e8e35b93f9db7fe624",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000045b": "0x00000000000000000000000000000000000000000000000000000000697238af",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000002462": "0x5cd583c165373a7f2989274fb0e2a067dc174c983406a7a81ff287ea7aaff99a",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000448": "0x000000000000000000000000000000000000000000000000000000006972389c",
|
|
|
|
|
"0x000000000000000000000000000000000000000000000000000000000000048b": "0x00000000000000000000000000000000000000000000000000000000697238df",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000478": "0x00000000000000000000000000000000000000000000000000000000697238cc"
|
2026-01-06 11:27:50 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"13": {
|
|
|
|
|
"address": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b5060043610610055575f3560e01c80633659cfe6146100595780635c60da1b1461006e578063715018a6146100975780638da5cb5b1461009f578063f2fde38b146100af575b5f5ffd5b61006c6100673660046102d7565b6100c2565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006c610109565b5f546001600160a01b031661007b565b61006c6100bd3660046102d7565b61011c565b6100ca61019a565b6100d3816101f3565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b61011161019a565b61011a5f610288565b565b61012461019a565b6001600160a01b03811661018e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61019781610288565b50565b5f546001600160a01b0316331461011a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610185565b6001600160a01b0381163b6102665760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b6064820152608401610185565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156102e7575f5ffd5b81356001600160a01b03811681146102fd575f5ffd5b939250505056fea2646970667358221220003d7f443094069cb023dc39fb36d6ba29922db6cd9b714ea95af972fc56405e64736f6c634300081c003300000000000000",
|
2026-01-06 11:27:50 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000059b670e9fa9d0a427751af201d676719a970857b",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65"
|
2026-01-06 11:27:50 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"14": {
|
|
|
|
|
"address": "0xBeaAFDA2E17fC95E69Dc06878039d274E0d2B21A",
|
|
|
|
|
"code": "0x608060405260043610610036575f3560e01c8063338c5371146100415780639bb66b2814610091578063e905182a146100be575f5ffd5b3661003d57005b5f5ffd5b34801561004c575f5ffd5b506100747f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f8168881565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561009c575f5ffd5b506100b06100ab3660046101ae565b6100ff565b604051610088929190610239565b3480156100c9575f5ffd5b506100f17f03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c11131481565b604051908152602001610088565b5f6060336001600160a01b037f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f81688161461014a576040516282b42960e81b815260040160405180910390fd5b846001600160a01b03168484604051610164929190610277565b5f60405180830381855af49150503d805f811461019c576040519150601f19603f3d011682016040523d82523d5f602084013e6101a1565b606091505b5091509150935093915050565b5f5f5f604084860312156101c0575f5ffd5b83356001600160a01b03811681146101d6575f5ffd5b9250602084013567ffffffffffffffff8111156101f1575f5ffd5b8401601f81018613610201575f5ffd5b803567ffffffffffffffff811115610217575f5ffd5b866020828401011115610228575f5ffd5b939660209190910195509293505050565b8215158152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b818382375f910190815291905056fea26469706673582212208fe760f358faedf4a90fd4b23c39c8397def11c5b035ea1406af976ecc426bbf64736f6c634300081c00330000000000",
|
2026-01-13 14:03:10 +00:00
|
|
|
"storage": {}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"12": {
|
|
|
|
|
"address": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
|
|
|
|
|
"code": "0x735fbdb2315678afecb367f032d93f642f64180aa33014608060405260043610610034575f3560e01c8063e5bad8da14610038575b5f5ffd5b61004b610046366004610256565b61005f565b604051901515815260200160405180910390f35b5f80610079610073368590038501856102fc565b85610104565b90506001600160a01b03851663a401662b8261009860c087018761039b565b8760e001356040518563ffffffff1660e01b81526004016100bc94939291906103e8565b602060405180830381865afa1580156100d7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100fb919061042c565b95945050505050565b81515f90819060f81b61013c8560200151600881811c62ff00ff1663ff00ff009290911b9190911617601081811c91901b1760e01b90565b85604001516101b287606001515f65ff000000ff00600883811b91821664ff000000ff9185901c91821617601090811b67ff000000ff0000009390931666ff000000ff00009290921691909117901c17602081811b6bffffffffffffffff000000001691901c63ffffffff161760c01b92915050565b6080880151600881811b63ff00ff001662ff00ff9290911c9190911617601081811b91901c1760e01b60a08901516040516001600160f81b031990961660208701526001600160e01b0319948516602187015260258601939093526001600160c01b0319909116604585015291909116604d83015260518201526071810184905260910160408051808303601f190181529190528051602090910120949350505050565b5f5f5f60608486031215610268575f5ffd5b83356001600160a01b038116811461027e575f5ffd5b925060208401359150604084013567ffffffffffffffff8111156102a0575f5ffd5b840161010081870312156102b2575f5ffd5b809150509250925092565b803560ff811681146102cd575f5ffd5b919050565b803563ffffffff811681146102cd575f5ffd5b803567ffffffffffffffff811681146102cd575f5ffd5b5f60c082840312801561030d575f5ffd5b5060405160c0810167ffffffffffffffff8111828210171561033d57634e487b7160e01b5f52604160045260245ffd5b604052610349836102bd565b8152610357602084016102d2565b602082015260408381013590820152610372606084016102e5565b6060820152610383608084016102d2565b608082015260a0928301359281019290925250919050565b5f5f8335601e198436030181126103b0575f5ffd5b83018035915067ffffffffffffffff8211156103ca575f5ffd5b6020019150600581901b36038213156103e1575f5ffd5b9250929050565b84815260606020820181905281018390525f6001600160fb1b0384111561040d575f5ffd5b8360051b80866080850137604083019390935250016080019392505050565b5f6020828403121561043c575f5ffd5b8151801515811461044b575f5ffd5b939250505056fea2646970667358221220202aa32fed9b1043addbc14e73c73106e521b4a0cbd4090b88a279664688a3ca64736f6c634300081c0033000000000000000000000000",
|
2026-01-20 10:32:32 +00:00
|
|
|
"storage": {}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"29": {
|
|
|
|
|
"address": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
|
|
|
|
|
"code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c657665
|
2026-01-06 11:27:50 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x38de7073e27519f272741044a68ab5a51022aa002af20801e32867226a9bb4bd": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x9254291d7d424716ad6728e8cf28d7329070cafa88280734e18f0a5f711cc416": "0x000000000000000000000000998abeb3e57409262ae5b751f60747921b33613e",
|
|
|
|
|
"0x288c6faa56b91953378099dc2014a331affa988ca357fe83ca55e72915585282": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x4bad58e84dc127f47e7265bd5e504be070126f63f93af282fe2a4f1acbb07707": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x165183f4d7a8ecead93a30c1491a78d70b212627d72d451cc2b61e9844bb6182": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000c5a5c42992decbae36851359345fe25997f5c42d",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x54ab5bc83c0127df10d352dbba9557880cef93f87419916bd513c73a26e9de39": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788"
|
2026-01-06 11:27:50 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"1": {
|
|
|
|
|
"address": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6",
|
|
|
|
|
"code": "0x732279b7a0a67db372996a5fab50d91eaa73d2ebe63014608060405260043610610034575f3560e01c8063a3499c7314610038575b5f5ffd5b818015610043575f5ffd5b50610057610052366004610230565b610059565b005b61006b836001600160a01b03166101b3565b610088576040516303777f6960e51b815260040160405180910390fd5b81836001600160a01b03163f146100b2576040516323e13ec960e21b815260040160405180910390fd5b6100da837f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b5f5f846001600160a01b0316836040516024016100f79190610309565b60408051601f198184030181529181526020820180516001600160e01b031663439fab9160e01b1790525161012c919061033e565b5f60405180830381855af49150503d805f8114610164576040519150601f19603f3d011682016040523d82523d5f602084013e610169565b606091505b509150915061017882826101fd565b506040516001600160a01b038616907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a25050505050565b5f6001600160a01b0382163f158015906101f757507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4706001600160a01b0383163f14155b92915050565b6060821561020c5750806101f7565b8151156100345781518083602001fd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610242575f5ffd5b83356001600160a01b0381168114610258575f5ffd5b925060208401359150604084013567ffffffffffffffff81111561027a575f5ffd5b8401601f8101861361028a575f5ffd5b803567ffffffffffffffff8111156102a4576102a461021c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156102d3576102d361021c565b6040528181528282016020018810156102ea575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f82518060208501845e5f92019182525091905056fea26469706673582212204f9eff25a489952d6ace57dae13f4311e26f51d13db35754950e1446aa6c4c3264736f6c634300081c003300",
|
2026-01-13 14:03:10 +00:00
|
|
|
"storage": {}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"2": {
|
|
|
|
|
"address": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b50600436106100e5575f3560e01c80639100674511610088578063ad8aca7711610063578063ad8aca77146101df578063df595cb8146101f2578063eb5a4e8714610205578063fddbdefd14610218575f5ffd5b80639100674514610196578063950d806e146101b9578063ad5f2210146101cc575f5ffd5b806354fd4d50116100c357806354fd4d5014610124578063628806ef146101425780636bddfa1f14610155578063882a3b3814610175575f5ffd5b806306641201146100e9578063268959e5146100fe5780634f906cf914610111575b5f5ffd5b6100fc6100f7366004610dbd565b61022b565b005b6100fc61010c366004610e0e565b61034c565b6100fc61011f366004610e0e565b610427565b61012c6104ca565b6040516101399190610e3f565b60405180910390f35b6100fc610150366004610e74565b6104fa565b610168610163366004610e74565b610588565b6040516101399190610ed0565b610188610183366004610e0e565b6105b1565b604051610139929190610ee2565b6101a96101a4366004610e0e565b610712565b6040519015158152602001610139565b6100fc6101c7366004610dbd565b610782565b6101686101da366004610e74565b610893565b6101a96101ed366004610e0e565b610939565b6101a9610200366004610dbd565b61095a565b6100fc610213366004610e0e565b6109af565b610168610226366004610f44565b610a7d565b836102368133610712565b61025357604051637bfa4b9f60e01b815260040160405180910390fd5b6001600160a01b0385165f908152600160205260408120906102758585610abb565b6001600160a01b0387165f908152600484016020526040902090915061029b9082610ae8565b6102b85760405163262118cd60e01b815260040160405180910390fd5b6001600160a01b0386165f90815260048301602052604090206102db9082610aff565b505f81815260058301602052604090206102f59087610b0a565b50856001600160a01b0316876001600160a01b03167f18242326b6b862126970679759169f01f646bd55ec5bfcab85ba9f337a74e0c6878760405161033b929190610f84565b60405180910390a350505050505050565b816103578133610712565b61037457604051637bfa4b9f60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526001602081905260409091206002019061039b82610b1e565b116103b9576040516310ce892b60e31b815260040160405180910390fd5b6103c38184610b0a565b6103e057604051630716d81b60e51b815260040160405180910390fd5b6040516001600160a01b0384811682528516907fdb9d5d31320daf5bc7181d565b6da4d12e30f0f4d5aa324a992426c14a1d19ce906020015b60405180910390a250505050565b816104328133610712565b61044f57604051637bfa4b9f60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526001602052604090206104708184610b0a565b61048d5760405163bed8295f60e01b815260040160405180910390fd5b6040516001600160a01b0384811682528516907fd706ed7ae044d795b49e54c9f519f663053951011985f663a862cd9ee72a9ac790602001610419565b60606104f57f76312e302e300000000000000000000000000000000000000000000000000006610b27565b905090565b6001600160a01b0381165f90815260016020526040902061051b8133610b0a565b6105385760405163bed8295f60e01b815260040160405180910390fd5b6105456002820133610b64565b506040513381526001600160a01b038316907fbf265e8326285a2747e33e54d5945f7111f2b5edb826eb8c08d4677779b3ff979060200160405180910390a25050565b6001600160a01b0381165f9081526001602052604090206060906105ab90610b78565b92915050565b6001600160a01b038083165f9081526001602090815260408083209385168352600490930190529081206060918291906105ea82610b1e565b90505f8167ffffffffffffffff81111561060657610606610fa7565b60405190808252806020026020018201604052801561062f578160200160208202803683370190505b5090505f8267ffffffffffffffff81111561064c5761064c610fa7565b604051908082528060200260200182016040528015610675578160200160208202803683370190505b5090505f5b83811015610704576106a861068f8683610b84565b606081901c9160a09190911b6001600160e01b03191690565b8483815181106106ba576106ba610fbb565b602002602001018484815181106106d3576106d3610fbb565b6001600160e01b0319909316602093840291909101909201919091526001600160a01b03909116905260010161067a565b509097909650945050505050565b6001600160a01b0382165f90815260016020526040812061073590600201610b1e565b5f0361075757816001600160a01b0316836001600160a01b03161490506105ab565b6001600160a01b0383165f90815260016020526040902061077b9060020183610b8f565b9392505050565b8361078d8133610712565b6107aa57604051637bfa4b9f60e01b815260040160405180910390fd5b6001600160a01b0385165f908152600160205260408120906107cc8585610abb565b6001600160a01b0387165f90815260048401602052604090209091506107f29082610ae8565b1561081057
|
2026-01-16 19:49:45 +00:00
|
|
|
"storage": {
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
|
|
|
|
}
|
2026-01-13 14:03:10 +00:00
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"22": {
|
|
|
|
|
"address": "0x95401dc811bb5740090279Ba06cfA8fcF6113778",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b50600436106100cb575f3560e01c806342966c681161008857806395d89b411161006357806395d89b41146101a7578063a457c2d7146101af578063a9059cbb146101c2578063dd62ed3e146101d5575f5ffd5b806342966c681461015757806370a082311461016c57806379cc679014610194575f5ffd5b806306fdde03146100cf578063095ea7b3146100ed57806318160ddd1461011057806323b872dd14610122578063313ce567146101355780633950935114610144575b5f5ffd5b6100d76101e8565b6040516100e49190610826565b60405180910390f35b6101006100fb366004610876565b610278565b60405190151581526020016100e4565b6002545b6040519081526020016100e4565b61010061013036600461089e565b610291565b604051601281526020016100e4565b610100610152366004610876565b6102b4565b61016a6101653660046108d8565b6102d5565b005b61011461017a3660046108ef565b6001600160a01b03165f9081526020819052604090205490565b61016a6101a2366004610876565b6102e2565b6100d76102fb565b6101006101bd366004610876565b61030a565b6101006101d0366004610876565b610389565b6101146101e336600461090f565b610396565b6060600380546101f790610940565b80601f016020809104026020016040519081016040528092919081815260200182805461022390610940565b801561026e5780601f106102455761010080835404028352916020019161026e565b820191905f5260205f20905b81548152906001019060200180831161025157829003601f168201915b5050505050905090565b5f336102858185856103c0565b60019150505b92915050565b5f3361029e8582856104e4565b6102a985858561055c565b506001949350505050565b5f336102858185856102c68383610396565b6102d09190610978565b6103c0565b6102df33826106fe565b50565b6102ed8233836104e4565b6102f782826106fe565b5050565b6060600480546101f790610940565b5f33816103178286610396565b90508381101561037c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a982868684036103c0565b5f3361028581858561055c565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104225760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610373565b6001600160a01b0382166104835760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610373565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b5f6104ef8484610396565b90505f19811461055657818110156105495760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610373565b61055684848484036103c0565b50505050565b6001600160a01b0383166105c05760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610373565b6001600160a01b0382166106225760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610373565b6001600160a01b0383165f90815260208190526040902054818110156106995760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610373565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610556565b6001600160a01b03821661075e5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610373565b6001600160a01b0382165f90815260208190526040902054818110156107d15760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610373565b6001600160a01b0383165f818152602081815260408083208686039055600280548790039055
|
refactor: cleanup old rewards model (#383)
## Summary
This PR removes the old merkle root-based rewards model and completes
the migration to EigenLayer Rewards V2 distribution. The old model
required operators to claim rewards by providing merkle proofs, while
the new model uses `submitRewards` to send rewards directly to
EigenLayer's `RewardsCoordinator`.
### Key Changes
- **Smart Contracts**: Removed `RewardsRegistry`,
`RewardsRegistryStorage`, `IRewardsRegistry`, and `SortedMerkleProof`
contracts along with all merkle claim functions from
`ServiceManagerBase`
- **Substrate Pallets**: Removed merkle proof generation from
`external-validators-rewards` pallet and deleted the entire
`runtime-api` crate (no longer needed)
- **Test Framework**: Removed all RewardsRegistry-related code from
deployment scripts, CLI handlers, and TypeScript bindings
- **Runtimes**: Cleaned up all three runtimes (testnet, stagenet,
mainnet) to remove runtime API implementations and unused imports
### Files Removed
**Contracts:**
- `contracts/src/middleware/RewardsRegistry.sol`
- `contracts/src/middleware/RewardsRegistryStorage.sol`
- `contracts/src/interfaces/IRewardsRegistry.sol`
- `contracts/src/libraries/SortedMerkleProof.sol`
- `contracts/test/RewardsRegistry.t.sol`
- `contracts/test/ServiceManagerRewardsRegistry.t.sol`
**Substrate:**
- `operator/pallets/external-validators-rewards/runtime-api/` (entire
crate)
**Test Framework:**
- `test/suites/rewards-message.test.ts`
### Files Modified
**Contracts:**
- `ServiceManagerBase.sol` - Removed merkle claim functions
- `ServiceManagerBaseStorage.sol` - Removed
`operatorSetToRewardsRegistry` mapping
- `IServiceManager.sol` - Removed interface members
**Substrate:**
- `external-validators-rewards` pallet - Removed merkle proof
generation, simplified `EraRewardsUtils` struct
- All runtime configs - Removed `ExternalValidatorsRewardsApi`
implementations
**Test Framework:**
- Updated deployment scripts, CLI handlers, relayer configs, and
TypeScript bindings
### Stats
```
50 files changed, 966 insertions(+), 4453 deletions(-)
```
## Test plan
- [x] All Rust tests pass (`cargo test`)
- [x] All contract tests pass (`forge test`)
- [x] TypeScript type checking passes (`bun typecheck`)
- [x] Contracts build successfully (`forge build`)
- [x] Operator builds successfully (`cargo build --release --features
fast-runtime`)
- [ ] E2E tests pass (`bun test:e2e`)
2026-01-09 14:25:49 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000d3c21bcecceda1000000",
|
|
|
|
|
"0xd19bcde47e0ffe1c643525c3cff070e266ec404a07f499b41fcbc480ff16fff7": "0x0000000000000000000000000000000000000000000069e10de76676d0800000",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000003": "0x54657374546f6b656e0000000000000000000000000000000000000000000012",
|
|
|
|
|
"0x14e04a66bf74771820a7400ff6cf065175b3d7eb25805a5bd1633b161af5d101": "0x0000000000000000000000000000000000000000000069e10de76676d0800000",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000004": "0x5445535400000000000000000000000000000000000000000000000000000008"
|
2026-01-06 11:27:50 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"7": {
|
|
|
|
|
"address": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
|
|
|
|
|
"code": "0x73a513e6e4b8f2a923d98304ec87f64353c4d5c853301460806040526004361061009b575f3560e01c806338412ce51161006e57806338412ce514610150578063480ff0651461016f5780636f378c061461018e578063957cae98146101ad578063c7f62387146101c0575f5ffd5b806319a79b481461009f5780631b8d43b0146100c057806320606b70146100f457806330adf81f14610129575b5f5ffd5b8180156100aa575f5ffd5b506100be6100b9366004610a4d565b6101df565b005b8180156100cb575f5ffd5b506100df6100da366004610acf565b610346565b60405190151581526020015b60405180910390f35b61011b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6040519081526020016100eb565b61011b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b81801561015b575f5ffd5b506100df61016a366004610b10565b61036b565b81801561017a575f5ffd5b506100be610189366004610b10565b610384565b818015610199575f5ffd5b506100df6101a8366004610b10565b6103cf565b61011b6101bb366004610b43565b6103dc565b8180156101cb575f5ffd5b506100be6101da366004610b10565b6103ec565b834211156102005760405163068568f360e21b815260040160405180910390fd5b5f61020a8961042d565b6001600160a01b0389165f90815260028c016020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928c928c928c9290919061025983610b6e565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e001604051602081830303815290604052805190602001206040516020016102d292919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090505f6102f7828686866104dc565b9050886001600160a01b0316816001600160a01b03161461032b57604051638baa579f60e01b815260040160405180910390fd5b6103398b8a8a8a6001610502565b5050505050505050505050565b5f610353858533856105f0565b506103608585858561067c565b506001949350505050565b5f61037a843385856001610502565b5060019392505050565b5f6001600160a01b0383166103bd57604051639cfea58360e01b81526001600160a01b0390911660048201526024015b60405180910390fd5b506103ca835f84846106f8565b505050565b5f61037a8433858561067c565b5f6103e68261042d565b92915050565b5f6001600160a01b038316610420576040516313053d9360e21b81526001600160a01b0390911660048201526024016103b4565b506103ca83835f846106f8565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8260405161045d9190610b86565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c001604051602081830303815290604052805190602001209050919050565b5f5f5f6104eb87878787610829565b915091506104f8816108e6565b5095945050505050565b5f6001600160a01b038516610536576040516322f051b160e21b81526001600160a01b0390911660048201526024016103b4565b505f6001600160a01b03841661056b5760405163270af7ed60e11b81526001600160a01b0390911660048201526024016103b4565b506001600160a01b038085165f908152600187016020908152604080832093871683529290522082905580156105e957826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516105e091815260200190565b60405180910390a35b5050505050565b6001600160a01b038084165f90815260018601602090815260408083209386168352929052908120545f198114610670578381848082101561065e57604051630c95cf2760e11b81526001600160a01b039093166004840152602483019190915260448201526064016103b4565b5050506106708686868685035f610502565b50600195945050505050565b5f6001600160a01b0384166106b0576040516313053d9360e21b81526001600160a01b0390911660048201526024016103b4565b505f6001600160a01b0383166106e557604051639cfea58360e01b81526001600160a01b0390911660048201526024016103b4565b506106f2848484846106f8565b50505050565b6001600160a01b0383166107245780846003015f8282546107199190610c22565b9091555061079a9050565b6001600160a01b0383165f90815260208590526040902054838183808210156107795760405163db42144d60e01b81526001600160a01b039093166004840152602483019190915260448201526064016103b4565b5050506001600160a01b0384165f9081526020869052604090209082900390555b6001600160a01b0382166107b85760038401805482900390556107d6565b6001600160a01b0382165f9081526020859052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068
|
2026-01-16 19:49:45 +00:00
|
|
|
"storage": {}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"15": {
|
|
|
|
|
"address": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
|
|
|
|
|
"code": "0x608060405260043610610079575f3560e01c80639623609d1161004c5780639623609d1461010957806399a88ec41461011c578063f2fde38b1461013b578063f3b7dead1461015a575f5ffd5b8063204e1c7a1461007d578063715018a6146100b85780637eff275e146100ce5780638da5cb5b146100ed575b5f5ffd5b348015610088575f5ffd5b5061009c610097366004610479565b610179565b6040516001600160a01b03909116815260200160405180910390f35b3480156100c3575f5ffd5b506100cc610204565b005b3480156100d9575f5ffd5b506100cc6100e836600461049b565b610217565b3480156100f8575f5ffd5b505f546001600160a01b031661009c565b6100cc6101173660046104e6565b61027a565b348015610127575f5ffd5b506100cc61013636600461049b565b6102e5565b348015610146575f5ffd5b506100cc610155366004610479565b61031b565b348015610165575f5ffd5b5061009c610174366004610479565b610399565b5f5f5f836001600160a01b031660405161019d90635c60da1b60e01b815260040190565b5f60405180830381855afa9150503d805f81146101d5576040519150601f19603f3d011682016040523d82523d5f602084013e6101da565b606091505b5091509150816101e8575f5ffd5b808060200190518101906101fc91906105bd565b949350505050565b61020c6103bd565b6102155f610416565b565b61021f6103bd565b6040516308f2839760e41b81526001600160a01b038281166004830152831690638f283970906024015b5f604051808303815f87803b158015610260575f5ffd5b505af1158015610272573d5f5f3e3d5ffd5b505050505050565b6102826103bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906102b290869086906004016105d8565b5f604051808303818588803b1580156102c9575f5ffd5b505af11580156102db573d5f5f3e3d5ffd5b5050505050505050565b6102ed6103bd565b604051631b2ce7f360e11b81526001600160a01b038281166004830152831690633659cfe690602401610249565b6103236103bd565b6001600160a01b03811661038d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61039681610416565b50565b5f5f5f836001600160a01b031660405161019d906303e1469160e61b815260040190565b5f546001600160a01b031633146102155760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610384565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610396575f5ffd5b5f60208284031215610489575f5ffd5b813561049481610465565b9392505050565b5f5f604083850312156104ac575f5ffd5b82356104b781610465565b915060208301356104c781610465565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f606084860312156104f8575f5ffd5b833561050381610465565b9250602084013561051381610465565b9150604084013567ffffffffffffffff81111561052e575f5ffd5b8401601f8101861361053e575f5ffd5b803567ffffffffffffffff811115610558576105586104d2565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610587576105876104d2565b60405281815282820160200188101561059e575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f602082840312156105cd575f5ffd5b815161049481610465565b60018060a01b0383168152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f830116840101915050939250505056fea2646970667358221220d1857c1d79adf09a4456300c200565d4db0d5bcc151c34d3d6a7ed403fb9defd64736f6c634300081c003300",
|
2026-01-06 11:27:50 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65"
|
2026-01-06 11:27:50 +00:00
|
|
|
}
|
|
|
|
|
},
|
2026-01-22 12:48:27 +00:00
|
|
|
"16": {
|
|
|
|
|
"address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
|
|
|
|
|
"code": "0x73e7f1725e7734ce288f8367e1bb143e90bb3f0512301460806040526004361061009b575f3560e01c80632a6c32291161006e5780632a6c322914610191578063805ce31d146101c5578063928bc49d146101db57806399056fcc146101ee578063fe61cc491461020d575f5ffd5b80630705f4651461009f57806309824a80146100c85780630b617646146100e957806326aa101f1461014a575b5f5ffd5b6100b26100ad366004611fdf565b61026c565b6040516100bf919061200a565b60405180910390f35b8180156100d3575f5ffd5b506100e76100e236600461203a565b610282565b005b7f59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f6547f59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f754604080519283526001600160801b039091166020830152016100bf565b61018161015836600461203a565b6001600160a01b03165f9081525f5160206125e85f395f51905f52602052604090205460ff1690565b60405190151581526020016100bf565b6101a461019f366004611fdf565b61033b565b6040805167ffffffffffffffff9384168152929091166020830152016100bf565b6101cd61036a565b6040519081526020016100bf565b6101cd6101e936600461207c565b610380565b8180156101f9575f5ffd5b506100e76102083660046120bc565b6103e0565b61025461021b366004611fdf565b5f9081527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23260205260409020546001600160a01b031690565b6040516001600160a01b0390911681526020016100bf565b5f5f61027783610494565b5460ff169392505050565b5f5160206125e85f395f51905f52610299826104ef565b60408051608081019091526001820154600160a01b900463ffffffff1681525f90602081016102c6610586565b815260028401546020909101906102e79086906001600160801b03166105e7565b81525f6020918201526040516001600160a01b03861681529192507ff78bb28d4b1d7da699e5c0bc2be29c2b04b5aab6aacf6298fe5304f9db9c6d7e910160405180910390a161033681610632565b505050565b5f5f5f61034784610494565b5467ffffffffffffffff6101008204811696600160481b90920416945092505050565b5f61037b610376610586565b610836565b905090565b6001600160a01b0383165f9081525f5160206125e85f395f51905f52602081905260408220805460ff166103c75760405163259ba1ad60e01b815260040160405180910390fd5b6103d461037686866108c7565b925050505b9392505050565b5f5160206125e85f395f51905f526001600160801b0382165f036104175760405163162908e360e11b815260040160405180910390fd5b6001600160a01b0387165f908152602082905260409020805460ff166104505760405163259ba1ad60e01b815260040160405180910390fd5b60018101546104745761046f61046a8989898989896109ae565b610632565b61048a565b61048a61046a82600101548a8a8a8a8a8a610b97565b5050505050505050565b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ac6020526040902060018101546001600160a01b03166104ea57604051636ddd9da960e01b815260040160405180910390fd5b919050565b610501816001600160a01b0316610cf9565b61051e5760405163c1ab6dc160e01b815260040160405180910390fd5b6001600160a01b0381165f9081525f5160206125e85f395f51905f5260208190526040909120805460ff168015610559575061055981610d3f565b1561057757604051633ea7ffd960e11b815260040160405180910390fd5b805460ff191660011790555050565b604080518082019091527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c230546001600160801b031681527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23154602082015290565b60605f6105f346610d53565b5f6105fd86610dbc565b61060686610ded565b60405160200161061a959493929190612161565b60405160208183030381529060405290505b92915050565b805160408051637061726160e01b60208083019190915260e09390931b6001600160e01b031916602482015281516008818303018152602890910190915280519101205f61067f82610494565b905061068a81610e8c565b5f6106988460200151610836565b90505f84606001516001600160801b0316826106b491906121c4565b9050803410156106d757604051631c0b171360e31b815260040160405180910390fd5b60608501516001600160801b0316156107225761072285606001516001600160801b031661070f5f5160206125e85f395f51905f5290565b600101546001600160a01b031690610f08565b825461074090600160481b900467ffffffffffffffff1660016121d7565b835467ffffffffffffffff91909116600160481b0270ffffffffffffffff000000000000000000199091161783555f61077982346121f7565b9050610783610f31565b811115610794576107943382610f08565b83546040805160208101889052600160481b90920460c01b6001600160c01b031916908201525f9060480160405160208183030381529060405280519060200120905080867f7153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b057
|
|
|
|
|
"storage": {}
|
|
|
|
|
},
|
|
|
|
|
"25": {
|
|
|
|
|
"address": "0x36C02dA8a0983159322a80FFE9F24b1acfF8B570",
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"code": "0x608060405260043610610195575f3560e01c8063a98fb355116100e7578063ceb29d6111610087578063e2148f5a11610062578063e2148f5a14610492578063f2fde38b146104b1578063fc299dee146104d0578063fe776c2a146104ef575f5ffd5b8063ceb29d611461042b578063d156b9111461044a578063d4c250081461045e575f5ffd5b8063be6ab6ef116100c2578063be6ab6ef146103ad578063c1a8e2c5146103ce578063c63fd502146103ed578063c968095b1461040c575f5ffd5b8063a98fb35514610337578063a9a899cd14610356578063b526578714610375575f5ffd5b8063715018a6116101525780638da5cb5b1161012d5780638da5cb5b146102c05780638f661996146102dd5780638f8ee552146102f0578063a831570514610318575f5ffd5b8063715018a61461026e57806373fe4ad81461028257806383821e8e146102a1575f5ffd5b80631500cd8d146101995780632fb31ef1146101ba578063303ca956146101f05780633bc28c8c1461020f57806357e443551461022e57806359b005341461024f575b5f5ffd5b3480156101a4575f5ffd5b506101b86101b3366004611eb6565b61051d565b005b3480156101c5575f5ffd5b506067546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101fb575f5ffd5b506101b861020a366004611f18565b610595565b34801561021a575f5ffd5b506101b8610229366004611eb6565b6106be565b348015610239575f5ffd5b5061024261073e565b6040516101e79190611fa6565b34801561025a575f5ffd5b506101b8610269366004611eb6565b61094b565b348015610279575f5ffd5b506101b86109d0565b34801561028d575f5ffd5b506101b861029c366004612068565b6109e3565b3480156102ac575f5ffd5b506101b86102bb36600461213c565b610d73565b3480156102cb575f5ffd5b506033546001600160a01b03166101d3565b6101b86102eb366004612188565b610f9a565b3480156102fb575f5ffd5b506103035f81565b60405163ffffffff90911681526020016101e7565b348015610323575f5ffd5b506101b86103323660046121b9565b61105a565b348015610342575f5ffd5b506101b861035136600461226a565b6110e5565b348015610361575f5ffd5b506101b8610370366004611eb6565b611164565b348015610380575f5ffd5b5061039d61038f366004611eb6565b6001600160a01b0316301490565b60405190151581526020016101e7565b3480156103b8575f5ffd5b506103c16111b4565b6040516101e7919061229b565b3480156103d9575f5ffd5b506101b86103e83660046122e6565b61125c565b3480156103f8575f5ffd5b506101b8610407366004612336565b611328565b348015610417575f5ffd5b506101b86104263660046121b9565b6114d2565b348015610436575f5ffd5b506101b86104453660046121b9565b61152c565b348015610455575f5ffd5b50610242611792565b348015610469575f5ffd5b506101d3610478366004611eb6565b60686020525f90815260409020546001600160a01b031681565b34801561049d575f5ffd5b506101b86104ac366004611eb6565b6117ae565b3480156104bc575f5ffd5b506101b86104cb366004611eb6565b611828565b3480156104db575f5ffd5b506065546101d3906001600160a01b031681565b3480156104fa575f5ffd5b5061039d610509366004611eb6565b60666020525f908152604090205460ff1681565b6105256118a1565b6001600160a01b03811661054c5760405163d92e233d60e01b815260040160405180910390fd5b606780546001600160a01b0319166001600160a01b0383169081179091556040517f6a8a174b559440c4e231f06fda7f0eb644f79306c33292fbb95f7602bef9aaf9905f90a250565b61059d6118fb565b6001600160a01b03831630146105c657604051631280731d60e21b815260040160405180910390fd5b600181146105e75760405163f37f411760e01b815260040160405180910390fd5b5f828282816105f8576105f86123f5565b905060200201602081019061060d919061241c565b63ffffffff16146106315760405163c106a33360e01b815260040160405180910390fd5b6001600160a01b0384165f90815260686020526040812080546001600160a01b03191690558290829081610667576106676123f5565b905060200201602081019061067c919061241c565b63ffffffff16846001600160a01b03167f2638d53da645bac898f1b50bd1d6d2a4d389e3141e209c988488abced5c3c54c60405160405180910390a350505050565b6106c66118a1565b6001600160a01b0381166106ed5760405163d92e233d60e01b815260040160405180910390fd5b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa499ec18d14a183a8ce150f6d1a61fe68e989121c8aa695bafde5305f1eee81c905f90a35050565b6040805180820182523081525f602082018190529151633743aedd60e11b8152606092907f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed6001600160a01b031690636e875dba906107a1908590600401612435565b5f60405180830381865afa1580156107bb573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526107e2919081019061245d565b90505f81516001600160401b038111156107fe5761
|
2026-01-13 14:03:10 +00:00
|
|
|
"storage": {
|
2026-01-22 12:48:27 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
2026-01-12 15:55:46 +00:00
|
|
|
}
|
2026-01-06 11:27:50 +00:00
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"32": {
|
|
|
|
|
"address": "0x998abeb3E57409262aE5b751f60747921B33613E",
|
2026-01-22 12:48:27 +00:00
|
|
|
"code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c657665
|
2026-01-12 15:55:46 +00:00
|
|
|
"storage": {
|
2026-01-22 12:48:27 +00:00
|
|
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788",
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000032": "0x00000000000000000000000095401dc811bb5740090279ba06cfa8fcf6113778",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000064": "0x00000000000000000000000000000000000000000000d3c21bcecceda1000000",
|
2026-01-22 12:48:27 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000065": "0x000000000000000000000000000000000000000000084595161401484a000000",
|
|
|
|
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000f5059a5d33d5853360d16c683c16e67980206f36"
|
2026-01-12 15:55:46 +00:00
|
|
|
}
|
refactor: cleanup old rewards model (#383)
## Summary
This PR removes the old merkle root-based rewards model and completes
the migration to EigenLayer Rewards V2 distribution. The old model
required operators to claim rewards by providing merkle proofs, while
the new model uses `submitRewards` to send rewards directly to
EigenLayer's `RewardsCoordinator`.
### Key Changes
- **Smart Contracts**: Removed `RewardsRegistry`,
`RewardsRegistryStorage`, `IRewardsRegistry`, and `SortedMerkleProof`
contracts along with all merkle claim functions from
`ServiceManagerBase`
- **Substrate Pallets**: Removed merkle proof generation from
`external-validators-rewards` pallet and deleted the entire
`runtime-api` crate (no longer needed)
- **Test Framework**: Removed all RewardsRegistry-related code from
deployment scripts, CLI handlers, and TypeScript bindings
- **Runtimes**: Cleaned up all three runtimes (testnet, stagenet,
mainnet) to remove runtime API implementations and unused imports
### Files Removed
**Contracts:**
- `contracts/src/middleware/RewardsRegistry.sol`
- `contracts/src/middleware/RewardsRegistryStorage.sol`
- `contracts/src/interfaces/IRewardsRegistry.sol`
- `contracts/src/libraries/SortedMerkleProof.sol`
- `contracts/test/RewardsRegistry.t.sol`
- `contracts/test/ServiceManagerRewardsRegistry.t.sol`
**Substrate:**
- `operator/pallets/external-validators-rewards/runtime-api/` (entire
crate)
**Test Framework:**
- `test/suites/rewards-message.test.ts`
### Files Modified
**Contracts:**
- `ServiceManagerBase.sol` - Removed merkle claim functions
- `ServiceManagerBaseStorage.sol` - Removed
`operatorSetToRewardsRegistry` mapping
- `IServiceManager.sol` - Removed interface members
**Substrate:**
- `external-validators-rewards` pallet - Removed merkle proof
generation, simplified `EraRewardsUtils` struct
- All runtime configs - Removed `ExternalValidatorsRewardsApi`
implementations
**Test Framework:**
- Updated deployment scripts, CLI handlers, relayer configs, and
TypeScript bindings
### Stats
```
50 files changed, 966 insertions(+), 4453 deletions(-)
```
## Test plan
- [x] All Rust tests pass (`cargo test`)
- [x] All contract tests pass (`forge test`)
- [x] TypeScript type checking passes (`bun typecheck`)
- [x] Contracts build successfully (`forge build`)
- [x] Operator builds successfully (`cargo build --release --features
fast-runtime`)
- [ ] E2E tests pass (`bun test:e2e`)
2026-01-09 14:25:49 +00:00
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"10": {
|
|
|
|
|
"address": "0xf5059a5D33d5853360D16C683c16e67980206f36",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b5060043610610187575f3560e01c80637a8b2637116100d9578063c4d66de811610093578063df6fadc11161006e578063df6fadc114610361578063e3dae51c1461037c578063f3e738751461038f578063fabc1cbc146103a2575f5ffd5b8063c4d66de814610328578063ce7c2ac21461033b578063d9caed121461034e575f5ffd5b80637a8b2637146102ad578063886f1195146102c05780638c871019146102e75780638f6a6240146102fa578063a6ab36f21461030d578063ab5921e114610320575f5ffd5b806347e7ef2411610144578063595c6a671161011f578063595c6a67146102655780635ac86ab71461026d5780635c975abb1461029c57806361b01b5d146102a4575f5ffd5b806347e7ef241461022a57806354fd4d501461023d578063553ca5f814610252575f5ffd5b806311c70c9d1461018b578063136439dd146101a05780632495a599146101b357806339b70e38146101e35780633a98ef391461020a57806343fe08b014610221575b5f5ffd5b61019e6101993660046111b1565b6103b5565b005b61019e6101ae3660046111d1565b6103cb565b6032546101c6906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101c67f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750881565b61021360335481565b6040519081526020016101da565b61021360645481565b6102136102383660046111fc565b610401565b610245610530565b6040516101da9190611226565b61021361026036600461125b565b610560565b61019e610573565b61028c61027b36600461128b565b6001805460ff9092161b9081161490565b60405190151581526020016101da565b600154610213565b61021360655481565b6102136102bb3660046111d1565b610587565b6101c67f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6102136102f53660046111d1565b6105d0565b61021361030836600461125b565b6105da565b61019e61031b3660046112a6565b6105e7565b6102456106c2565b61019e61033636600461125b565b6106e2565b61021361034936600461125b565b6107a8565b61021361035c3660046112dc565b61083a565b606454606554604080519283526020830191909152016101da565b61021361038a3660046111d1565b61093c565b61021361039d3660046111d1565b610973565b61019e6103b03660046111d1565b61097d565b6103bd6109ea565b6103c78282610a9b565b5050565b6103d3610b3f565b60015481811681146103f85760405163c61dca5d60e01b815260040160405180910390fd5b6103c782610be2565b5f5f61040c81610c1f565b336001600160a01b037f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb6075081614610455576040516348da714f60e01b815260040160405180910390fd5b61045f8484610c55565b6033545f61046f6103e88361132e565b90505f6103e861047d610cac565b610487919061132e565b90505f6104948783611341565b9050806104a18489611354565b6104ab919061136b565b9550855f036104cd57604051630c392ed360e11b815260040160405180910390fd5b6104d7868561132e565b60338190556f4b3b4ca85a86c47a098a223fffffffff101561050c57604051632f14e8a360e11b815260040160405180910390fd5b610525826103e8603354610520919061132e565b610d16565b505050505092915050565b606061055b7f76312e302e300000000000000000000000000000000000000000000000000006610d62565b905090565b5f61056d6102bb836107a8565b92915050565b61057b610b3f565b6105855f19610be2565b565b5f5f6103e8603354610599919061132e565b90505f6103e86105a7610cac565b6105b1919061132e565b9050816105be8583611354565b6105c8919061136b565b949350505050565b5f61056d8261093c565b5f61056d61039d836107a8565b5f54610100900460ff161580801561060557505f54600160ff909116105b8061061e5750303b15801561061e57505f5460ff166001145b6106435760405162461bcd60e51b815260040161063a9061138a565b60405180910390fd5b5f805460ff191660011790558015610664575f805461ff0019166101001790555b61066e8484610a9b565b61067782610d9f565b80156106bc575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b60606040518060800160405280604d815260200161145b604d9139905090565b5f54610100900460ff161580801561070057505f54600160ff909116105b806107195750303b15801561071957505f5460ff166001145b6107355760405162461bcd60e51b815260040161063a9061138a565b5f805460ff191660011790558015610756575f805461ff0019166101001790555b61075f82610d9f565b80156103c7575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a15050565b60405163fe243a1760e01b81526001600160a01b0382811660048301523060248301525f917f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb6075089091169063fe243a17
|
2026-01-13 14:03:10 +00:00
|
|
|
"storage": {
|
2026-01-22 12:48:27 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
2026-01-13 14:03:10 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"40": {
|
|
|
|
|
"address": "0xc5a5C42992dECbae36851359345FE25997F5C42d",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b50600436106102ff575f3560e01c8063670d3ba211610195578063b2447af7116100e4578063db4df7611161009e578063f231bd0811610079578063f231bd08146107f7578063f605ce081461080a578063fabc1cbc1461081d578063fe4b84df14610830575f5ffd5b8063db4df76114610796578063dc2af692146107bd578063df5cf723146107d0575f5ffd5b8063b2447af714610708578063b66bd9891461071b578063b9fbaed11461072e578063ba1a84e51461075d578063c221d8ae14610770578063d3d96ff414610783575f5ffd5b8063886f11951161014f578063952899ee1161012a578063952899ee146106bc578063a9333ec8146106cf578063a9821821146106e2578063adc2e3d9146106f5575f5ffd5b8063886f1195146106625780638ce648541461068957806394d7d00c146106a9575f5ffd5b8063670d3ba2146105c45780636cfb4481146105d75780636e3492b5146106025780636e875dba1461061557806379ae50cd146106285780637bc1ef611461063b575f5ffd5b806340120dab1161025157806350feea201161020b57806356c483e6116101e657806356c483e61461057e578063595c6a67146105915780635ac86ab7146105995780635c975abb146105bc575f5ffd5b806350feea2014610543578063547afb871461055657806354fd4d5014610569575f5ffd5b806340120dab146104875780634177a87c146104a85780634657e26a146104c85780634a10ffe5146104ef5780634b5046ef1461050f5780634cfd293914610522575f5ffd5b8063261f84e0116102bc5780632bab2c4a116102975780632bab2c4a1461042d578063304c10cd1461044057806332a879e4146104535780633635205714610466575f5ffd5b8063261f84e0146103be5780632981eb77146103d15780632b453a9a1461040d575f5ffd5b80630f3df50e1461030357806310e1b9b8146103335780631352c3e614610353578063136439dd1461037657806315fe50281461038b578063260dc758146103ab575b5f5ffd5b610316610311366004614bf0565b610843565b6040516001600160a01b0390911681526020015b60405180910390f35b610346610341366004614c0a565b610884565b60405161032a9190614c51565b610366610361366004614c84565b6108bd565b604051901515815260200161032a565b610389610384366004614cb8565b610938565b005b61039e610399366004614ccf565b610972565b60405161032a9190614d4d565b6103666103b9366004614bf0565b610a89565b6103896103cc366004614d9f565b610aba565b6103f87f000000000000000000000000000000000000000000000000000000000000003281565b60405163ffffffff909116815260200161032a565b61042061041b366004614e84565b610b63565b60405161032a9190614f27565b61042061043b366004614f8a565b610b79565b61031661044e366004614ccf565b610c18565b61038961046136600461500e565b610c47565b61047961047436600461508e565b610d8e565b60405161032a9291906150e0565b61049a6104953660046150f8565b610ed1565b60405161032a929190615185565b6104bb6104b6366004614bf0565b61104c565b60405161032a91906151e2565b6103167f0000000000000000000000003aa5ebb10dc797cac828524e59a333d0a371443c81565b6105026104fd3660046151f4565b611070565b60405161032a9190615237565b61038961051d36600461500e565b611118565b610535610530366004614bf0565b6111ab565b60405190815260200161032a565b610389610551366004615282565b6111cd565b6105026105643660046152e0565b6112be565b610571611366565b60405161032a9190615322565b61038961058c366004615357565b611396565b61038961149b565b6103666105a7366004615381565b606654600160ff9092169190911b9081161490565b606654610535565b6103666105d2366004614c84565b6114af565b6105ea6105e53660046150f8565b6114db565b6040516001600160401b03909116815260200161032a565b6103896106103660046153b7565b6114f0565b6104bb610623366004614bf0565b6118b3565b61039e610636366004614ccf565b6118c4565b6103f87f000000000000000000000000000000000000000000000000000000000000004b81565b6103167f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b61069c6106973660046153e8565b61199e565b60405161032a919061542b565b6105026106b736600461543d565b611a5a565b6103896106ca366004615498565b611b46565b6105ea6106dd3660046150f8565b611fe7565b6103896106f0366004615641565b612016565b6103896107033660046156bf565b6120c8565b610535610716366004614bf0565b612411565b610389610729366004615282565b612433565b61074161073c366004614ccf565b61258d565b60408051921515835263ffffffff90911660208301520161032a565b61053561076b366004614ccf565b612627565b6104bb61077e366004614c84565b612647565b6103896107913660046150f8565b612670565b6103167f000000000000000000000000c6e7df5e7b4f2a278906862b61205850344d4e7d81565b6103666107cb366004614ccf565b61279d565b6103167f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8281565b
|
2026-01-13 14:03:10 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
2026-01-13 14:03:10 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"9": {
|
|
|
|
|
"address": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
|
|
|
|
|
"code": "0x735fc8d32690cc91d4c39d9d3abcbd16989f875707301460806040526004361061006b575f3560e01c8063017b73111461006f578063253946451461009057806365529675146100af5780638257f3d5146100ce578063ae8a4d98146100ed578063fe1aa59d1461010c575b5f5ffd5b81801561007a575f5ffd5b5061008e61008936600461080c565b61012b565b005b81801561009b575f5ffd5b5061008e6100aa36600461080c565b610155565b8180156100ba575f5ffd5b5061008e6100c9366004610860565b6101db565b8180156100d9575f5ffd5b5061008e6100e836600461080c565b610267565b8180156100f8575f5ffd5b5061008e61010736600461080c565b6102f8565b818015610117575f5ffd5b5061008e6101263660046108ae565b610328565b5f610138828401846109a7565b9050610150815f0151826020015183604001516103a5565b505050565b5f61016282840184610a68565b80516020820151604080840151905163a3499c7360e01b8152939450732279b7a0a67db372996a5fab50d91eaa73d2ebe69363a3499c73936101aa9390929091600401610b1b565b5f6040518083038186803b1580156101c0575f5ffd5b505af41580156101d2573d5f5f3e3d5ffd5b50505050505050565b5f6101e882840184610b4a565b90505f6102147f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b79610414565b82519091506001600160a01b0316610248576102438582846020015185604001516001600160801b031661046c565b610260565b6102608582845f0151856020015186604001516104c9565b5050505050565b5f61027482840184610b7b565b80517e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab805492935091829060ff1916600183818111156102b5576102b5610bc9565b021790555081516040517f4016a1377b8961c4aa6f3a2d3de830a685ddbfe0f228ffc0208eb96304c4cf1a916102ea91610bdd565b60405180910390a150505050565b5f61030582840184610c03565b9050610322815f015182602001518360400151846060015161052e565b50505050565b5f61033582840184610cbd565b90505f61034186610414565b90505f825f01518360200151846040015160405160240161036493929190610d45565b60408051601f198184030181529190526020810180516001600160e01b031663c6b295c160e01b179052905061039b828783610679565b5050505050505050565b5f6103af84610705565b6040516340c10f1960e01b81526001600160a01b0385811660048301526001600160801b0385166024830152919250908216906340c10f19906044015f604051808303815f87803b158015610402575f5ffd5b505af115801561039b573d5f5f3e3d5ffd5b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ad60205260409020546001600160a01b0316806104675760405163d3227c9b60e01b815260040160405180910390fd5b919050565b6040516001600160a01b0383166024820152604481018290525f9060640160408051601f198184030181529190526020810180516001600160e01b03166305b1137b60e01b17905290506104c1848683610679565b505050505050565b6040516001600160a01b038085166024830152831660448201526001600160801b03821660648201525f9060840160408051601f198184030181529190526020810180516001600160e01b03166309733b7b60e21b17905290506101d2858783610679565b5f8481527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23260205260408120547f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e906001600160a01b0316156105a457604051633ea7ffd960e11b815260040160405180910390fd5b5f8585856040516105b4906107bb565b6105c093929190610d78565b604051809103905ff0801580156105d9573d5f5f3e3d5ffd5b50604080518082018252600180825260208083018c81525f8d815260048901835285812080546001600160a01b0319166001600160a01b038916908117909155808252898452908690208551815460ff19169015151781559151919093015592519081529293509189917f57f58171b8777633d03aff1e7408b96a3d910c93a7ce433a8cb7fb837dc306a6910160405180910390a2509695505050505050565b60605f5f856001600160a01b0316639bb66b2886866040518363ffffffff1660e01b81526004016106ab929190610db0565b5f604051808303815f875af11580156106c6573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106ed9190810190610ddb565b915091506106fb8282610796565b9695505050505050565b5f8181527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23260205260408120547f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e906001600160a01b031661077a5760405163259ba1ad60e01b815260040160405180910390fd5b5f9283526004016020525060409020546001600160a01b031690565b606082156107a55750806107b5565b81511561006b5781518083602001fd5b92915050565b610c3580610e6883390190565b5f5f83601f8401126107d8575f5ffd5b5081356001600160401b038111156107ee575f5ffd5b602083019150836020
|
2026-01-22 12:48:27 +00:00
|
|
|
"storage": {}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"43": {
|
|
|
|
|
"address": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
|
|
|
|
|
"code": "0x73cf7ed3acca5a467e9e704c703e8d87f634fb0fc93014608060405260043610610034575f3560e01c8063d3b08db814610038575b5f5ffd5b61004b610046366004610370565b610061565b6040516100589190610465565b60405180910390f35b805180516060915f83815b83518163ffffffff1610156101065781848263ffffffff16815181106100945761009461049a565b60200260200101516040516020016100c4919060609190911b6bffffffffffffffffffffffff1916815260140190565b60408051601f19818403018152908290526100e292916020016104c5565b604051602081830303815290604052915080806100fe906104f5565b91505061006c565b50630e02a00760e31b5f8061011a876101ac565b8465ff000000ff00600888811b91821664ff000000ff918a901c91821617601090811b67ff000000ff0000009390931666ff000000ff00009290921691909117901c17602081811b6bffffffffffffffff000000001691901c63ffffffff161760c01b60405160200161019296959493929190610519565b604051602081830303815290604052945050505050919050565b6060603f8263ffffffff16116101e957604051603f60fa1b60fa84901b1660208201526021015b6040516020818303038152906040529050919050565b613fff8263ffffffff1611610248576102256102116403fffffffc600285901b166001610572565b600881811b62ffff001691901c60ff161790565b6040516020016101d3919060f09190911b6001600160f01b031916815260020190565b633fffffff8263ffffffff16116102ba5761029760028363ffffffff16901b60026102739190610572565b600881811c62ff00ff1663ff00ff009290911b9190911617601081811c91901b1790565b6040516020016101d3919060e09190911b6001600160e01b031916815260040190565b604051600360f81b60208201526001600160e01b0319600884811c62ff00ff1663ff00ff009186901b9190911617601081811c91901b1760e01b1660218201526025016101d3565b634e487b7160e01b5f52604160045260245ffd5b6040516020810167ffffffffffffffff8111828210171561033957610339610302565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561036857610368610302565b604052919050565b5f60208284031215610380575f5ffd5b813567ffffffffffffffff811115610396575f5ffd5b8201602081850312156103a7575f5ffd5b6103af610316565b813567ffffffffffffffff8111156103c5575f5ffd5b80830192505084601f8301126103d9575f5ffd5b813567ffffffffffffffff8111156103f3576103f3610302565b8060051b6104036020820161033f565b9182526020818501810192908101908884111561041e575f5ffd5b6020860195505b8386101561045757853592506001600160a01b0383168314610445575f5ffd5b82825260209586019590910190610425565b845250919695505050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f6104d96104d383866104ae565b846104ae565b949350505050565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff821663ffffffff8103610510576105106104e1565b60010192915050565b6001600160e01b0319871681526001600160f81b03198681166004830152851660058201525f61055561054f60068401876104ae565b856104ae565b6001600160c01b0319939093168352505060080195945050505050565b63ffffffff818116838216019081111561058e5761058e6104e1565b9291505056fea2646970667358221220ec754a565932b22e059c17b06dbd28b7721de4df0054b69f4983510c827d2c9364736f6c634300081c0033000000000000000000000000000000000000",
|
|
|
|
|
"storage": {}
|
2026-01-06 11:27:50 +00:00
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"34": {
|
|
|
|
|
"address": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
|
|
|
|
|
"code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c657665
|
2026-01-20 10:32:32 +00:00
|
|
|
"storage": {
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
|
|
|
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000009635f643e140090a9a8dcd712ed6285858cebef",
|
|
|
|
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788",
|
|
|
|
|
"0x00000000000000000000000000000000000000000000000000000000000000cb": "0x000003e80000000000001c2090f79bf6eb2c4f870365e785982e1f101e93b906",
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65"
|
2026-01-20 10:32:32 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"5": {
|
|
|
|
|
"address": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318",
|
|
|
|
|
"code": "0x738a791620dd6260079bf849dc5567adc3f2fdc3183014608060405260043610610090575f3560e01c8063ab55562e11610063578063ab55562e146100fd578063af18d14214610105578063c82b5f451461010d578063ded905d514610115575f5ffd5b80632db726161461009457806379d0e91c146100bc5780637cb1a954146100e05780639ce504ff146100f6575b5f5ffd5b6100a76100a23660046109da565b61011c565b60405190151581526020015b60405180910390f35b6100c7600160f81b81565b6040516001600160f81b031990911681526020016100b3565b6100e8600581565b6040519081526020016100b3565b6100c75f81565b6100e8600681565b6100e8600481565b6100e8600881565b6100e85f81565b5f6101318461012b8580610a64565b84610278565b61013c57505f61026f565b6101496020840184610a82565b6020013583806020019061015d9190610a82565b351061016a57505f61026f565b5f61017e866101798680610a64565b610419565b90505f6101c7826101926020880188610a82565b356101a06020890189610a82565b602001358880602001906101b49190610a82565b6101c2906040810190610a96565b610434565b90505f6101e56101df36889003880160408901610b1d565b836104da565b90506001600160a01b03891663a401662b826102056101008a018a610a96565b8a61012001356040518563ffffffff1660e01b815260040161022a9493929190610bbc565b602060405180830381865afa158015610245573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102699190610c00565b93505050505b95945050505050565b5f5f82610285575f61028b565b600160f81b5b90505f5b61029c6080860186610a96565b905081101561040c575f6102b36080870187610a96565b838181106102c3576102c3610c1b565b90506020028101906102d59190610a82565b3514801561032157506102eb6080860186610a96565b828181106102fb576102fb610c1b565b905060200281019061030d9190610a82565b61031b906040810190610c2f565b90506021145b801561039657506001600160f81b031982166103406080870187610a96565b8381811061035057610350610c1b565b90506020028101906103629190610a82565b610370906040810190610c2f565b5f81811061038057610380610c1b565b9050013560f81c60f81b6001600160f81b031916145b80156103f457506103aa6080860186610a96565b828181106103ba576103ba610c1b565b90506020028101906103cc9190610a82565b6103da906040810190610c2f565b6103e8916001908290610c72565b6103f191610c99565b86145b1561040457600192505050610412565b60010161028f565b505f9150505b9392505050565b5f610424838361062c565b8051906020012090505b92915050565b5f85815b838110156104cf57866001166001148061045457508587600101145b1561048b5761048485858381811061046e5761046e610c1b565b90506020020135835f9182526020526040902090565b91506104b9565b6104b6828686848181106104a1576104a1610c1b565b905060200201355f9182526020526040902090565b91505b600196871c965f19909601861c86019501610438565b509695505050505050565b81515f90819060f81b6105128560200151600881811c62ff00ff1663ff00ff009290911b9190911617601081811c91901b1760e01b90565b856040015161058887606001515f65ff000000ff00600883811b91821664ff000000ff9185901c91821617601090811b67ff000000ff0000009390931666ff000000ff00009290921691909117901c17602081811b6bffffffffffffffff000000001691901c63ffffffff161760c01b92915050565b6080880151600881811b63ff00ff001662ff00ff9290911c9190911617601081811b91901c1760e01b60a08901516040516001600160f81b031990961660208701526001600160e01b0319948516602187015260258601939093526001600160c01b0319909116604585015291909116604d83015260518201526071810184905260910160408051808303601f190181529190528051602090910120949350505050565b60605f823561063e60208501356106b8565b6040850135606086013561065d6106586080890189610a96565b6106e8565b604051602001610671959493929190610ccd565b60405160208183030381529060405290508361068d82516106b8565b826040516020016106a093929190610d00565b60405160208183030381529060405291505092915050565b606063ffffffff8211156106df57604051637404cccd60e11b815260040160405180910390fd5b61042e82610778565b60408051602081019091525f808252606091905b8381101561075c578161073186868481811061071a5761071a610c1b565b905060200281019061072c9190610a82565b6108d3565b604051602001610742929190610d24565b60408051601f1981840301815291905291506001016106fc565b50610766836106b8565b816040516020016106a0929190610d24565b6060603f8263ffffffff16116107b557604051603f60fa1b60fa84901b1660208201526021015b6040516020818303038152906040529050919050565b613fff8263ffffffff1611610814576107f16107dd6403fffffffc600285901b166001610d3a565b600881811b62ffff001691901c60ff161790565b604051602001
|
2026-01-12 15:55:46 +00:00
|
|
|
"storage": {}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"31": {
|
|
|
|
|
"address": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
|
2026-01-20 10:32:32 +00:00
|
|
|
"code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c657665
|
2026-01-16 19:49:45 +00:00
|
|
|
"storage": {
|
2026-01-20 10:32:32 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
2026-01-22 12:48:27 +00:00
|
|
|
"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788",
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65",
|
|
|
|
|
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000007a2088a1bfc9d81c55368ae168c2c02570cb814f"
|
2026-01-16 19:49:45 +00:00
|
|
|
}
|
|
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"3": {
|
|
|
|
|
"address": "0x09635F643e140090A9A8Dcd712eD6285858ceBef",
|
|
|
|
|
"code": "0x608060405234801561000f575f5ffd5b50600436106103b3575f3560e01c8063886f1195116101f5578063de02e50311610114578063f6efbb59116100a9578063fabc1cbc11610079578063fabc1cbc14610a33578063fbf1e2c114610a46578063fce36c7d14610a59578063ff9f6cce14610a6c575f5ffd5b8063f6efbb59146109e7578063f74e8eac146109fa578063f8cd844814610a0d578063f96abf2e14610a20575f5ffd5b8063ed71e6a2116100e4578063ed71e6a214610967578063f22cef8514610994578063f2f07ab4146109a7578063f2fde38b146109d4575f5ffd5b8063de02e50314610907578063e063f81f1461091a578063e810ce211461092d578063ea4d3c9b14610940575f5ffd5b8063a50a1d9c1161018a578063bf21a8aa1161015a578063bf21a8aa14610879578063c46db606146108a0578063ca8aa7c7146108cd578063dcbb03b3146108f4575f5ffd5b8063a50a1d9c14610807578063aebd8bae1461081a578063b3dbb0e014610847578063bb7e451f1461085a575f5ffd5b80639cb9a5fa116101c55780639cb9a5fa146107a75780639d45c281146107ba5780639de4b35f146107e1578063a0169ddd146107f4575f5ffd5b8063886f11951461074c5780638da5cb5b146107735780639104c319146107845780639be3d4e41461079f575f5ffd5b80634596021c116102e15780635c975abb11610276578063715018a611610246578063715018a6146106ff5780637b8f8b0514610707578063863cb9a91461070f578063865c695314610722575f5ffd5b80635c975abb146106a25780635e9d8348146106aa57806363f6a798146106bd5780636d21117e146106d2575f5ffd5b806354fd4d50116102b157806354fd4d501461064f57806358baaa3e14610664578063595c6a67146106775780635ac86ab71461067f575f5ffd5b80634596021c146105d85780634657e26a146105eb5780634b943960146106125780634d18cc3514610638575f5ffd5b8063149bc8721161035757806339b70e381161032757806339b70e38146105745780633a8c07861461059b5780633ccc861d146105b25780633efe1db6146105c5575f5ffd5b8063149bc872146104d95780632b9f64a4146104fa57806336af41fa1461053a57806337838ed01461054d575f5ffd5b80630e9a53cf116103925780630e9a53cf1461043f5780630eb383451461048c578063131433b41461049f578063136439dd146104c6575f5ffd5b806218572c146103b757806304a0c502146103ee5780630ca298991461042a575b5f5ffd5b6103d96103c5366004613a33565b60d16020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6104157f0000000000000000000000000000000000000000000000000000000000278d0081565b60405163ffffffff90911681526020016103e5565b61043d610438366004613aab565b610a7f565b005b610447610d25565b6040516103e591905f6080820190508251825263ffffffff602084015116602083015263ffffffff604084015116604083015260608301511515606083015292915050565b61043d61049a366004613b07565b610e25565b6104157f0000000000000000000000000000000000000000000000000000000065fb788081565b61043d6104d4366004613b3e565b610ea5565b6104ec6104e7366004613b55565b610edf565b6040519081526020016103e5565b610522610508366004613a33565b60cc6020525f90815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016103e5565b61043d610548366004613b6f565b610f54565b6104157f000000000000000000000000000000000000000000000000000000000076a70081565b6105227f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750881565b60cb5461041590600160a01b900463ffffffff1681565b61043d6105c0366004613bbe565b6110c5565b61043d6105d3366004613c14565b6110ec565b61043d6105e6366004613c3e565b6112c2565b6105227f0000000000000000000000003aa5ebb10dc797cac828524e59a333d0a371443c81565b610625610620366004613a33565b611325565b60405161ffff90911681526020016103e5565b60cb5461041590600160c01b900463ffffffff1681565b610657611380565b6040516103e59190613c90565b61043d610672366004613cc5565b6113b0565b61043d6113c4565b6103d961068d366004613cde565b606654600160ff9092169190911b9081161490565b6066546104ec565b6103d96106b8366004613cfe565b6113d8565b60cb5461062590600160e01b900461ffff1681565b6103d96106e0366004613d2f565b60cf60209081525f928352604080842090915290825290205460ff1681565b61043d611463565b60ca546104ec565b61043d61071d366004613a33565b611474565b6104ec610730366004613d59565b60cd60209081525f928352604080842090915290825290205481565b6105227f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6033546001600160a01b0316610522565b61052273beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac081565b610447611485565b61043d6107b5366004613d85565b611521565b6104157f000000000000000000000000000000000000000000000000000000000001518081565b6106256107ef366004613dbc565b61169c565b61043d
|
|
|
|
|
"storage": {
|
|
|
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff"
|
|
|
|
|
}
|
2026-01-16 19:49:45 +00:00
|
|
|
},
|
refactor(rewards): Optimize reward calculation (#408)
### Summary
Optimizes `award_session_performance_points` by batching all validator
rewards into a single storage mutation instead of performing individual
mutations inside the loop.
### Problem
The `award_session_performance_points` function, called during session
rotation via `SessionManager::end_session`, was calling `reward_by_ids`
inside the validator loop for each validator individually:
```rust
for validator in validators.iter() {
// ... calculate points ...
Self::reward_by_ids([(validator.clone(), points)].into_iter());
}
```
Each call to `reward_by_ids` performs a `StorageMap::mutate` on
`RewardPointsForEra`, which reads and writes the entire
`EraRewardPoints` structure (a `BTreeMap` containing up to N validator
entries). With N validators, this results in N separate
read-modify-write cycles of an O(N)-sized structure, leading to O(N²)
total storage I/O.
### Solution
Collect all reward points first, then perform a single batched call to
`reward_by_ids`:
```rust
let mut rewards = Vec::new();
for validator in validators.iter() {
// ... calculate points ...
rewards.push((validator.clone(), points));
}
if !rewards.is_empty() {
Self::reward_by_ids(rewards.into_iter());
}
```
This reduces the complexity from O(N²) to O(N) by performing only one
storage mutation that processes all validators at once.
### Why This Matters
Session rotation hooks are mandatory—they execute regardless of block
weight limits. While `pallet_session::on_initialize` returns `max_block`
weight during rotation (preventing user transactions), the actual
execution time still matters. With a large validator set, O(N²) storage
operations could exceed the block time target, potentially causing block
production delays.
### Test Plan
- [x] Existing unit tests pass (`cargo test -p
pallet-external-validators-rewards`)
2026-01-22 21:40:12 +00:00
|
|
|
"8": {
|
|
|
|
|
"address": "0x0E801D84Fa97b50751Dbf25036d067dCf18858bF",
|
|
|
|
|
"code": "0x60806040526004361061003e575f3560e01c806305b1137b1461004257806325ccedec14610063578063c6b295c114610082578063d0e30db014610061575b5f5ffd5b34801561004d575f5ffd5b5061006161005c36600461025e565b6100a1565b005b34801561006e575f5ffd5b5061006161007d366004610288565b6100b8565b34801561008d575f5ffd5b5061006161009c3660046102ef565b6100da565b6100b46001600160a01b038316826100f7565b5050565b6100d56001600160a01b038416836001600160801b038416610120565b505050565b5f6100e6848484610171565b9050806100f1575f5ffd5b50505050565b5f5f5f5f5f85875af19050806100d557604051633d2cec6f60e21b815260040160405180910390fd5b6040516001600160a01b0383166024820152604481018290526100d590849060640160408051601f198184030181529190526020810180516001600160e01b031663a9059cbb60e01b179052610188565b5f5f5f5f85516020870186895af195945050505050565b5f5f836001600160a01b0316836040516101a291906103be565b5f604051808303815f865af19150503d805f81146101db576040519150601f19603f3d011682016040523d82523d5f602084013e6101e0565b606091505b50915091505f82801561020b57508151158061020b57508180602001905181019061020b91906103d4565b905080158061022257506001600160a01b0385163b155b156102405760405163022e258160e11b815260040160405180910390fd5b5050505050565b6001600160a01b038116811461025b575f5ffd5b50565b5f5f6040838503121561026f575f5ffd5b823561027a81610247565b946020939093013593505050565b5f5f5f6060848603121561029a575f5ffd5b83356102a581610247565b925060208401356102b581610247565b915060408401356001600160801b03811681146102d0575f5ffd5b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610301575f5ffd5b833561030c81610247565b9250602084013567ffffffffffffffff811115610327575f5ffd5b8401601f81018613610337575f5ffd5b803567ffffffffffffffff811115610351576103516102db565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610380576103806102db565b604052818152828201602001881015610397575f5ffd5b816020840160208301375f9181016020019190915293969395505050506040919091013590565b5f82518060208501845e5f920191825250919050565b5f602082840312156103e4575f5ffd5b815180151581146103f3575f5ffd5b939250505056fea2646970667358221220590055fea5441ad6e827390b16005643886d2dc4ffe2b97b43ed3ab207076ab664736f6c634300081c003300",
|
2026-01-22 12:48:27 +00:00
|
|
|
"storage": {}
|
2026-01-06 11:27:50 +00:00
|
|
|
}
|
|
|
|
|
}
|