Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,12 @@ const VersionRow: FC<VersionRowProps> = ({
{version.binaryUri}
</a>
) : (
'—'
// tnt-core 0.19 no longer returns `binaryUri` on-chain — it
// is event-sourced. Until the indexer wiring lands it reads
// `null` here; show a graceful notice instead of a bare dash.
<span className="text-mono-100 dark:text-mono-80">
(unavailable on this chain)
</span>
)
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,13 @@ const OperatorExitPanel: FC<Props> = ({
</div>

{/* Current Exit Status */}
{/*
TODO(v019): `useCanScheduleExit` fail-closes to `{ canExit: false }` on
v019 chains (tnt-core 0.19 removed the `canScheduleExit` view), so the
Schedule-Exit button below is always gated off there and only the
yellow "unavailable" reason renders. Wire getExitStatus-based
eligibility in the hook to re-enable scheduling on v019.
*/}
{exitStatus === ExitStatus.None && (
<div className="space-y-3">
{canScheduleExit?.canExit ? (
Expand Down
26 changes: 17 additions & 9 deletions apps/tangle-dapp/src/pages/staking/withdraw/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -296,19 +296,27 @@ const StakingWithdrawForm: FC = () => {
const locks = res.result as Array<{
amount: bigint;
multiplier: number;
expiryBlock: bigint;
// The synced (0.18+) `MULTI_ASSET_DELEGATION_ABI` names field 2
// `expiryTimestamp`; viem keys decoded tuples by ABI component name,
// so this is the property to read on every revision. The *value* is a
// block number on `legacy` and a unix timestamp on `v018`/`v019` — the
// same positional slot (uint64), so the decode succeeds either way and
// only the comparison basis must branch below.
expiryTimestamp: bigint;
}>;

// tnt-core 0.18 redefined the LockInfo slot as a unix TIMESTAMP while
// keeping the same position/type, so the decode silently succeeds on
// both revisions — the comparison basis is what must branch. Comparing
// a timestamp against a block number reads "locked for decades".
// Pre-0.18 (`legacy`) stored `expiryBlock` as a BLOCK NUMBER, so it must
// be compared against the current block height. tnt-core 0.18 redefined
// the slot as a unix TIMESTAMP (seconds) and 0.19 kept that semantics, so
// `v018`/`v019` compare against wall-clock seconds. Comparing a timestamp
// against a block number (or vice versa) reads "locked for decades".
const isLegacyBlockBasis =
getTntCoreRevisionByChainId(chainId) === 'legacy';
const nowSeconds = BigInt(Math.floor(Date.now() / 1000));
const locked = locks.reduce((sum, lock) => {
const stillLocked =
getTntCoreRevisionByChainId(chainId) === 'v018'
? lock.expiryBlock > nowSeconds
: lock.expiryBlock > currentBlockNumber;
const stillLocked = isLegacyBlockBasis
? lock.expiryTimestamp > currentBlockNumber
: lock.expiryTimestamp > nowSeconds;
return stillLocked ? sum + lock.amount : sum;
}, BigInt(0));

Expand Down
28 changes: 23 additions & 5 deletions libs/dapp-config/src/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,31 @@ export const ETHEREUM_HOLESKY_CONTRACTS: ContractAddresses = {
* - `v018`: tnt-core 0.18 greenfield redeploys — `operatorCount` moved to the
* `blueprintOperatorCount(uint64)` view (struct is 6 fields; decoding the
* legacy 7-field tuple throws), display prose is event-sourced from
* `BlueprintDefinitionRecorded`, and the `LockInfo` slot named
* `expiryBlock` carries a unix TIMESTAMP.
* `BlueprintDefinitionRecorded`, and the third `LockInfo` slot — renamed
* `expiryBlock` -> `expiryTimestamp` in the synced ABI, same uint64 position
* — carries a unix TIMESTAMP (seconds) rather than a block number.
* - `v019`: tnt-core 0.19 hash+emit shrink — several on-chain reads lost
* storage fields that are now event-sourced. The `getSlashProposal` tuple
* dropped `proposedAt` / `disputeReason` / `disputedAt`; the binary-version
* read (`getBinaryVersion` / `effectiveBinaryVersion`) dropped `binaryUri`;
* the attestation read (`getAttestation` / `listAttestations`) dropped
* `reportUri`; `blueprintSources(uint64)->BlueprintSource[]` was replaced by
* `blueprintSourcesHash(uint64)->bytes32` (the source list is event-sourced;
* the `setBlueprintSources` WRITE still takes the full `BlueprintSource[]`);
* and the `canScheduleExit(uint64,address)` view was removed (derive from
* `getExitStatus`). `LockInfo.expiryTimestamp` keeps the v018 semantics —
* a uint64 unix TIMESTAMP (seconds), NOT a block number — so the withdraw
* lock/countdown math compares it against wall-clock seconds, not block
* height, exactly as on v018 (confirmed against tnt-core
* `Types.LockInfo.expiryTimestamp`). Publish/attest WRITE params are
* unchanged — only the stored/returned fields moved off-chain. Decoding a
* v0.18 tuple against v0.19 returndata throws, so these reads must select the
* shorter ABI by revision; do not merge the two entries into one ABI.
*
* Flip a chain to `v018` in the same change that updates its addresses to
* the redeployed contracts — never separately.
* Flip a chain to `v018` / `v019` in the same change that updates its
* addresses to the redeployed contracts — never separately.
*/
export type TntCoreRevision = 'legacy' | 'v018';
export type TntCoreRevision = 'legacy' | 'v018' | 'v019';

export const getTntCoreRevisionByChainId = (
chainId: number,
Expand Down
16 changes: 8 additions & 8 deletions libs/tangle-shared-ui/src/abi/blueprintServiceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,11 +387,6 @@ const ABI = [
type: 'bytes32',
internalType: 'bytes32',
},
{
name: 'binaryUri',
type: 'string',
internalType: 'string',
},
{
name: 'attestationHash',
type: 'bytes32',
Expand All @@ -409,6 +404,11 @@ const ABI = [
},
],
},
{
name: 'binaryUri',
type: 'string',
internalType: 'string',
},
],
outputs: [],
stateMutability: 'nonpayable',
Expand Down Expand Up @@ -530,9 +530,9 @@ const ABI = [
internalType: 'address',
},
{
name: 'inputs',
type: 'bytes',
internalType: 'bytes',
name: 'inputsHash',
type: 'bytes32',
internalType: 'bytes32',
},
{
name: 'outputs',
Expand Down
2 changes: 1 addition & 1 deletion libs/tangle-shared-ui/src/abi/multiAssetDelegation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ const ABI = [
internalType: 'enum Types.LockMultiplier',
},
{
name: 'expiryBlock',
name: 'expiryTimestamp',
type: 'uint64',
internalType: 'uint64',
},
Expand Down
90 changes: 90 additions & 0 deletions libs/tangle-shared-ui/src/abi/operatorStatusRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,11 @@ const ABI = [
],
anonymous: false,
},
{
type: 'error',
name: 'AlreadyRegistered',
inputs: [],
},
{
type: 'error',
name: 'ECDSAInvalidSignature',
Expand Down Expand Up @@ -1589,6 +1594,81 @@ const ABI = [
},
],
},
{
type: 'error',
name: 'InternalOnly',
inputs: [],
},
{
type: 'error',
name: 'IntervalTooShort',
inputs: [],
},
{
type: 'error',
name: 'InvalidBounds',
inputs: [],
},
{
type: 'error',
name: 'InvalidMaxMissed',
inputs: [],
},
{
type: 'error',
name: 'InvalidSignature',
inputs: [],
},
{
type: 'error',
name: 'NameTooLong',
inputs: [],
},
{
type: 'error',
name: 'NotAuthorized',
inputs: [],
},
{
type: 'error',
name: 'NotRegistered',
inputs: [],
},
{
type: 'error',
name: 'NotRegisteredOperator',
inputs: [],
},
{
type: 'error',
name: 'NotServiceOwner',
inputs: [],
},
{
type: 'error',
name: 'NotSlashingOracle',
inputs: [],
},
{
type: 'error',
name: 'OnlyTangleCore',
inputs: [],
},
{
type: 'error',
name: 'OperatorNotEligibleForRemoval',
inputs: [],
},
{
type: 'error',
name: 'OperatorSlashed',
inputs: [],
},
{
type: 'error',
name: 'OperatorUnknown',
inputs: [],
},
{
type: 'error',
name: 'OwnableInvalidOwner',
Expand All @@ -1611,6 +1691,16 @@ const ABI = [
},
],
},
{
type: 'error',
name: 'TooManyDefinitions',
inputs: [],
},
{
type: 'error',
name: 'ZeroAddress',
inputs: [],
},
] as const;

export default ABI;
Loading
Loading