Skip to content

fix: ShareClassManager and SimplePriceManager - transfer shares underflow#746

Merged
hieronx merged 16 commits intomainfrom
scm-pending-issuance
Oct 17, 2025
Merged

fix: ShareClassManager and SimplePriceManager - transfer shares underflow#746
hieronx merged 16 commits intomainfrom
scm-pending-issuance

Conversation

@onnovisser
Copy link
Contributor

Product requirements

  • SCM and SimplePriceManager can underflow if shares are transferred before submitQueuedShares is called

Design notes

TODOs

  • [ ]

@onnovisser onnovisser marked this pull request as ready for review October 16, 2025 19:35
@onnovisser onnovisser changed the title refactor: SCM pending issuance and settle method fix: ShareClassManager and SimplePriceManager - transfer shares underflow Oct 16, 2025
Copy link
Contributor

@wischli wischli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me and seems feasible! Thanks for the fix. Overall, I'd love to see some assertions/tests in e2e in the future, definitely not this PR.


// When shares are transferred, the issuance in the SCM updates immediately,
// but in this contract they are tracked separately as transferredIn/Out.
// Here we get the diff between the old SPM issuance and the new SCM issuance,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit

Suggested change
// Here we get the diff between the old SPM issuance and the new SCM issuance,
// Here we get the diff between the old SCM issuance and the new SCM issuance,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional (Single Price Manager = SPM)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually clarified that it's the current stale SPM issuance

assertEq(toIssuance, 200);
assertEq(fromTransferredOut, 0);
assertEq(fromTransferredIn, 0);
assertEq(toTransferredIn, 50);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: IIUC, this is not 0 because we haven't called onUpdate for network 2 yet right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes exactly

mapping(PoolId => mapping(ShareClassId => Price)) public pricePoolPerShare;
mapping(PoolId => mapping(ShareClassId => ShareClassMetadata)) public metadata;
mapping(PoolId => mapping(ShareClassId => mapping(uint16 centrifugeId => uint128))) public issuance;
mapping(PoolId => mapping(ShareClassId => mapping(uint16 centrifugeId => IssuancePerNetwork))) internal
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should make this public. Otherwise there is no way to know the individual sum of issuances and revocations, if it is reverting.

Copy link
Contributor

@mustermeiszer mustermeiszer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good fix

onnovisser and others added 3 commits October 17, 2025 11:53
Co-authored-by: Jeroen <1748621+hieronx@users.noreply.github.com>
hieronx
hieronx previously approved these changes Oct 17, 2025
@hieronx hieronx merged commit 27ebe5c into main Oct 17, 2025
11 of 12 checks passed
@hieronx hieronx deleted the scm-pending-issuance branch October 17, 2025 10:09
@github-actions
Copy link

Coverage after merging scm-pending-issuance into main will be

99.01%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src/adapters
   AxelarAdapter.sol97.67%90%100%100%118
   LayerZeroAdapter.sol98.41%90%100%100%124
   RecoveryAdapter.sol100%100%100%100%
   WormholeAdapter.sol97.67%90%100%100%108
src/admin
   OpsGuardian.sol100%100%100%100%
   ProtocolGuardian.sol100%100%100%100%
   Root.sol100%100%100%100%
   TokenRecoverer.sol100%100%100%100%
src/core/hub
   Accounting.sol94.79%88%100%96.61%132, 134, 137, 141, 144
   Holdings.sol97.71%88.89%100%100%116, 237, 82
   Hub.sol93.98%81.13%93.02%97.54%269, 287, 305, 339, 343, 374–375, 413, 497–498, 543, 548, 585, 600, 87
   HubHandler.sol98%90.91%100%100%71
   HubRegistry.sol92.39%76.67%100%100%118, 124, 130, 35, 46, 79, 99
   ShareClassManager.sol100%100%100%100%
src/core/libraries
   PricingLib.sol100%100%100%100%
src/core/messaging
   GasService.sol97.94%100%100%96.92%106, 116
   Gateway.sol100%100%100%100%
   MessageDispatcher.sol99.60%98.55%100%100%699
   MessageProcessor.sol83.51%60.53%100%99.07%102, 105, 112, 115, 117, 128, 133, 142, 145, 148, 160, 163, 166, 171, 181, 184, 193, 196, 199, 212, 223, 228, 231, 235, 86, 88–89, 92–93, 96–97
   MultiAdapter.sol100%100%100%100%
