Skip to content
Draft
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
20 changes: 20 additions & 0 deletions governance/xc_admin/packages/xc_admin_common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,16 @@
"default": "./dist/esm/governance_payload/SetWormholeAddress.mjs"
}
},
"./governance_payload/UpdateTrustedSigner": {
"require": {
"types": "./dist/cjs/governance_payload/UpdateTrustedSigner.d.ts",
"default": "./dist/cjs/governance_payload/UpdateTrustedSigner.cjs"
},
"import": {
"types": "./dist/esm/governance_payload/UpdateTrustedSigner.d.ts",
"default": "./dist/esm/governance_payload/UpdateTrustedSigner.mjs"
}
},
"./governance_payload/UpgradeContract": {
"require": {
"types": "./dist/cjs/governance_payload/UpgradeContract.d.ts",
Expand All @@ -238,6 +248,16 @@
"default": "./dist/esm/governance_payload/UpgradeContract.mjs"
}
},
"./governance_payload/UpgradeLazerContract": {
"require": {
"types": "./dist/cjs/governance_payload/UpgradeLazerContract.d.ts",
"default": "./dist/cjs/governance_payload/UpgradeLazerContract.cjs"
},
"import": {
"types": "./dist/esm/governance_payload/UpgradeLazerContract.d.ts",
"default": "./dist/esm/governance_payload/UpgradeLazerContract.mjs"
}
},
"./governance_payload/WithdrawFee": {
"require": {
"types": "./dist/cjs/governance_payload/WithdrawFee.d.ts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import {
EvmExecutorAction,
EvmExecute,
StarknetSetWormholeAddress,
LazerAction,
UpgradeLazerContract256Bit,
UpdateTrustedSigner264Bit,
} from "..";
import * as fc from "fast-check";
import { type ChainName, CHAINS } from "../chains";
Expand Down Expand Up @@ -282,6 +285,39 @@ test("GovernancePayload ser/de", (done) => {
),
).toBeTruthy();

const upgradeLazerContract = new UpgradeLazerContract256Bit(
"sui",
"043d0ed8155263af0862372df3af9403c502358661f317f62fbdc026d03beaee",
);
const upgradeLazerContractBuffer = upgradeLazerContract.encode();
console.log(upgradeLazerContractBuffer.toJSON());
expect(
upgradeLazerContractBuffer.equals(
Buffer.from([
80, 84, 71, 77, 3, 0, 0, 21, 4, 61, 14, 216, 21, 82, 99, 175, 8, 98, 55,
45, 243, 175, 148, 3, 197, 2, 53, 134, 97, 243, 23, 246, 47, 189, 192,
38, 208, 59, 234, 238,
]),
),
).toBeTruthy();

const updateTrustedSigner = new UpdateTrustedSigner264Bit(
"sui",
"03a4380f01136eb2640f90c17e1e319e02bbafbeef2e6e67dc48af53f9827e155b",
10794n,
);
const updateTrustedSignerBuffer = updateTrustedSigner.encode();
console.log(updateTrustedSignerBuffer.toJSON());
expect(
updateTrustedSignerBuffer.equals(
Buffer.from([
80, 84, 71, 77, 3, 1, 0, 21, 3, 164, 56, 15, 1, 19, 110, 178, 100, 15,
144, 193, 126, 30, 49, 158, 2, 187, 175, 190, 239, 46, 110, 103, 220,
72, 175, 83, 249, 130, 126, 21, 91, 0, 0, 0, 0, 0, 0, 42, 42,
]),
),
).toBeTruthy();

done();
});

