Skip to content

Commit

Permalink
Merge pull request #170 from zerodevapp/feat/update-signers
Browse files Browse the repository at this point in the history
feat: add update signers feature to multi-chain-weighted-validator plugin
  • Loading branch information
adnpark authored Aug 23, 2024
2 parents d07daf9 + 538e6a4 commit 27725a5
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 83 deletions.
18 changes: 18 additions & 0 deletions plugins/multi-chain-weighted-validator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# @zerodev/multi-chain-weighted-validator

## 5.3.0-alpha-7

### Patch Changes

- Update contract address

## 5.3.0-alpha-6

### Patch Changes

- Rollback contract version to 5.3.0-alpha-4

## 5.3.0-alpha-5

### Patch Changes

- Added support for `renew` signers config.

## 5.3.0-alpha-4

### Patch Changes
Expand Down
7 changes: 7 additions & 0 deletions plugins/multi-chain-weighted-validator/abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ export const MultiChainWeightedValidatorAbi = [
outputs: [],
stateMutability: "payable"
},
{
type: "function",
name: "renew",
inputs: [{ name: "_data", type: "bytes", internalType: "bytes" }],
outputs: [],
stateMutability: "nonpayable"
},
{
type: "function",
name: "proposalStatus",
Expand Down
2 changes: 1 addition & 1 deletion plugins/multi-chain-weighted-validator/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const getRecoveryAction = (entryPoint: EntryPoint): Action => {
}

export const MULTI_CHAIN_WEIGHTED_VALIDATOR_ADDRESS_V07 =
"0x3f1ebD30816085c0F8f1b88d066609b8923B8422"
"0xA99cD3c93773dA7f321A28a97648b608f347E6A1"

export enum SIGNER_TYPE {
ECDSA = "0x01",
Expand Down
4 changes: 4 additions & 0 deletions plugins/multi-chain-weighted-validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@ import {
type WeightedSigner,
type WeightedValidatorConfig,
createMultiChainWeightedValidator,
getCurrentSigners,
getUpdateConfigCall,
getValidatorAddress
} from "./toMultiChainWeightedValidatorPlugin.js"

export {
createMultiChainWeightedValidator,
getUpdateConfigCall,
getCurrentSigners,
type WeightedValidatorConfig,
type WeightedSigner,
getValidatorAddress,
Expand Down
2 changes: 1 addition & 1 deletion plugins/multi-chain-weighted-validator/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zerodev/multi-chain-weighted-validator",
"version": "5.3.0-alpha-4",
"version": "5.3.0-alpha-7",
"author": "ZeroDev",
"main": "./_cjs/index.js",
"module": "./_esm/index.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
type Transport,
type TypedDataDefinition,
encodeAbiParameters,
encodeFunctionData,
zeroAddress
} from "viem"
import { toAccount } from "viem/accounts"
Expand Down Expand Up @@ -309,91 +310,121 @@ export async function createMultiChainWeightedValidator<
}
}