src/core/messaging/libraries
   MessageLib.sol100%100%100%100%
src/core/spoke
   BalanceSheet.sol99.42%96.43%100%100%57
   PoolEscrow.sol100%100%100%100%
   ShareToken.sol92.41%60%94.44%98.04%100, 112, 144, 146, 32
   Spoke.sol97.40%89.39%100%100%131, 131–132, 132, 134, 91–92
   VaultRegistry.sol95.65%90.32%100%98.11%54, 60–62
src/core/spoke/factories
   PoolEscrowFactory.sol100%100%100%100%
   TokenFactory.sol100%100%100%100%
src/core/utils
   BatchedMulticall.sol100%100%100%100%
   ContractUpdater.sol100%100%100%100%
src/hooks
   BaseTransferHook.sol98.48%100%95.83%98.80%108
   FreelyTransferable.sol92.31%80%100%100%36
   FreezeOnly.sol100%100%100%100%
   FullRestrictions.sol95.24%88.89%100%100%44
   RedemptionRestrictions.sol85.71%50%100%100%36
src/hooks/libraries
   UpdateRestrictionMessageLib.sol90%50%100%100%40, 61, 82
src/managers/hub
   NAVManager.sol100%100%100%100%
   SimplePriceManager.sol100%100%100%100%
src/managers/spoke
   MerkleProofManager.sol97.01%87.50%100%100%103, 110
   OnOfframpManager.sol100%100%100%100%
   QueueManager.sol100%100%100%100%
src/managers/spoke/decoders
   BaseDecoder.sol100%100%100%100%
   CircleDecoder.sol83.33%100%100%75%22
   VaultDecoder.sol100%100%100%100%
src/misc
   Auth.sol100%100%100%100%
   ERC20.sol100%100%100%100%
   Escrow.sol56.25%33.33%100%66.67%17, 19, 23–24, 24, 24, 26
   Multicall.sol83.33%33.33%100%100%19, 19
   Recoverable.sol100%100%100%100%
   ReentrancyProtection.sol90%75%100%100%24
src/misc/libraries
   ArrayLib.sol100%100%100%100%
   BitmapLib.sol100%100%100%100%
   BytesLib.sol90.27%56%100%100%109, 120, 131, 14, 142, 153, 16, 164, 175, 186, 87
   CastLib.sol95.24%66.67%100%100%10, 34
   EIP712Lib.sol100%100%100%100%
   MathLib.sol93.46%76.19%100%97.33%34–35, 44, 46, 48, 50, 52
   MerkleProofLib.sol100%100%100%100%
   SafeTransferLib.sol96.97%92.86%100%100%75
   SignatureLib.sol95.24%80%100%100%17
   StringLib.sol100%100%100%100%
   TransientArrayLib.sol100%100%100%100%
   TransientBytesLib.sol100%100%100%100%
   TransientStorageLib.sol100%100%100%100%
src/valuations
   IdentityValuation.sol100%100%100%100%
   OracleValuation.sol100%100%100%100%
src/vaults
   AsyncRequestManager.sol96.34%84.95%100%99.63%193, 217, 220, 223, 226, 237, 249, 313, 347, 461, 466, 505, 507, 556, 563
   AsyncVault.sol96.25%83.33%95%98.15%147, 48
   BaseVaults.sol92.50%80.77%95.24%93.94%126, 139, 241, 311–312, 398–399, 87–88, 88, 88–90
   BatchRequestManager.sol100%100%100%100%
   RefundEscrow.sol100%100%100%100%
   SyncDepositVault.sol100%100%100%100%
   SyncManager.sol96.45%88.89%100%97.89%103–104, 106, 64, 69
   VaultRouter.sol87.31%52%100%94.19%113, 113, 115–116, 116, 118, 129–130, 149, 149, 161, 204, 76, 79–80, 92–93
src/vaults/factories
   AsyncVaultFactory.sol89.47%50%100%93.33%35, 47
   RefundEscrowFactory.sol100%100%100%100%
   SyncDepositVaultFactory.sol91.30%50%100%94.74%44, 59
src/vaults/libraries
   RequestCallbackMessageLib.sol89.58%50%100%100%104, 139, 38, 57, 77
   RequestMessageLib.sol89.74%50%100%100%37, 55, 72, 89

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants