mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-07-22 16:05:47 +00:00
Add multisig pending-operations UI, fix broken multisig address calc, new signing portal
- calculateMultisigAddress was completely broken (hex-decoded an SS58 string and never hashed the preimage) - fixed via @pezkuwi/util-crypto's real encodeMultiAddress/createKeyMulti, verified against the actual known multisig address on-chain. - ReservesDashboardPage had stale Noter/Berdevk addresses that don't match the real signers - centralized as BRIDGE_MULTISIG_SPECIFIC_ADDRESSES. - USDTBridge withdrawal called assets.burn directly as a single-signer extrinsic (always fails - only the multisig is Admin) while only checking status.isFinalized (a failed dispatch is still finalized, so it silently did nothing) - replaced with the correct transfer-to-custody flow the relayer actually watches for. - New MultisigOperationsPage (/multisig/pending) lists pending calls from real Multisig.Multisigs storage and lets any of the 5 signers approve/reject with their own wallet extension. - New standalone sign/ app (deployed separately at pezbridge-sign.pex.mom) - a dedicated, gated signing portal for the same operations, so signing isn't dependent on this app alone.
This commit is contained in:
+25
-16
@@ -6,7 +6,7 @@
|
||||
import type { ApiPromise } from '@pezkuwi/api';
|
||||
import type { SubmittableExtrinsic } from '@pezkuwi/api/types';
|
||||
import { Tiki } from './tiki';
|
||||
import { encodeAddress, sortAddresses } from '@pezkuwi/util-crypto';
|
||||
import { encodeMultiAddress, sortAddresses } from '@pezkuwi/util-crypto';
|
||||
|
||||
// ========================================
|
||||
// MULTISIG CONFIGURATION
|
||||
@@ -30,6 +30,21 @@ export const USDT_MULTISIG_CONFIG = {
|
||||
] as MultisigMember[],
|
||||
};
|
||||
|
||||
/**
|
||||
* Addresses for the two non-unique Tiki roles (Noter, Berdevk are held by all 21 validators,
|
||||
* so which specific validator sits on THIS multisig has to be pinned manually - it can't be
|
||||
* derived from the Tiki on-chain lookup alone). This is the single source of truth: it MUST
|
||||
* match the real 5 signatories the on-chain bridge multisig was actually derived from (see
|
||||
* res/validators-tiki.md "USDT Bridge Custody Multisig" and the usdt-bridge-multisig-migration
|
||||
* memory). Centralized here instead of copy-pasted per-page - a stale copy of these two
|
||||
* addresses previously sat in ReservesDashboardPage.tsx and didn't match any real signer,
|
||||
* which silently made every derived multisig address wrong.
|
||||
*/
|
||||
export const BRIDGE_MULTISIG_SPECIFIC_ADDRESSES: Record<string, string> = {
|
||||
Noter: '5ELgySrX5ZyK7EWXjj6bAedyTCcTNWDANbiiipsT5gnpoCEp', // Validator_04
|
||||
Berdevk: '5HWFZbhkZuTUySXu6ZXYKrTHBnWXHvWRKLozE22zhnwXGGxk', // Validator_02
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// MULTISIG MEMBER QUERIES
|
||||
// ========================================
|
||||
@@ -87,21 +102,15 @@ export function calculateMultisigAddress(
|
||||
threshold: number = USDT_MULTISIG_CONFIG.threshold,
|
||||
ss58Format: number = 42
|
||||
): string {
|
||||
// Sort members (multisig requires sorted order)
|
||||
const sortedMembers = sortAddresses(members);
|
||||
|
||||
// Create multisig address
|
||||
// Formula: blake2(b"modlpy/utilisuba" + concat(sorted_members) + threshold)
|
||||
const multisigId = encodeAddress(
|
||||
new Uint8Array([
|
||||
...Buffer.from('modlpy/utilisuba'),
|
||||
...sortedMembers.flatMap((addr) => Array.from(Buffer.from(addr, 'hex'))),
|
||||
threshold,
|
||||
]),
|
||||
ss58Format
|
||||
);
|
||||
|
||||
return multisigId;
|
||||
// Delegates to @pezkuwi/util-crypto's own createKeyMulti/encodeMultiAddress, which correctly
|
||||
// implements pallet_multisig's derivation (blake2_256 of
|
||||
// SCALE-encode(b"modlpy/utilisuba" ++ compact-len ++ sorted pubkeys ++ u16 threshold)). A
|
||||
// previous hand-rolled version here decoded each address with `Buffer.from(addr, 'hex')` -
|
||||
// treating an SS58 string as hex, which is simply wrong - and never hashed the preimage at
|
||||
// all, so it silently produced an address with no relationship to the real multisig account.
|
||||
// Caught by directly testing this function against the known real 5 bridge signatories,
|
||||
// which threw immediately instead of quietly returning a bogus address.
|
||||
return encodeMultiAddress(members, threshold, ss58Format);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user