// [TODO]
// export function getUpdateConfigCall<entryPoint extends EntryPoint>(
// entryPointAddress: entryPoint,
// newConfig: WeightedValidatorConfig
// ): {
// to: Address
// value: bigint
// data: Hex
// } {
// const signers = [...newConfig.signers].sort(sortByPublicKey)
// const validatorAddress = getValidatorAddress(entryPointAddress)
// TODO: move to client actions?
// -- approveUpdateConfigUserOp
// -- sendUpdateConfigUserOp
export function getUpdateConfigCall<entryPoint extends EntryPoint>(
entryPointAddress: entryPoint,
config: WeightedValidatorConfig
): {
to: Address
value: bigint
data: Hex
} {
const validatorAddress = getValidatorAddress(entryPointAddress)

// return {
// to: validatorAddress,
// value: 0n,
// data: encodeFunctionData({
// abi: MultiChainWeightedValidatorAbi,
// functionName: "renew",
// args: [
// signers.map((signer) => signer.address) ?? [],
// signers.map((signer) => signer.weight) ?? [],
// newConfig.threshold,
// newConfig.delay || 0
// ]
// })
// }
// }

// [TODO]
// export async function getCurrentSigners<
// entryPoint extends EntryPoint,
// TTransport extends Transport = Transport,
// TChain extends Chain | undefined = Chain | undefined
// >(
// client: Client<TTransport, TChain, undefined>,
// {
// entryPoint: entryPointAddress,
// multiSigAccountAddress,
// validatorAddress
// }: {
// entryPoint: entryPoint
// multiSigAccountAddress: Address
// validatorAddress?: Address
// }
// ): Promise<Array<{ address: Address; weight: number }>> {
// validatorAddress =
// validatorAddress ?? getValidatorAddress(entryPointAddress)
// if (!validatorAddress) {
// throw new Error("Validator address not provided")
// }
// const signers: Array<{ address: Address; weight: number }> = []
// let nextGuardian: Address
// Check if sum of weights is equal or greater than threshold
let totalWeight = 0
for (const signer of config.signers) {
totalWeight += signer.weight
}
if (totalWeight < config.threshold) {
throw new Error(
`Sum of weights (${totalWeight}) is less than threshold (${config.threshold})`
)
}

// // Fetch first guardian info from weightedStorage
// const weightedStorage = await getAction(
// client,
// readContract,
// "readContract"
// )({
// abi: MultiChainWeightedValidatorAbi,
// address: validatorAddress,
// functionName: "weightedStorage",
// args: [multiSigAccountAddress]
// })
// sort signers by address in descending order
const configSigners = config
? [...config.signers]
.map((signer) =>
typeof signer.publicKey === "object"
? {
...signer,
publicKey: encodeWebAuthnPubKey(
signer.publicKey
) as Hex
}
: { ...signer, publicKey: signer.publicKey as Hex }
)
.sort(sortByPublicKey)
: []

// nextGuardian = weightedStorage[3]
return {
to: validatorAddress,
value: 0n,
data: encodeFunctionData({
abi: MultiChainWeightedValidatorAbi,
functionName: "renew",
args: [
concatHex([
toHex(config.threshold, { size: 3 }),
toHex(config.delay || 0, { size: 6 }),
encodeAbiParameters(
[{ name: "guardiansData", type: "bytes[]" }],
[
configSigners.map((cfg) =>
concatHex([
cfg.publicKey.length === 42
? SIGNER_TYPE.ECDSA
: SIGNER_TYPE.PASSKEY,
toHex(cfg.weight, { size: 3 }),
cfg.publicKey
])
)
]
)
])
]
})
}
}

// // Loop until nextGuardian is the address(maxUint160) value
// while (nextGuardian !== "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF") {
// const guardianStorage = await getAction(
// client,
// readContract,
// "readContract"
// )({
// abi: MultiChainWeightedValidatorAbi,
// address: validatorAddress,
// functionName: "guardian",
// args: [nextGuardian, multiSigAccountAddress]
// })
export async function getCurrentSigners<
entryPoint extends EntryPoint,
TTransport extends Transport = Transport,
TChain extends Chain | undefined = Chain | undefined
>(
client: Client<TTransport, TChain, undefined>,
{
entryPoint: entryPointAddress,
multiChainWeightedAccountAddress
}: {
entryPoint: entryPoint
multiChainWeightedAccountAddress: Address
}
): Promise<Array<{ encodedPublicKey: Hex; weight: number }>> {
const validatorAddress = getValidatorAddress(entryPointAddress)

// const guardianWeight = guardianStorage[0]
// signers.push({ address: nextGuardian, weight: guardianWeight })
const multiChainWeightedStorage = await getAction(
client,
readContract,
"readContract"
)({
abi: MultiChainWeightedValidatorAbi,
address: validatorAddress,
functionName: "multiChainWeightedStorage",
args: [multiChainWeightedAccountAddress]
})

// nextGuardian = guardianStorage[1]
// }
const guardiansLength = multiChainWeightedStorage[3]

// return signers
// }
const signers: Array<{ encodedPublicKey: Hex; weight: number }> = []
for (let i = 0; i < guardiansLength; i++) {
const guardian = await getAction(
client,
readContract,
"readContract"
)({
abi: MultiChainWeightedValidatorAbi,
address: validatorAddress,
functionName: "guardian",
args: [BigInt(i), multiChainWeightedAccountAddress]
})
signers.push({
encodedPublicKey: guardian[2],
weight: guardian[1]
})
}
return signers
}

0 comments on commit 27725a5

Please sign in to comment.