|
| 1 | +import { Address, TransactionEIP7702 } from 'viem' |
| 2 | +import { recoverAuthorizationAddress, SignedAuthorization, SignedAuthorizationList } from 'viem/experimental' |
| 3 | + |
| 4 | +import { DELEGATION_MAGIC_PREFIX } from '../constants' |
| 5 | + |
| 6 | +export type RecoveredAuthorizationMap = Record<Address, SignedAuthorization> |
| 7 | + |
| 8 | +export class Delegation { |
| 9 | + /** |
| 10 | + * Recovers the signers of each authorization within the list sent in the transaction |
| 11 | + * @dev this can also return just the contractAddress each signer is delegated to |
| 12 | + * @param transaction : TransactionEIP7702 |
| 13 | + * @returns : Promise<RecoveredAuthorizationMap> |
| 14 | + */ |
| 15 | + public static parseAuthorizationListFromTransaction(transaction: TransactionEIP7702): Promise<RecoveredAuthorizationMap> { |
| 16 | + return this.parseAuthorizationList(transaction.authorizationList) |
| 17 | + } |
| 18 | + |
| 19 | + /** |
| 20 | + * Recovers the signers of each authorization in the list |
| 21 | + * @param authorizationList : SignedAuthorizationList |
| 22 | + * @returns : Promise<RecoveredAuthorizationMap> |
| 23 | + */ |
| 24 | + public static async parseAuthorizationList(authorizationList: SignedAuthorizationList): Promise<RecoveredAuthorizationMap> { |
| 25 | + // recover each authorization |
| 26 | + const result: RecoveredAuthorizationMap = {} |
| 27 | + for (const authorization of authorizationList) { |
| 28 | + const signer = await recoverAuthorizationAddress({ authorization }) |
| 29 | + result[signer] = authorization |
| 30 | + } |
| 31 | + return result |
| 32 | + } |
| 33 | + |
| 34 | + /// Parses a delegation from an address's code |
| 35 | + /// @dev will throw if the code is not a valid delegation per EIP7702 spec |
| 36 | + public static parseFromCode(code: `0x${string}`): Address { |
| 37 | + if(code.length !== 48) { |
| 38 | + throw new Error(`Invalid delegation length: ${code.length}`) |
| 39 | + } |
| 40 | + // parse out magic prefix which is 4 bytes |
| 41 | + const magicPrefix = code.slice(0, 8) |
| 42 | + if(magicPrefix !== DELEGATION_MAGIC_PREFIX) { |
| 43 | + throw new Error(`Invalid delegation magic prefix: ${magicPrefix}`) |
| 44 | + } |
| 45 | + const delegation = code.slice(8) |
| 46 | + return `0x${delegation}` as Address |
| 47 | + } |
| 48 | +} |
0 commit comments