testlib.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. /**
  2. *
  3. * Copyright 2022 Wormhole Project Contributors
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. import {
  19. ChainId,
  20. CHAIN_ID_AVAX,
  21. CHAIN_ID_BSC,
  22. CHAIN_ID_ETH,
  23. CHAIN_ID_FANTOM,
  24. CHAIN_ID_OASIS,
  25. CHAIN_ID_POLYGON,
  26. CHAIN_ID_SOLANA,
  27. CHAIN_ID_TERRA,
  28. CHAIN_ID_NEAR,
  29. } from "@certusone/wormhole-sdk/lib/cjs/utils";
  30. const web3EthAbi = require("web3-eth-abi");
  31. const web3Utils = require("web3-utils");
  32. const elliptic = require("elliptic");
  33. export class TestLib {
  34. zeroBytes: string;
  35. singleGuardianKey: string[] = ["beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe"];
  36. singleGuardianPrivKey: string[] = [
  37. "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0",
  38. ];
  39. constructor() {
  40. this.zeroBytes =
  41. "0000000000000000000000000000000000000000000000000000000000000000";
  42. }
  43. hexStringToUint8Array(hs: string): Uint8Array {
  44. if (hs.length % 2 === 1) {
  45. // prepend a 0
  46. hs = "0" + hs;
  47. }
  48. const buf = Buffer.from(hs, "hex");
  49. const retval = Uint8Array.from(buf);
  50. return retval;
  51. }
  52. uint8ArrayToHexString(arr: Uint8Array, add0x: boolean) {
  53. const ret: string = Buffer.from(arr).toString("hex");
  54. if (!add0x) {
  55. return ret;
  56. }
  57. return "0x" + ret;
  58. }
  59. guardianKeys: string[] = [
  60. "52A26Ce40F8CAa8D36155d37ef0D5D783fc614d2",
  61. "389A74E8FFa224aeAD0778c786163a7A2150768C",
  62. "B4459EA6482D4aE574305B239B4f2264239e7599",
  63. "072491bd66F63356090C11Aae8114F5372aBf12B",
  64. "51280eA1fd2B0A1c76Ae29a7d54dda68860A2bfF",
  65. "fa9Aa60CfF05e20E2CcAA784eE89A0A16C2057CB",
  66. "e42d59F8FCd86a1c5c4bA351bD251A5c5B05DF6A",
  67. "4B07fF9D5cE1A6ed58b6e9e7d6974d1baBEc087e",
  68. "c8306B84235D7b0478c61783C50F990bfC44cFc0",
  69. "C8C1035110a13fe788259A4148F871b52bAbcb1B",
  70. "58A2508A20A7198E131503ce26bBE119aA8c62b2",
  71. "8390820f04ddA22AFe03be1c3bb10f4ba6CF94A0",
  72. "1FD6e97387C34a1F36DE0f8341E9D409E06ec45b",
  73. "255a41fC2792209CB998A8287204D40996df9E54",
  74. "bA663B12DD23fbF4FbAC618Be140727986B3BBd0",
  75. "79040E577aC50486d0F6930e160A5C75FD1203C6",
  76. "3580D2F00309A9A85efFAf02564Fc183C0183A96",
  77. "3869795913D3B6dBF3B24a1C7654672c69A23c35",
  78. "1c0Cc52D7673c52DE99785741344662F5b2308a0",
  79. ];
  80. guardianPrivKeys: string[] = [
  81. "563d8d2fd4e701901d3846dee7ae7a92c18f1975195264d676f8407ac5976757",
  82. "8d97f25916a755df1d9ef74eb4dbebc5f868cb07830527731e94478cdc2b9d5f",
  83. "9bd728ad7617c05c31382053b57658d4a8125684c0098f740a054d87ddc0e93b",
  84. "5a02c4cd110d20a83a7ce8d1a2b2ae5df252b4e5f6781c7855db5cc28ed2d1b4",
  85. "93d4e3b443bf11f99a00901222c032bd5f63cf73fc1bcfa40829824d121be9b2",
  86. "ea40e40c63c6ff155230da64a2c44fcd1f1c9e50cacb752c230f77771ce1d856",
  87. "87eaabe9c27a82198e618bca20f48f9679c0f239948dbd094005e262da33fe6a",
  88. "61ffed2bff38648a6d36d6ed560b741b1ca53d45391441124f27e1e48ca04770",
  89. "bd12a242c6da318fef8f98002efb98efbf434218a78730a197d981bebaee826e",
  90. "20d3597bb16525b6d09e5fb56feb91b053d961ab156f4807e37d980f50e71aff",
  91. "344b313ffbc0199ff6ca08cacdaf5dc1d85221e2f2dc156a84245bd49b981673",
  92. "848b93264edd3f1a521274ca4da4632989eb5303fd15b14e5ec6bcaa91172b05",
  93. "c6f2046c1e6c172497fc23bd362104e2f4460d0f61984938fa16ef43f27d93f6",
  94. "693b256b1ee6b6fb353ba23274280e7166ab3be8c23c203cc76d716ba4bc32bf",
  95. "13c41508c0da03018d61427910b9922345ced25e2bbce50652e939ee6e5ea56d",
  96. "460ee0ee403be7a4f1eb1c63dd1edaa815fbaa6cf0cf2344dcba4a8acf9aca74",
  97. "b25148579b99b18c8994b0b86e4dd586975a78fa6e7ad6ec89478d7fbafd2683",
  98. "90d7ac6a82166c908b8cf1b352f3c9340a8d1f2907d7146fb7cd6354a5436cca",
  99. "b71d23908e4cf5d6cd973394f3a4b6b164eb1065785feee612efdfd8d30005ed",
  100. ];
  101. encoder(type: string, val: any) {
  102. if (type == "uint8")
  103. return web3EthAbi.encodeParameter("uint8", val).substring(2 + (64 - 2));
  104. if (type == "uint16")
  105. return web3EthAbi.encodeParameter("uint16", val).substring(2 + (64 - 4));
  106. if (type == "uint32")
  107. return web3EthAbi.encodeParameter("uint32", val).substring(2 + (64 - 8));
  108. if (type == "uint64")
  109. return web3EthAbi.encodeParameter("uint64", val).substring(2 + (64 - 16));
  110. if (type == "uint128")
  111. return web3EthAbi
  112. .encodeParameter("uint128", val)
  113. .substring(2 + (64 - 32));
  114. if (type == "uint256" || type == "bytes32")
  115. return web3EthAbi.encodeParameter(type, val).substring(2 + (64 - 64));
  116. }
  117. ord(c: any) {
  118. return c.charCodeAt(0);
  119. }
  120. genGuardianSetUpgrade(
  121. signers: any,
  122. guardianSet: number,
  123. targetSet: number,
  124. nonce: number,
  125. seq: number,
  126. guardianKeys: string[]
  127. ): string {
  128. const b = [
  129. "0x",
  130. this.zeroBytes.slice(0, 28 * 2),
  131. this.encoder("uint8", this.ord("C")),
  132. this.encoder("uint8", this.ord("o")),
  133. this.encoder("uint8", this.ord("r")),
  134. this.encoder("uint8", this.ord("e")),
  135. this.encoder("uint8", 2),
  136. this.encoder("uint16", 0),
  137. this.encoder("uint32", targetSet),
  138. this.encoder("uint8", guardianKeys.length),
  139. ];
  140. guardianKeys.forEach((x) => {
  141. b.push(x);
  142. });
  143. let emitter = "0x" + this.zeroBytes.slice(0, 31 * 2) + "04";
  144. let seconds = Math.floor(new Date().getTime() / 1000.0);
  145. return this.createSignedVAA(
  146. guardianSet,
  147. signers,
  148. seconds,
  149. nonce,
  150. 1,
  151. emitter,
  152. seq,
  153. 32,
  154. b.join("")
  155. );
  156. }
  157. genGSetFee(
  158. signers: any,
  159. guardianSet: number,
  160. nonce: number,
  161. seq: number,
  162. tchain: number,
  163. amt: number
  164. ) {
  165. const b = [
  166. "0x",
  167. this.zeroBytes.slice(0, 28 * 2),
  168. this.encoder("uint8", this.ord("C")),
  169. this.encoder("uint8", this.ord("o")),
  170. this.encoder("uint8", this.ord("r")),
  171. this.encoder("uint8", this.ord("e")),
  172. this.encoder("uint8", 3),
  173. this.encoder("uint16", tchain),
  174. this.encoder("uint256", Math.floor(amt)),
  175. ];
  176. let emitter = "0x" + this.zeroBytes.slice(0, 31 * 2) + "04";
  177. var seconds = Math.floor(new Date().getTime() / 1000.0);
  178. return this.createSignedVAA(
  179. guardianSet,
  180. signers,
  181. seconds,
  182. nonce,
  183. 1,
  184. emitter,
  185. seq,
  186. 32,
  187. b.join("")
  188. );
  189. }
  190. genGFeePayout(
  191. signers: any,
  192. guardianSet: number,
  193. nonce: number,
  194. seq: number,
  195. tchain: number,
  196. amt: number,
  197. dest: Uint8Array
  198. ) {
  199. const b = [
  200. "0x",
  201. this.zeroBytes.slice(0, 28 * 2),
  202. this.encoder("uint8", this.ord("C")),
  203. this.encoder("uint8", this.ord("o")),
  204. this.encoder("uint8", this.ord("r")),
  205. this.encoder("uint8", this.ord("e")),
  206. this.encoder("uint8", 4),
  207. this.encoder("uint16", tchain),
  208. this.encoder("uint256", Math.floor(amt)),
  209. this.uint8ArrayToHexString(dest, false),
  210. ];
  211. let emitter = "0x" + this.zeroBytes.slice(0, 31 * 2) + "04";
  212. var seconds = Math.floor(new Date().getTime() / 1000.0);
  213. return this.createSignedVAA(
  214. guardianSet,
  215. signers,
  216. seconds,
  217. nonce,
  218. 1,
  219. emitter,
  220. seq,
  221. 32,
  222. b.join("")
  223. );
  224. }
  225. genCoreUpdate(
  226. signers: any,
  227. guardianSet: number,
  228. nonce: number,
  229. seq: number,
  230. tchain: number,
  231. hash: string
  232. ) {
  233. const b = [
  234. "0x",
  235. this.zeroBytes.slice(0, 28 * 2),
  236. this.encoder("uint8", this.ord("C")),
  237. this.encoder("uint8", this.ord("o")),
  238. this.encoder("uint8", this.ord("r")),
  239. this.encoder("uint8", this.ord("e")),
  240. this.encoder("uint8", 1),
  241. this.encoder("uint16", tchain),
  242. hash,
  243. ];
  244. let emitter = "0x" + this.zeroBytes.slice(0, 31 * 2) + "04";
  245. var seconds = Math.floor(new Date().getTime() / 1000.0);
  246. return this.createSignedVAA(
  247. guardianSet,
  248. signers,
  249. seconds,
  250. nonce,
  251. 1,
  252. emitter,
  253. seq,
  254. 32,
  255. b.join("")
  256. );
  257. }
  258. genTokenUpdate(
  259. signers: any,
  260. guardianSet: number,
  261. nonce: number,
  262. seq: number,
  263. tchain: number,
  264. hash: string
  265. ) {
  266. const b = [
  267. "0x",
  268. this.zeroBytes.slice(0, (32 - 11) * 2),
  269. this.encoder("uint8", this.ord("T")),
  270. this.encoder("uint8", this.ord("o")),
  271. this.encoder("uint8", this.ord("k")),
  272. this.encoder("uint8", this.ord("e")),
  273. this.encoder("uint8", this.ord("n")),
  274. this.encoder("uint8", this.ord("B")),
  275. this.encoder("uint8", this.ord("r")),
  276. this.encoder("uint8", this.ord("i")),
  277. this.encoder("uint8", this.ord("d")),
  278. this.encoder("uint8", this.ord("g")),
  279. this.encoder("uint8", this.ord("e")),
  280. this.encoder("uint8", 2),
  281. this.encoder("uint16", tchain),
  282. hash,
  283. ];
  284. let emitter = "0x" + this.zeroBytes.slice(0, 31 * 2) + "04";
  285. var seconds = Math.floor(new Date().getTime() / 1000.0);
  286. return this.createSignedVAA(
  287. guardianSet,
  288. signers,
  289. seconds,
  290. nonce,
  291. 1,
  292. emitter,
  293. seq,
  294. 32,
  295. b.join("")
  296. );
  297. }
  298. getTokenEmitter(chain: number): string {
  299. if (chain === CHAIN_ID_SOLANA) {
  300. return "c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f";
  301. }
  302. if (chain === CHAIN_ID_ETH) {
  303. return "0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585";
  304. }
  305. if (chain === CHAIN_ID_TERRA) {
  306. return "0000000000000000000000007cf7b764e38a0a5e967972c1df77d432510564e2";
  307. }
  308. if (chain === CHAIN_ID_BSC) {
  309. return "000000000000000000000000b6f6d86a8f9879a9c87f643768d9efc38c1da6e7";
  310. }
  311. if (chain === CHAIN_ID_POLYGON) {
  312. return "0000000000000000000000005a58505a96d1dbf8df91cb21b54419fc36e93fde";
  313. }
  314. if (chain === CHAIN_ID_AVAX) {
  315. return "0000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052";
  316. }
  317. if (chain === CHAIN_ID_OASIS) {
  318. return "0000000000000000000000005848c791e09901b40a9ef749f2a6735b418d7564";
  319. }
  320. if (chain === CHAIN_ID_FANTOM) {
  321. return "0000000000000000000000007C9Fc5741288cDFdD83CeB07f3ea7e22618D79D2";
  322. }
  323. return "";
  324. }
  325. getNftEmitter(chain: ChainId): string {
  326. if (chain === CHAIN_ID_SOLANA) {
  327. return "96ee982293251b48729804c8e8b24b553eb6b887867024948d2236fd37a577ab";
  328. }
  329. if (chain === CHAIN_ID_ETH) {
  330. return "0000000000000000000000006ffd7ede62328b3af38fcd61461bbfc52f5651fe";
  331. }
  332. if (chain === CHAIN_ID_BSC) {
  333. return "0000000000000000000000005a58505a96d1dbf8df91cb21b54419fc36e93fde";
  334. }
  335. if (chain === CHAIN_ID_POLYGON) {
  336. return "00000000000000000000000090bbd86a6fe93d3bc3ed6335935447e75fab7fcf";
  337. }
  338. if (chain === CHAIN_ID_AVAX) {
  339. return "000000000000000000000000f7b6737ca9c4e08ae573f75a97b73d7a813f5de5";
  340. }
  341. if (chain === CHAIN_ID_OASIS) {
  342. return "00000000000000000000000004952D522Ff217f40B5Ef3cbF659EcA7b952a6c1";
  343. }
  344. if (chain === CHAIN_ID_FANTOM) {
  345. return "000000000000000000000000A9c7119aBDa80d4a4E0C06C8F4d8cF5893234535";
  346. }
  347. return "";
  348. }
  349. genRegisterChain(
  350. signers: any,
  351. guardianSet: number,
  352. nonce: number,
  353. seq: number,
  354. chain: number
  355. ) {
  356. const b = [
  357. "0x",
  358. this.zeroBytes.slice(0, (32 - 11) * 2),
  359. this.encoder("uint8", this.ord("T")),
  360. this.encoder("uint8", this.ord("o")),
  361. this.encoder("uint8", this.ord("k")),
  362. this.encoder("uint8", this.ord("e")),
  363. this.encoder("uint8", this.ord("n")),
  364. this.encoder("uint8", this.ord("B")),
  365. this.encoder("uint8", this.ord("r")),
  366. this.encoder("uint8", this.ord("i")),
  367. this.encoder("uint8", this.ord("d")),
  368. this.encoder("uint8", this.ord("g")),
  369. this.encoder("uint8", this.ord("e")),
  370. this.encoder("uint8", 1),
  371. this.encoder("uint16", 0),
  372. this.encoder("uint16", chain),
  373. this.getTokenEmitter(chain),
  374. ];
  375. let emitter = "0x" + this.zeroBytes.slice(0, 31 * 2) + "04";
  376. var seconds = Math.floor(new Date().getTime() / 1000.0);
  377. return this.createSignedVAA(
  378. guardianSet,
  379. signers,
  380. seconds,
  381. nonce,
  382. 1,
  383. emitter,
  384. seq,
  385. 32,
  386. b.join("")
  387. );
  388. }
  389. genAssetMeta(
  390. signers: any,
  391. guardianSet: number,
  392. nonce: number,
  393. seq: number,
  394. tokenAddress: string,
  395. chain: number,
  396. decimals: number,
  397. symbol: string,
  398. name: string
  399. ) {
  400. const b = [
  401. "0x",
  402. this.encoder("uint8", 2),
  403. this.zeroBytes.slice(0, 64 - tokenAddress.length),
  404. tokenAddress,
  405. this.encoder("uint16", chain),
  406. this.encoder("uint8", decimals),
  407. Buffer.from(symbol).toString("hex"),
  408. this.zeroBytes.slice(0, (32 - symbol.length) * 2),
  409. Buffer.from(name).toString("hex"),
  410. this.zeroBytes.slice(0, (32 - name.length) * 2),
  411. ];
  412. // console.log(b.join())
  413. // console.log(b.join('').length)
  414. let emitter = "0x" + this.getTokenEmitter(chain);
  415. let seconds = Math.floor(new Date().getTime() / 1000.0);
  416. return this.createSignedVAA(
  417. guardianSet,
  418. signers,
  419. seconds,
  420. nonce,
  421. chain,
  422. emitter,
  423. seq,
  424. 32,
  425. b.join("")
  426. );
  427. }
  428. genTransfer(
  429. signers: any,
  430. guardianSet: number,
  431. nonce: number,
  432. seq: number,
  433. amount: number,
  434. tokenAddress: string,
  435. tokenChain: number,
  436. toAddress: string,
  437. toChain: number,
  438. fee: number
  439. ) {
  440. const b = [
  441. "0x",
  442. this.encoder("uint8", 1),
  443. this.encoder("uint256", Math.floor(amount * 100000000)),
  444. this.zeroBytes.slice(0, 64 - tokenAddress.length),
  445. tokenAddress,
  446. this.encoder("uint16", tokenChain),
  447. this.zeroBytes.slice(0, 64 - toAddress.length),
  448. toAddress,
  449. this.encoder("uint16", toChain),
  450. this.encoder("uint256", Math.floor(fee * 100000000)),
  451. ];
  452. let emitter = "0x" + this.getTokenEmitter(tokenChain);
  453. let seconds = Math.floor(new Date().getTime() / 1000.0);
  454. return this.createSignedVAA(
  455. guardianSet,
  456. signers,
  457. seconds,
  458. nonce,
  459. tokenChain,
  460. emitter,
  461. seq,
  462. 32,
  463. b.join("")
  464. );
  465. }
  466. genNFTTransfer(
  467. signers: any,
  468. guardianSet: number,
  469. nonce: number,
  470. seq: number,
  471. contract: string, // 32 bytes
  472. fchain: number,
  473. symbol: string,
  474. name: string,
  475. tokenid: string,
  476. uri: string,
  477. target: string, // 32 bytes
  478. tochain: number
  479. ) {
  480. const b = [
  481. "0x",
  482. this.encoder("uint8", 1),
  483. this.zeroBytes.slice(0, 64 - contract.length),
  484. contract,
  485. this.encoder("uint16", fchain),
  486. Buffer.from(symbol).toString("hex"),
  487. this.zeroBytes.slice(0, (32 - symbol.length) * 2),
  488. Buffer.from(name).toString("hex"),
  489. this.zeroBytes.slice(0, (32 - name.length) * 2),
  490. this.zeroBytes.slice(0, 64 - tokenid.length),
  491. tokenid,
  492. this.encoder("uint8", uri.length),
  493. Buffer.from(uri).toString("hex"),
  494. this.zeroBytes.slice(0, 64 - target.length),
  495. target,
  496. this.encoder("uint16", tochain),
  497. ];
  498. let emitter = "0x" + this.getNftEmitter(fchain as ChainId);
  499. let seconds = Math.floor(new Date().getTime() / 1000.0);
  500. return this.createSignedVAA(
  501. guardianSet,
  502. signers,
  503. seconds,
  504. nonce,
  505. fchain,
  506. emitter,
  507. seq,
  508. 32,
  509. b.join("")
  510. );
  511. }
  512. /**
  513. * Create a packed and signed VAA for testing.
  514. * See https://github.com/wormhole-foundation/wormhole/blob/dev.v2/design/0001_generic_message_passing.md
  515. *
  516. * @param {} guardianSetIndex The guardian set index
  517. * @param {*} signers The list of private keys for signing the VAA
  518. * @param {*} timestamp The timestamp of VAA
  519. * @param {*} nonce The nonce.
  520. * @param {*} emitterChainId The emitter chain identifier
  521. * @param {*} emitterAddress The emitter chain address, prefixed with 0x
  522. * @param {*} sequence The sequence.
  523. * @param {*} consistencyLevel The reported consistency level
  524. * @param {*} payload This VAA Payload hex string, prefixed with 0x
  525. */
  526. createSignedVAA(
  527. guardianSetIndex: number,
  528. signers: any,
  529. timestamp: number,
  530. nonce: number,
  531. emitterChainId: number,
  532. emitterAddress: string,
  533. sequence: number,
  534. consistencyLevel: number,
  535. payload: string
  536. ) {
  537. console.log(typeof payload);
  538. const body = [
  539. this.encoder("uint32", timestamp),
  540. this.encoder("uint32", nonce),
  541. this.encoder("uint16", emitterChainId),
  542. this.encoder("bytes32", emitterAddress),
  543. this.encoder("uint64", sequence),
  544. this.encoder("uint8", consistencyLevel),
  545. payload.substring(2),
  546. ];
  547. const hash = web3Utils.keccak256(web3Utils.keccak256("0x" + body.join("")));
  548. let signatures = "";
  549. for (const i in signers) {
  550. // eslint-disable-next-line new-cap
  551. const ec = new elliptic.ec("secp256k1");
  552. const key = ec.keyFromPrivate(signers[i]);
  553. const signature = key.sign(hash.substr(2), { canonical: true });
  554. const packSig = [
  555. this.encoder("uint8", i),
  556. this.zeroPadBytes(signature.r.toString(16), 32),
  557. this.zeroPadBytes(signature.s.toString(16), 32),
  558. this.encoder("uint8", signature.recoveryParam),
  559. ];
  560. signatures += packSig.join("");
  561. }
  562. const vm = [
  563. this.encoder("uint8", 1),
  564. this.encoder("uint32", guardianSetIndex),
  565. this.encoder("uint8", signers.length),
  566. signatures,
  567. body.join(""),
  568. ].join("");
  569. return vm;
  570. }
  571. zeroPadBytes(value: string, length: number) {
  572. while (value.length < 2 * length) {
  573. value = "0" + value;
  574. }
  575. return value;
  576. }
  577. }
  578. module.exports = {
  579. TestLib,
  580. };