fix(f02-mocks): match encoding format against f02's own vectors - #20
Conversation
There was a problem hiding this comment.
Pull request overview
This PR aligns the Solidity f02 (Reward actor) wire encoding/decoding with f02’s own DAG-CBOR serialization vectors, so the production encoder can be validated against canonical on-chain expectations instead of only matching the local mock.
Changes:
- Reworks
FVMRewardsto use shared CBOR primitives, shortest-form integer encoding, explicit width-guards, and addstryStepWeightRecords. - Updates the mock Reward actor and its tests to match the new parameter tuple shapes (single-field tuple wrappers, distribution encoding, cancel-pending null-id semantics).
- Adds
FVMRewardWire.t.solvector tests that assert the exact bytes dispatched to the mock, mirroring f02’s upstream vectors.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/lib/FVMRewards.sol |
Replaces ad-hoc encoders with shared DAG-CBOR primitives, adds width guards and StepWeightRecords support. |
test/mocks/FVMRewardActor.sol |
Updates mock decoding/behavior to match updated wire format; adds param-recording and claim-return override hooks. |
test/mocks/FVMRewardActor.t.sol |
Refactors tests to use new library wrappers and new registration/distribution semantics. |
test/mocks/FVMRewardWire.t.sol |
New “golden vector” tests pinning exact bytes emitted by the production encoder. |
Suppressed comments (2)
test/mocks/FVMRewardActor.sol:818
_decodeAddressaccepts any protocol-4 byte string of length 22 as an EVM address, but the comment specifies protocol-4 with the EAM namespace (0x0a). Without checking the namespace byte, non-EAM delegated addresses would be mis-decoded as valid EVM addresses.
} else if (protocol == 4 && len == 22) {
assembly ("memory-safe") {
addr := shr(96, calldataload(add(pos, 2)))
}
}
test/mocks/FVMRewardActor.sol:787
- This doc comment still describes decoding an f410 address and/or CBOR null, but
_decodeAddressno longer handles null and now supports both protocol-0 ID addresses and protocol-4 delegated addresses. Updating the comment avoids misleading future edits.
/// @dev Decodes an f410 delegated address wrapped in a CBOR byte string (0x04, 0x0a, 20
/// bytes) at absolute calldata position `pos`, or CBOR null (address(0)) for an IMPLICIT
/// stream's absent writer. The address bytes are big-endian, so one `calldataload` shifted
/// into place reads all 20 at once.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
cfba718 to
079cf15
Compare
|
@wjmelements anticipating one of your objections: I did replace your optimised, inlined cbor with a more compact form that could share across the implementations. |
079cf15 to
3473400
Compare
Also: - one set of CBOR primitives - addresses encode in both forms a contract can hold - add tryStepWeightRecords over a shared encoder, and guard each field against the width f02 declares - FVMRewardWire.t.sol mirrors actors/reward/tests/types_test.rs, asserting the bytes the mock received
3473400 to
904a142
Compare
…efining Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
…icate Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
…block Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
| /// @dev An implicit stream (null distribution) carries no share map. | ||
| error ImplicitStreamWithShares(); |
Also: