Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7b9d1fc
refactor: replace null sentinel ambiguity with init-as-node bootstrap
thedavidmeister May 3, 2026
b81ea1e
test: pin _ensureBootstrap one-shot snapshot semantics
thedavidmeister May 3, 2026
de10f27
style: forge fmt
thedavidmeister May 3, 2026
f1b0f36
refactor: renumber ACTION_TYPE_INIT_V1 to bit 0 + regen pointers
thedavidmeister May 3, 2026
8e54534
test: replace remaining hardcoded action-type bits with constants
thedavidmeister May 3, 2026
4ad1908
test: replace remaining hardcoded action-type literals + fmt
thedavidmeister May 3, 2026
fd33899
test: receipt-side cursor monotonicity is list-order, not numeric
thedavidmeister May 3, 2026
202a1f0
chore: regen stale pointers + 0-index natspec scaffold
thedavidmeister May 3, 2026
acee041
Merge remote-tracking branch 'origin/main' into refactor/issue-79-nul…
thedavidmeister May 3, 2026
97ebdc1
refactor: 0-based indexing with NODE_NONE sentinel (WIP - test update…
thedavidmeister May 3, 2026
4ff46fd
test: pin null-cursor assertions to NODE_NONE in LibCorporateActionNo…
thedavidmeister May 3, 2026
d1aee6f
test: shift cursor assertions in StoxReceiptVault tests for 0-based s…
thedavidmeister May 3, 2026
37bc8a5
test: shift facet test indices for 0-based scheme (partial)
thedavidmeister May 3, 2026
08e9079
test: more facet test fixes for 0-based scheme
thedavidmeister May 3, 2026
4f19676
test: more facet test fixes — cancel pointer NODE_NONE, walk while loops
thedavidmeister May 3, 2026
60ccc91
test: update StoxReceipt mock vault for NODE_NONE no-match sentinel
thedavidmeister May 3, 2026
d8d6d56
test: invariant suite NODE_NONE updates and pre-bootstrap empty check
thedavidmeister May 3, 2026
bc065f3
chore: regen all pointers + update fallback routing test for 0-based
thedavidmeister May 3, 2026
9a41544
test: invariant test pre-bootstrap empty-array early return
thedavidmeister May 3, 2026
b832151
test: more LibCorporateActionNode fuzz NODE_NONE updates
thedavidmeister May 3, 2026
10fd954
style: forge fmt
thedavidmeister May 4, 2026
b71397a
test: InvariantVault.nextOfType handles NODE_NONE no-match sentinel
thedavidmeister May 4, 2026
7a62fcb
Merge remote-tracking branch 'origin/main' into refactor/issue-79-nul…
thedavidmeister May 4, 2026
20c355a
chore: regen pointers with hard rebuild (foundry cache was stale)
thedavidmeister May 4, 2026
d7f86df
test: add coverage for 6 0-based-refactor gaps + drop redundant NODE_…
thedavidmeister May 4, 2026
4f9d79e
test: pin 4 more 0-based-refactor gaps with mutation verification
thedavidmeister May 4, 2026
5fc3667
test: pin 3 more 0-based-refactor gaps with mutation verification
thedavidmeister May 4, 2026
c144fd2
test: pin 2 final 0-based-refactor gaps with mutation verification
thedavidmeister May 4, 2026
c80b568
chore: regen StoxCorporateActionsFacet pointers
thedavidmeister May 4, 2026
5628553
test: add 0-based bootstrap coverage from CodeRabbit review
thedavidmeister May 4, 2026
b991b08
test: pin "fold mutates only totalSupplyLatestCursor"
thedavidmeister May 4, 2026
4d1adb4
test: pin "fold walks around cancelled middle node"
thedavidmeister May 4, 2026
7a7b0ad
test: pin guard ordering in nextOfType / prevOfType
thedavidmeister May 4, 2026
38a8d91
test: align mock NextOfType empty-splits branch with no-more-nodes shape
thedavidmeister May 4, 2026
53559b1
chore: regen downstream vault pointers after facet pointer bump
thedavidmeister May 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/concrete/StoxCorporateActionsFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ pragma solidity =0.8.25;
import {ICorporateActionsV1} from "../interface/ICorporateActionsV1.sol";
import {LibCorporateAction, SCHEDULE_CORPORATE_ACTION, CANCEL_CORPORATE_ACTION} from "../lib/LibCorporateAction.sol";
import {ActionDoesNotExist} from "../error/ErrCorporateAction.sol";
import {CorporateActionNode, CompletionFilter, LibCorporateActionNode} from "../lib/LibCorporateActionNode.sol";
import {
CorporateActionNode,
CompletionFilter,
LibCorporateActionNode,
NODE_NONE
} from "../lib/LibCorporateActionNode.sol";
import {IAuthorizeV1} from "rain.vats/interface/IAuthorizeV1.sol";
import {OffchainAssetReceiptVault} from "rain.vats/concrete/vault/OffchainAssetReceiptVault.sol";

Expand Down Expand Up @@ -158,7 +163,10 @@ contract StoxCorporateActionsFacet is ICorporateActionsV1 {
returns (bytes memory parameters)
{
LibCorporateAction.CorporateActionStorage storage s = LibCorporateAction.getStorage();
if (cursor == 0 || cursor >= s.nodes.length) revert ActionDoesNotExist(cursor);
// Bounds check covers `NODE_NONE` (= type(uint256).max) implicitly:
// `s.nodes.length` is bounded by realistic schedule cadence, so any
// sentinel value comparable to max uint256 is >= length.
if (cursor >= s.nodes.length) revert ActionDoesNotExist(cursor);
parameters = s.nodes[cursor].parameters;
}

Expand Down
14 changes: 8 additions & 6 deletions src/concrete/StoxReceipt.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ import {LibReceiptRebase} from "../lib/LibReceiptRebase.sol";
/// pre-split underlying while holding a post-split share worth double).
///
/// Migration is lazy, identical in shape to the share-side model:
/// - Each `(holder, id)` pair tracks its own migration cursor — the 1-based
/// index of the last completed stock split node it has been migrated
/// through. Storage lives at a dedicated ERC-7201 namespace on this
/// contract (`LibCorporateActionReceipt`).
/// - Each `(holder, id)` pair tracks its own migration cursor — the
/// vault's node index of the last completed stock split this pair has
/// been migrated through. Storage lives at a dedicated ERC-7201
/// namespace on this contract (`LibCorporateActionReceipt`). The
/// default cursor 0 is the vault's bootstrap node — fresh pairs start
/// there.
/// - On every `_update` (transfer / mint / burn), both `from` and `to` are
/// migrated through all completed stock splits for each `id` in the
/// batch before the transfer executes.
Expand Down Expand Up @@ -67,8 +69,8 @@ contract StoxReceipt is Receipt {
/// applied.
/// @param account The holder whose `(account, id)` migration state changed.
/// @param id The receipt id.
/// @param fromCursor The `(account, id)` cursor before this migration
/// (0 means never migrated).
/// @param fromCursor The `(account, id)` cursor before this migration.
/// The default 0 is the vault's bootstrap node.
/// @param toCursor The `(account, id)` cursor after this migration.
/// @param oldBalance The raw stored balance before rasterization.
/// @param newBalance The raw stored balance after rasterization.
Expand Down
9 changes: 6 additions & 3 deletions src/concrete/StoxReceiptVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@ contract StoxReceiptVault is OffchainAssetReceiptVault {
/// `_migrateAccount`, before the mint / burn / transfer delta is
/// applied.
/// @param account The account whose migration state changed.
/// @param fromCursor The account's migration cursor before this migration
/// (0 means never migrated). Corresponds to the 1-based index of the last
/// completed corporate action this account had already seen.
/// @param fromCursor The account's migration cursor before this
/// migration. The default 0 corresponds to the bootstrap node (idx 0)
/// — every fresh holder starts there because the cursor mapping
/// defaults to 0 and bootstrap is identity for splits, so "no
/// migration applied" and "migrated through the identity bootstrap"
/// are the same state.
/// @param toCursor The account's migration cursor after this migration.
/// @param oldBalance The account's **stored** balance before rasterization
/// — i.e. the value returned by `LibERC20Storage.underlyingBalance(account)` at
Expand Down
8 changes: 4 additions & 4 deletions src/generated/StoxCorporateActionsFacet.pointers.sol

Large diffs are not rendered by default.

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/generated/StoxReceipt.pointers.sol

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/generated/StoxReceiptVault.pointers.sol

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/generated/StoxUnifiedDeployer.pointers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ pragma solidity ^0.8.25;
// file needs the contract to exist so that it can be compiled.

/// @dev Hash of the known bytecode.
bytes32 constant BYTECODE_HASH = bytes32(0xb39f6d3ba45e8e35a720e4490c48255196b1e3d8fc551aeec1d3ca1c54324d80);
bytes32 constant BYTECODE_HASH = bytes32(0x3bded1b6618cabcddbf6defae2ae227c5398eb8941e4d23f026bbd5fad62b628);

/// @dev The deterministic deploy address of the contract when deployed via
/// the Zoltu factory.
address constant DEPLOYED_ADDRESS = address(0x4A5a688771A17c90303FE4De95BfaFA3A0c80529);
address constant DEPLOYED_ADDRESS = address(0x00b845e5CF42Da8F5a25dB1B02b2843E11C28e38);

/// @dev The creation bytecode of the contract.
bytes constant CREATION_CODE =
hex"6080604052348015600e575f80fd5b506106308061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806301ffc9a714610038578063733e1f8d1461005f575b5f80fd5b61004b6100463660046102a3565b610074565b604051901515815260200160405180910390f35b61007261006d36600461042d565b61010c565b005b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f733e1f8d00000000000000000000000000000000000000000000000000000000148061010657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040517f4904fab30000000000000000000000000000000000000000000000000000000081525f90738e4a26b59e8ca70493e5b86882776714d2f900ed90634904fab39061015e908590600401610570565b6020604051808303815f875af115801561017a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019e9190610615565b6040517fd786858b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201529091505f907302be7f0b93a78685fa7312d2e587a5ad1f776f8c9063d786858b906024016020604051808303815f875af1158015610220573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102449190610615565b6040805133815273ffffffffffffffffffffffffffffffffffffffff858116602083015283168183015290519192507fa0d99d93cf7a5f89661fa0829369a7e4896e755871efe65440bab2429387d55b919081900360600190a1505050565b5f602082840312156102b3575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146102e2575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715610339576103396102e9565b60405290565b6040516080810167ffffffffffffffff81118282101715610339576103396102e9565b73ffffffffffffffffffffffffffffffffffffffff81168114610383575f80fd5b50565b5f82601f830112610395575f80fd5b813567ffffffffffffffff808211156103b0576103b06102e9565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156103f6576103f66102e9565b8160405283815286602085880101111561040e575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f6020828403121561043d575f80fd5b813567ffffffffffffffff80821115610454575f80fd5b9083019060408286031215610467575f80fd5b61046f610316565b823561047a81610362565b815260208301358281111561048d575f80fd5b9290920191608083870312156104a1575f80fd5b6104a961033f565b83356104b481610362565b81526020840135838111156104c7575f80fd5b6104d388828701610386565b6020830152506040840135838111156104ea575f80fd5b6104f688828701610386565b6040830152506060840135935061050c84610362565b60608101939093526020810192909252509392505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f73ffffffffffffffffffffffffffffffffffffffff808451166020840152602084015160408085015281815116606085015260208101516080808601526105bf60e0860182610524565b905060408201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08683030160a08701526105fa8282610524565b9150508260608301511660c086015280935050505092915050565b5f60208284031215610625575f80fd5b81516102e28161036256";
hex"6080604052348015600e575f80fd5b506106308061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806301ffc9a714610038578063733e1f8d1461005f575b5f80fd5b61004b6100463660046102a3565b610074565b604051901515815260200160405180910390f35b61007261006d36600461042d565b61010c565b005b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f733e1f8d00000000000000000000000000000000000000000000000000000000148061010657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040517f4904fab30000000000000000000000000000000000000000000000000000000081525f9073d6d64702bda5781fbe3cdb20174e123ddc8718c190634904fab39061015e908590600401610570565b6020604051808303815f875af115801561017a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019e9190610615565b6040517fd786858b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201529091505f907302be7f0b93a78685fa7312d2e587a5ad1f776f8c9063d786858b906024016020604051808303815f875af1158015610220573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102449190610615565b6040805133815273ffffffffffffffffffffffffffffffffffffffff858116602083015283168183015290519192507fa0d99d93cf7a5f89661fa0829369a7e4896e755871efe65440bab2429387d55b919081900360600190a1505050565b5f602082840312156102b3575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146102e2575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715610339576103396102e9565b60405290565b6040516080810167ffffffffffffffff81118282101715610339576103396102e9565b73ffffffffffffffffffffffffffffffffffffffff81168114610383575f80fd5b50565b5f82601f830112610395575f80fd5b813567ffffffffffffffff808211156103b0576103b06102e9565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156103f6576103f66102e9565b8160405283815286602085880101111561040e575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f6020828403121561043d575f80fd5b813567ffffffffffffffff80821115610454575f80fd5b9083019060408286031215610467575f80fd5b61046f610316565b823561047a81610362565b815260208301358281111561048d575f80fd5b9290920191608083870312156104a1575f80fd5b6104a961033f565b83356104b481610362565b81526020840135838111156104c7575f80fd5b6104d388828701610386565b6020830152506040840135838111156104ea575f80fd5b6104f688828701610386565b6040830152506060840135935061050c84610362565b60608101939093526020810192909252509392505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f73ffffffffffffffffffffffffffffffffffffffff808451166020840152602084015160408085015281815116606085015260208101516080808601526105bf60e0860182610524565b905060408201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08683030160a08701526105fa8282610524565b9150508260608301511660c086015280935050505092915050565b5f60208284031215610625575f80fd5b81516102e28161036256";

/// @dev The runtime bytecode of the contract.
bytes constant RUNTIME_CODE =
hex"608060405234801561000f575f80fd5b5060043610610034575f3560e01c806301ffc9a714610038578063733e1f8d1461005f575b5f80fd5b61004b6100463660046102a3565b610074565b604051901515815260200160405180910390f35b61007261006d36600461042d565b61010c565b005b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f733e1f8d00000000000000000000000000000000000000000000000000000000148061010657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040517f4904fab30000000000000000000000000000000000000000000000000000000081525f90738e4a26b59e8ca70493e5b86882776714d2f900ed90634904fab39061015e908590600401610570565b6020604051808303815f875af115801561017a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019e9190610615565b6040517fd786858b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201529091505f907302be7f0b93a78685fa7312d2e587a5ad1f776f8c9063d786858b906024016020604051808303815f875af1158015610220573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102449190610615565b6040805133815273ffffffffffffffffffffffffffffffffffffffff858116602083015283168183015290519192507fa0d99d93cf7a5f89661fa0829369a7e4896e755871efe65440bab2429387d55b919081900360600190a1505050565b5f602082840312156102b3575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146102e2575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715610339576103396102e9565b60405290565b6040516080810167ffffffffffffffff81118282101715610339576103396102e9565b73ffffffffffffffffffffffffffffffffffffffff81168114610383575f80fd5b50565b5f82601f830112610395575f80fd5b813567ffffffffffffffff808211156103b0576103b06102e9565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156103f6576103f66102e9565b8160405283815286602085880101111561040e575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f6020828403121561043d575f80fd5b813567ffffffffffffffff80821115610454575f80fd5b9083019060408286031215610467575f80fd5b61046f610316565b823561047a81610362565b815260208301358281111561048d575f80fd5b9290920191608083870312156104a1575f80fd5b6104a961033f565b83356104b481610362565b81526020840135838111156104c7575f80fd5b6104d388828701610386565b6020830152506040840135838111156104ea575f80fd5b6104f688828701610386565b6040830152506060840135935061050c84610362565b60608101939093526020810192909252509392505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f73ffffffffffffffffffffffffffffffffffffffff808451166020840152602084015160408085015281815116606085015260208101516080808601526105bf60e0860182610524565b905060408201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08683030160a08701526105fa8282610524565b9150508260608301511660c086015280935050505092915050565b5f60208284031215610625575f80fd5b81516102e28161036256";
hex"608060405234801561000f575f80fd5b5060043610610034575f3560e01c806301ffc9a714610038578063733e1f8d1461005f575b5f80fd5b61004b6100463660046102a3565b610074565b604051901515815260200160405180910390f35b61007261006d36600461042d565b61010c565b005b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f733e1f8d00000000000000000000000000000000000000000000000000000000148061010657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040517f4904fab30000000000000000000000000000000000000000000000000000000081525f9073d6d64702bda5781fbe3cdb20174e123ddc8718c190634904fab39061015e908590600401610570565b6020604051808303815f875af115801561017a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019e9190610615565b6040517fd786858b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201529091505f907302be7f0b93a78685fa7312d2e587a5ad1f776f8c9063d786858b906024016020604051808303815f875af1158015610220573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102449190610615565b6040805133815273ffffffffffffffffffffffffffffffffffffffff858116602083015283168183015290519192507fa0d99d93cf7a5f89661fa0829369a7e4896e755871efe65440bab2429387d55b919081900360600190a1505050565b5f602082840312156102b3575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146102e2575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715610339576103396102e9565b60405290565b6040516080810167ffffffffffffffff81118282101715610339576103396102e9565b73ffffffffffffffffffffffffffffffffffffffff81168114610383575f80fd5b50565b5f82601f830112610395575f80fd5b813567ffffffffffffffff808211156103b0576103b06102e9565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156103f6576103f66102e9565b8160405283815286602085880101111561040e575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f6020828403121561043d575f80fd5b813567ffffffffffffffff80821115610454575f80fd5b9083019060408286031215610467575f80fd5b61046f610316565b823561047a81610362565b815260208301358281111561048d575f80fd5b9290920191608083870312156104a1575f80fd5b6104a961033f565b83356104b481610362565b81526020840135838111156104c7575f80fd5b6104d388828701610386565b6020830152506040840135838111156104ea575f80fd5b6104f688828701610386565b6040830152506060840135935061050c84610362565b60608101939093526020810192909252509392505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f73ffffffffffffffffffffffffffffffffffffffff808451166020840152602084015160408085015281815116606085015260208101516080808601526105bf60e0860182610524565b905060408201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08683030160a08701526105fa8282610524565b9150508260608301511660c086015280935050505092915050565b5f60208284031215610625575f80fd5b81516102e28161036256";
Loading
Loading