Expand All @@ -291,6 +327,7 @@ function governanceHeaderArb(): Arbitrary<PythGovernanceHeader> {
...Object.keys(ExecutorAction),
...Object.keys(TargetAction),
...Object.keys(EvmExecutorAction),
...Object.keys(LazerAction),
] as ActionName[];
const actionArb = fc.constantFrom(...actions);
const targetChainIdArb = fc.constantFrom(
Expand Down Expand Up @@ -451,6 +488,23 @@ function governanceActionArb(): Arbitrary<PythGovernanceAction> {
expo,
);
});
} else if (header.action === "UpgradeLazerContract") {
return hexBytesArb({ minLength: 32, maxLength: 32 }).map((buffer) => {
return new UpgradeLazerContract256Bit(header.targetChainId, buffer);
});
} else if (header.action === "UpdateTrustedSigner") {
return fc
.record({
publicKey: hexBytesArb({ minLength: 33, maxLength: 33 }),
expiresAt: fc.bigInt({ min: 0n, max: 2n ** 64n - 1n }),
})
.map(({ publicKey, expiresAt }) => {
return new UpdateTrustedSigner264Bit(
header.targetChainId,
publicKey,
expiresAt,
);
});
} else {
throw new Error("Unsupported action type");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export const EvmExecutorAction = {
Execute: 0,
} as const;

export const LazerAction = {
UpgradeLazerContract: 0,
UpdateTrustedSigner: 1,
};

/** Helper to get the ActionName from a (moduleId, actionId) tuple*/
export function toActionName(
deserialized: Readonly<{ moduleId: number; actionId: number }>,
Expand Down Expand Up @@ -63,14 +68,22 @@ export function toActionName(
deserialized.actionId == 0
) {
return "Execute";
} else if (deserialized.moduleId == MODULE_LAZER) {
switch (deserialized.actionId) {
case 0:
return "UpgradeLazerContract";
case 1:
return "UpdateTrustedSigner";
}
}
return undefined;
}

export declare type ActionName =
| keyof typeof ExecutorAction
| keyof typeof TargetAction
| keyof typeof EvmExecutorAction;
| keyof typeof EvmExecutorAction
| keyof typeof LazerAction;

/** Governance header that should be in every Pyth crosschain governance message*/
export class PythGovernanceHeader {
Expand Down Expand Up @@ -136,9 +149,12 @@ export class PythGovernanceHeader {
} else if (this.action in TargetAction) {
module = MODULE_TARGET;
action = TargetAction[this.action as keyof typeof TargetAction];
} else {
} else if (this.action in EvmExecutorAction) {
module = MODULE_EVM_EXECUTOR;
action = EvmExecutorAction[this.action as keyof typeof EvmExecutorAction];
} else {
module = MODULE_LAZER;
action = LazerAction[this.action as keyof typeof LazerAction];
}
if (toChainId(this.targetChainId) === undefined)
throw new Error(`Invalid chain id ${this.targetChainId}`);
Expand All @@ -159,7 +175,13 @@ export const MAGIC_NUMBER = 0x4d475450;
export const MODULE_EXECUTOR = 0;
export const MODULE_TARGET = 1;
export const MODULE_EVM_EXECUTOR = 2;
export const MODULES = [MODULE_EXECUTOR, MODULE_TARGET, MODULE_EVM_EXECUTOR];
export const MODULE_LAZER = 3;
export const MODULES = [
MODULE_EXECUTOR,
MODULE_TARGET,
MODULE_EVM_EXECUTOR,
MODULE_LAZER,
];

export interface PythGovernanceAction {
readonly targetChainId: ChainName;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { ChainName } from "../chains";
import { PythGovernanceActionImpl } from "./PythGovernanceAction";
import * as BufferLayout from "@solana/buffer-layout";
import * as BufferLayoutExt from "./BufferLayoutExt";

// 33-byte signer address, used by Sui
export class UpdateTrustedSigner264Bit extends PythGovernanceActionImpl {
static layout: BufferLayout.Structure<
Readonly<{ publicKey: string; expiresAt: bigint }>
> = BufferLayout.struct([
BufferLayoutExt.hexBytes(33, "publicKey"),
BufferLayoutExt.u64be("expiresAt"),
]);

constructor(
targetChainId: ChainName,
readonly publicKey: string,
readonly expiresAt: bigint,
) {
super(targetChainId, "UpdateTrustedSigner");
}

static decode(data: Buffer): UpdateTrustedSigner264Bit | undefined {
const decoded = PythGovernanceActionImpl.decodeWithPayload(
data,
"UpdateTrustedSigner",
this.layout,
);
if (!decoded) return undefined;

return new UpdateTrustedSigner264Bit(
decoded[0].targetChainId,
decoded[1].publicKey,
decoded[1].expiresAt,
);
}

encode(): Buffer {
return super.encodeWithPayload(UpdateTrustedSigner264Bit.layout, {
publicKey: this.publicKey,
expiresAt: this.expiresAt,
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { ChainName } from "../chains";
import { PythGovernanceActionImpl } from "./PythGovernanceAction";
import * as BufferLayout from "@solana/buffer-layout";
import * as BufferLayoutExt from "./BufferLayoutExt";

// Used by Sui
export class UpgradeLazerContract256Bit extends PythGovernanceActionImpl {
static layout: BufferLayout.Structure<Readonly<{ hash: string }>> =
BufferLayout.struct([BufferLayoutExt.hexBytes(32, "hash")]);

constructor(
targetChainId: ChainName,
readonly hash: string,
) {
super(targetChainId, "UpgradeLazerContract");
}

static decode(data: Buffer): UpgradeLazerContract256Bit | undefined {
const decoded = PythGovernanceActionImpl.decodeWithPayload(
data,
"UpgradeLazerContract",
this.layout,
);
if (!decoded) return undefined;

return new UpgradeLazerContract256Bit(
decoded[0].targetChainId,
decoded[1].hash,
);
}

encode(): Buffer {
return super.encodeWithPayload(UpgradeLazerContract256Bit.layout, {
hash: this.hash,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
import { EvmExecute } from "./ExecuteAction";
import { SetTransactionFee } from "./SetTransactionFee";
import { WithdrawFee } from "./WithdrawFee";
import { UpgradeLazerContract256Bit } from "./UpgradeLazerContract";
import { UpdateTrustedSigner264Bit } from "./UpdateTrustedSigner";

/** Decode a governance payload */
export function decodeGovernancePayload(
Expand Down Expand Up @@ -79,6 +81,10 @@ export function decodeGovernancePayload(
return SetTransactionFee.decode(data);
case "WithdrawFee":
return WithdrawFee.decode(data);
case "UpgradeLazerContract":
return UpgradeLazerContract256Bit.decode(data);
case "UpdateTrustedSigner":
return UpdateTrustedSigner264Bit.decode(data);
default:
return undefined;
}
Expand All @@ -96,3 +102,5 @@ export * from "./SetTransactionFee";
export * from "./SetWormholeAddress";
export * from "./ExecuteAction";
export * from "./WithdrawFee";
export * from "./UpgradeLazerContract";
export * from "./UpdateTrustedSigner";
10 changes: 10 additions & 0 deletions lazer/contracts/sui/Move.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ edition = "2024.beta"
[addresses]
pyth_lazer = "0x0"

[dependencies.Wormhole]
git = "https://github.com/wormhole-foundation/wormhole.git"
subdir = "sui/wormhole"
# "sui/mainnet" or "sui/testnet" respectively, as "main" doesn't have address
# TODO(matej): It's hard to tell whether these branches are officially
# supported, and testnet one is already outdated, so we either want to have the
# package at MVR at some point, or maybe want to consider creating our own
# branches with symlinked `Move.toml`.
rev = "sui/mainnet"

[dev-dependencies]

[dev-addresses]
5 changes: 5 additions & 0 deletions lazer/contracts/sui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ sui move test test_parse_and_verify_le_ecdsa_update # run a specific test

Deploy:

Bump version in [`meta.move`]. **You must do this, otherwise we get locked out
of the package after an upgrade!**

TODO

[`meta.move`]: sources/meta.move
Loading
Loading