Skip to content

Commit 046ba8a

Browse files
authored
feat(governance): add SetFeeInToken directive (#1654)
* feat(governance): add SetFeeInToken directive * refactor(governance): custom decode/encode for SetFeeInToken
1 parent 42cd062 commit 046ba8a

File tree

4 files changed

+114
-3
lines changed

4 files changed

+114
-3
lines changed

governance/xc_admin/packages/xc_admin_common/src/__tests__/GovernancePayload.test.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
AuthorizeGovernanceDataSourceTransfer,
2727
RequestGovernanceDataSourceTransfer,
2828
} from "../governance_payload/GovernanceDataSourceTransfer";
29-
import { SetFee } from "../governance_payload/SetFee";
29+
import { SetFee, SetFeeInToken } from "../governance_payload/SetFee";
3030
import { SetValidPeriod } from "../governance_payload/SetValidPeriod";
3131
import {
3232
DataSource,
@@ -196,6 +196,28 @@ test("GovernancePayload ser/de", (done) => {
196196
)
197197
).toBeTruthy();
198198

199+
const setFeeInToken = new SetFeeInToken(
200+
"starknet",
201+
42n,
202+
8n,
203+
Buffer.from(
204+
"049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
205+
"hex"
206+
)
207+
);
208+
const setFeeInTokenBuffer = setFeeInToken.encode();
209+
console.log(setFeeInTokenBuffer.toJSON());
210+
expect(
211+
setFeeInTokenBuffer.equals(
212+
Buffer.from([
213+
80, 84, 71, 77, 1, 7, 234, 147, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0,
214+
0, 0, 8, 32, 4, 157, 54, 87, 13, 78, 70, 244, 142, 153, 103, 75, 211,
215+
252, 200, 70, 68, 221, 214, 185, 111, 124, 116, 27, 21, 98, 184, 47,
216+
158, 0, 77, 199,
217+
])
218+
)
219+
).toBeTruthy();
220+
199221
const setDataSources = new SetDataSources("starknet", [
200222
{
201223
emitterChain: 1,
@@ -384,6 +406,24 @@ function governanceActionArb(): Arbitrary<PythGovernanceAction> {
384406
callData
385407
)
386408
);
409+
} else if (header.action === "SetFeeInToken") {
410+
return fc
411+
.record({
412+
value: fc.bigUintN(64),
413+
expo: fc.bigUintN(64),
414+
token: fc.array(fc.integer({ min: 0, max: 255 }), {
415+
minLength: 0,
416+
maxLength: 128,
417+
}),
418+
})
419+
.map(({ value, expo, token }) => {
420+
return new SetFeeInToken(
421+
header.targetChainId,
422+
value,
423+
expo,
424+
Buffer.from(token)
425+
);
426+
});
387427
} else {
388428
throw new Error("Unsupported action type");
389429
}

governance/xc_admin/packages/xc_admin_common/src/governance_payload/PythGovernanceAction.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const TargetAction = {
1515
SetValidPeriod: 4,
1616
RequestGovernanceDataSourceTransfer: 5,
1717
SetWormholeAddress: 6,
18+
SetFeeInToken: 7,
1819
} as const;
1920

2021
export const EvmExecutorAction = {
@@ -43,6 +44,8 @@ export function toActionName(
4344
return "RequestGovernanceDataSourceTransfer";
4445
case 6:
4546
return "SetWormholeAddress";
47+
case 7:
48+
return "SetFeeInToken";
4649
}
4750
} else if (
4851
deserialized.moduleId == MODULE_EVM_EXECUTOR &&

governance/xc_admin/packages/xc_admin_common/src/governance_payload/SetFee.ts

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { PythGovernanceActionImpl } from "./PythGovernanceAction";
1+
import {
2+
PythGovernanceActionImpl,
3+
PythGovernanceHeader,
4+
} from "./PythGovernanceAction";
25
import * as BufferLayout from "@solana/buffer-layout";
36
import * as BufferLayoutExt from "./BufferLayoutExt";
47
import { ChainName } from "../chains";
@@ -42,3 +45,66 @@ export class SetFee extends PythGovernanceActionImpl {
4245
});
4346
}
4447
}
48+
49+
/** Set the fee in the specified token on the target chain to newFeeValue * 10^newFeeExpo.
50+
* The length and encoding of token is chain-specific:
51+
* - On Starknet, it's a 256-bit BE integer representing the token account address.
52+
*/
53+
export class SetFeeInToken extends PythGovernanceActionImpl {
54+
static layout: BufferLayout.Structure<
55+
Readonly<{
56+
newFeeValue: bigint;
57+
newFeeExpo: bigint;
58+
tokenLen: number;
59+
}>
60+
> = BufferLayout.struct([
61+
BufferLayoutExt.u64be("newFeeValue"),
62+
BufferLayoutExt.u64be("newFeeExpo"),
63+
BufferLayout.u8("tokenLen"),
64+
]);
65+
66+
constructor(
67+
targetChainId: ChainName,
68+
readonly newFeeValue: bigint,
69+
readonly newFeeExpo: bigint,
70+
readonly token: Buffer
71+
) {
72+
super(targetChainId, "SetFeeInToken");
73+
}
74+
75+
static decode(data: Buffer): SetFeeInToken | undefined {
76+
const header = PythGovernanceHeader.decode(data);
77+
if (!header || header.action !== "SetFeeInToken") {
78+
return undefined;
79+
}
80+
81+
let index = PythGovernanceHeader.span;
82+
const fields = SetFeeInToken.layout.decode(data, index);
83+
index += SetFeeInToken.layout.span;
84+
return new SetFeeInToken(
85+
header.targetChainId,
86+
fields.newFeeValue,
87+
fields.newFeeExpo,
88+
data.subarray(index)
89+
);
90+
}
91+
92+
encode(): Buffer {
93+
const headerBuffer = new PythGovernanceHeader(
94+
this.targetChainId,
95+
"SetFeeInToken"
96+
).encode();
97+
98+
const fieldsBuf = Buffer.alloc(SetFeeInToken.layout.span);
99+
SetFeeInToken.layout.encode(
100+
{
101+
newFeeValue: this.newFeeValue,
102+
newFeeExpo: this.newFeeExpo,
103+
tokenLen: this.token.length,
104+
},
105+
fieldsBuf
106+
);
107+
108+
return Buffer.concat([headerBuffer, fieldsBuf, this.token]);
109+
}
110+
}

governance/xc_admin/packages/xc_admin_common/src/governance_payload/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
} from "./GovernanceDataSourceTransfer";
1515
import { SetDataSources } from "./SetDataSources";
1616
import { SetValidPeriod } from "./SetValidPeriod";
17-
import { SetFee } from "./SetFee";
17+
import { SetFee, SetFeeInToken } from "./SetFee";
1818
import {
1919
EvmSetWormholeAddress,
2020
StarknetSetWormholeAddress,
@@ -52,6 +52,8 @@ export function decodeGovernancePayload(
5252
return SetDataSources.decode(data);
5353
case "SetFee":
5454
return SetFee.decode(data);
55+
case "SetFeeInToken":
56+
return SetFeeInToken.decode(data);
5557
case "SetValidPeriod":
5658
return SetValidPeriod.decode(data);
5759
case "RequestGovernanceDataSourceTransfer":

0 commit comments

Comments
 (0)