From a0823ba07fe1d368ca6a8706d86ec275e195ed29 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Mon, 11 May 2026 07:03:56 -0600 Subject: [PATCH] chore(abi): sync tnt-core v0.15.0 (Round 4 audit consolidation) Regenerate ABIs from tnt-core@v0.15.0 (PRs #126, #127, #129) and fix the two callsites in this dapp that the v0.14/v0.15 breaking changes actually touched. Everything else either landed as additive surface or was outside our consumer set. ABI changes (auto-generated): - ITangleFull: + claimDisputeBond(), + pendingDisputeBondRefund(address); ServiceEscrow struct gains trailing __reservedAggregateCursor + subscriptionBaselineStake fields (positional reads at the old offsets are unchanged, named decoders ignore the new fields). - IMultiAssetDelegation: + getCumStakeSeconds(operator, asset) view, + AdapterChangeWhileDepositsExist error. - ValidatorPodManager (hand-maintained ABI under tangle-dapp/src/abi): drop removed `podOwnerShares`, retype `totalShares` int256 -> uint256, add `getSharesUint`, `recordBeaconChainDeposit`, `recordBeaconChainRebase`, and the new `BeaconRebase` event. Extend `SharesUpdated` / `WithdrawalQueued` / `WithdrawalCompleted` with their newly-appended fields (`newShares` retyped to uint256 to match share-pool semantics; trailing `assets` on the withdrawal events). Consumer fixes: - features/native-staking/useValidatorPodManager.ts: `usePodOwnerShares` now calls `getShares` instead of the removed `podOwnerShares` view. `getShares` returns int256, but the bigint shape used by PodOwnerInfo / DelegationCard / WithdrawalCard is preserved and the downstream renderers already clamp negative values for display. - operators/manage/components/modals/DisputeSlashModal.tsx: the bond hint text used to claim the bond was "refunded if dispute upheld"; v0.14.0 switched dispute-bond refunds to a pull pattern (cancelSlash no longer pushes), so reword to "claimable via claimDisputeBond if dispute upheld" to set the right expectation. - data/graphql/useSlashing.ts: add an inline NOTE on `useCancelSlashTx` documenting the pull-pattern + a TODO(v0.15.0) for the follow-up `useClaimDisputeBondTx` hook and disputer-side UI affordance. Out-of-scope deferred items (left as TODOs / not surfaced in UI yet): - claimDisputeBond() / pendingDisputeBondRefund(address) hooks + UI for the disputer-side refund claim flow. Tracked in the inline TODO above. - TangleToken.burn / burnFrom now revert with BurnDisabled(); no dapp callsite exposes a burn action today, so nothing to gate. - L2SlashingReceiver bridge deploy flow (proxy + initialize) is not invoked from the dapp; deploys live in tnt-core scripts. - billSubscription semantics shifted to TWAP-fair but the ABI signature is unchanged and we don't call it from the dapp. Verification: - yarn typecheck (tangle-dapp, tangle-cloud) -> clean - yarn lint (tangle-dapp, tangle-cloud, tangle-shared-ui) -> clean - prettier --check on every touched file -> clean Refs: tangle-network/tnt-core#126, #127, #129 --- .../components/modals/DisputeSlashModal.tsx | 2 +- .../src/abi/validatorPodManager.ts | 91 ++++++++++++++++++- .../hooks/useValidatorPodManager.ts | 8 +- .../src/abi/multiAssetDelegation.ts | 62 +++++++++++++ libs/tangle-shared-ui/src/abi/tangle.ts | 36 ++++++++ .../src/data/graphql/useSlashing.ts | 6 ++ 6 files changed, 197 insertions(+), 8 deletions(-) diff --git a/apps/tangle-cloud/src/pages/operators/manage/components/modals/DisputeSlashModal.tsx b/apps/tangle-cloud/src/pages/operators/manage/components/modals/DisputeSlashModal.tsx index 06ef5c2b35..0b83aed1bd 100644 --- a/apps/tangle-cloud/src/pages/operators/manage/components/modals/DisputeSlashModal.tsx +++ b/apps/tangle-cloud/src/pages/operators/manage/components/modals/DisputeSlashModal.tsx @@ -162,7 +162,7 @@ const DisputeSlashModal = ({ {disputeBond > BigInt(0) - ? `${formatEthAmount(disputeBond)} ETH (refunded if dispute upheld)` + ? `${formatEthAmount(disputeBond)} ETH (claimable via claimDisputeBond if dispute upheld)` : 'No bond required'} {isAlreadyDisputed && hasKnownDisputer ? ( diff --git a/apps/tangle-dapp/src/abi/validatorPodManager.ts b/apps/tangle-dapp/src/abi/validatorPodManager.ts index bc68a63962..638cbd59d1 100644 --- a/apps/tangle-dapp/src/abi/validatorPodManager.ts +++ b/apps/tangle-dapp/src/abi/validatorPodManager.ts @@ -29,6 +29,9 @@ export const VALIDATOR_POD_MANAGER_ABI = [ type: 'function', }, // Shares + // NOTE: tnt-core v0.15.0 refactored VPM to a share-pool model. The legacy + // `podOwnerShares` view is removed — readers must use `getShares` (int256, + // can be negative pre-rebase) or `getSharesUint` (uint256, clamped to 0). { inputs: [{ internalType: 'address', name: 'owner', type: 'address' }], name: 'getShares', @@ -38,18 +41,41 @@ export const VALIDATOR_POD_MANAGER_ABI = [ }, { inputs: [{ internalType: 'address', name: 'owner', type: 'address' }], - name: 'podOwnerShares', - outputs: [{ internalType: 'int256', name: '', type: 'int256' }], + name: 'getSharesUint', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function', }, { inputs: [], name: 'totalShares', - outputs: [{ internalType: 'int256', name: '', type: 'int256' }], + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function', }, + // Beacon-chain accounting (replaces removed recordBeaconChainEthBalanceUpdate). + { + inputs: [ + { internalType: 'address', name: 'podOwner', type: 'address' }, + { internalType: 'uint256', name: 'assets', type: 'uint256' }, + ], + name: 'recordBeaconChainDeposit', + outputs: [ + { internalType: 'uint256', name: 'mintedShares', type: 'uint256' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'podOwner', type: 'address' }, + { internalType: 'int256', name: 'assetsDelta', type: 'int256' }, + ], + name: 'recordBeaconChainRebase', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, // Operator Management { inputs: [], @@ -306,14 +332,57 @@ export const VALIDATOR_POD_MANAGER_ABI = [ }, { indexed: false, - internalType: 'int256', + internalType: 'uint256', name: 'newShares', - type: 'int256', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'totalAssets', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'totalSharesPool', + type: 'uint256', }, ], name: 'SharesUpdated', type: 'event', }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: false, + internalType: 'int256', + name: 'assetsDelta', + type: 'int256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'newTotalAssets', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'totalSharesPool', + type: 'uint256', + }, + ], + name: 'BeaconRebase', + type: 'event', + }, { anonymous: false, inputs: [ @@ -411,6 +480,12 @@ export const VALIDATOR_POD_MANAGER_ABI = [ name: 'shares', type: 'uint256', }, + { + indexed: false, + internalType: 'uint256', + name: 'assets', + type: 'uint256', + }, ], name: 'WithdrawalQueued', type: 'event', @@ -436,6 +511,12 @@ export const VALIDATOR_POD_MANAGER_ABI = [ name: 'shares', type: 'uint256', }, + { + indexed: false, + internalType: 'uint256', + name: 'assets', + type: 'uint256', + }, ], name: 'WithdrawalCompleted', type: 'event', diff --git a/apps/tangle-dapp/src/features/native-staking/hooks/useValidatorPodManager.ts b/apps/tangle-dapp/src/features/native-staking/hooks/useValidatorPodManager.ts index aa3ba30831..f7e99f5a6f 100644 --- a/apps/tangle-dapp/src/features/native-staking/hooks/useValidatorPodManager.ts +++ b/apps/tangle-dapp/src/features/native-staking/hooks/useValidatorPodManager.ts @@ -87,7 +87,11 @@ export const useGetPod = (ownerAddress: Address | undefined) => { }; }; -// Hook to get owner's shares +// Hook to get owner's shares. +// tnt-core v0.15.0: legacy `podOwnerShares` was removed during the share-pool +// refactor. `getShares` returns int256 (can be negative if a beacon rebase +// pushed the owner under their previous share count); UI keeps the bigint +// shape and downstream renderers already clamp at zero where needed. export const usePodOwnerShares = (ownerAddress: Address | undefined) => { const chainId = useChainId(); const contractAddress = getValidatorPodManagerAddress(chainId); @@ -95,7 +99,7 @@ export const usePodOwnerShares = (ownerAddress: Address | undefined) => { const { data, isLoading, error, refetch } = useReadContract({ address: contractAddress ?? undefined, abi: VALIDATOR_POD_MANAGER_ABI, - functionName: 'podOwnerShares', + functionName: 'getShares', args: ownerAddress ? [ownerAddress] : undefined, query: { enabled: !!ownerAddress && !!contractAddress, diff --git a/libs/tangle-shared-ui/src/abi/multiAssetDelegation.ts b/libs/tangle-shared-ui/src/abi/multiAssetDelegation.ts index 602dd69b0a..1629aab048 100644 --- a/libs/tangle-shared-ui/src/abi/multiAssetDelegation.ts +++ b/libs/tangle-shared-ui/src/abi/multiAssetDelegation.ts @@ -597,6 +597,52 @@ const ABI = [ ], stateMutability: 'view', }, + { + type: 'function', + name: 'getCumStakeSeconds', + inputs: [ + { + name: 'operator', + type: 'address', + internalType: 'address', + }, + { + name: 'asset', + type: 'tuple', + internalType: 'struct Types.Asset', + components: [ + { + name: 'kind', + type: 'uint8', + internalType: 'enum Types.AssetKind', + }, + { + name: 'token', + type: 'address', + internalType: 'address', + }, + ], + }, + ], + outputs: [ + { + name: 'cum', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'lastUpdate', + type: 'uint64', + internalType: 'uint64', + }, + { + name: 'currentStake', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, { type: 'function', name: 'getDelegation', @@ -2849,6 +2895,22 @@ const ABI = [ ], anonymous: false, }, + { + type: 'error', + name: 'AdapterChangeWhileDepositsExist', + inputs: [ + { + name: 'token', + type: 'address', + internalType: 'address', + }, + { + name: 'currentDeposits', + type: 'uint256', + internalType: 'uint256', + }, + ], + }, ] as const; export default ABI; diff --git a/libs/tangle-shared-ui/src/abi/tangle.ts b/libs/tangle-shared-ui/src/abi/tangle.ts index 322641cc3b..275ace1006 100644 --- a/libs/tangle-shared-ui/src/abi/tangle.ts +++ b/libs/tangle-shared-ui/src/abi/tangle.ts @@ -517,6 +517,13 @@ const ABI = [ outputs: [], stateMutability: 'nonpayable', }, + { + type: 'function', + name: 'claimDisputeBond', + inputs: [], + outputs: [], + stateMutability: 'nonpayable', + }, { type: 'function', name: 'claimRewards', @@ -2325,6 +2332,16 @@ const ABI = [ type: 'uint256', internalType: 'uint256', }, + { + name: '__reservedAggregateCursor', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'subscriptionBaselineStake', + type: 'uint256', + internalType: 'uint256', + }, ], }, ], @@ -3149,6 +3166,25 @@ const ABI = [ ], stateMutability: 'view', }, + { + type: 'function', + name: 'pendingDisputeBondRefund', + inputs: [ + { + name: 'disputer', + type: 'address', + internalType: 'address', + }, + ], + outputs: [ + { + name: '', + type: 'uint256', + internalType: 'uint256', + }, + ], + stateMutability: 'view', + }, { type: 'function', name: 'pendingRewards', diff --git a/libs/tangle-shared-ui/src/data/graphql/useSlashing.ts b/libs/tangle-shared-ui/src/data/graphql/useSlashing.ts index 73db661238..34d3676c82 100644 --- a/libs/tangle-shared-ui/src/data/graphql/useSlashing.ts +++ b/libs/tangle-shared-ui/src/data/graphql/useSlashing.ts @@ -1338,6 +1338,12 @@ export const useExecuteSlashBatchTx = () => { /** * Hook to cancel a slash proposal. + * + * NOTE (tnt-core v0.14.0): `cancelSlash` no longer auto-refunds the disputer's + * bond. After cancellation, the disputer must call `claimDisputeBond()` and + * may inspect their pending balance with `pendingDisputeBondRefund(address)`. + * TODO(v0.15.0): wire up a `useClaimDisputeBondTx` + dedicated UI affordance + * on the disputer-facing slash detail view (and surface the pending balance). */ export const useCancelSlashTx = () => { const chainId = useChainId();