payloads.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. package vaa
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "math"
  8. ethcommon "github.com/ethereum/go-ethereum/common"
  9. "github.com/holiman/uint256"
  10. )
  11. // CoreModule is the identifier of the Core module (which is used for governance messages)
  12. var CoreModule = []byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x43, 0x6f, 0x72, 0x65}
  13. var CoreModuleStr = string(CoreModule[:])
  14. // WasmdModule is the identifier of the Wormchain Wasmd module (which is used for governance messages)
  15. var WasmdModule = [32]byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x57, 0x61, 0x73, 0x6D, 0x64, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x65}
  16. var WasmdModuleStr = string(WasmdModule[:])
  17. // GatewayModule is the identifier of the Gateway module (which is used for general Gateway-related governance messages)
  18. var GatewayModule = [32]byte{
  19. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  20. 0x00, 0x00, 0x00, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
  21. }
  22. var GatewayModuleStr = string(GatewayModule[:])
  23. // CircleIntegrationModule is the identifier of the Circle Integration module (which is used for governance messages).
  24. // It is the hex representation of "CircleIntegration" left padded with zeroes.
  25. var CircleIntegrationModule = [32]byte{
  26. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
  27. 0x69, 0x72, 0x63, 0x6c, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
  28. }
  29. var CircleIntegrationModuleStr = string(CircleIntegrationModule[:])
  30. // IbcReceiverModule is the identifier of the Wormchain ibc_receiver contract module (which is used for governance messages)
  31. // It is the hex representation of "IbcReceiver" left padded with zeroes.
  32. var IbcReceiverModule = [32]byte{
  33. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  34. 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x62, 0x63, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72,
  35. }
  36. var IbcReceiverModuleStr = string(IbcReceiverModule[:])
  37. // IbcTranslatorModule is the identifier of the Wormchain ibc_receiver contract module (which is used for governance messages)
  38. // It is the hex representation of "IbcTranslator" left padded with zeroes.
  39. var IbcTranslatorModule = [32]byte{
  40. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  41. 0x00, 0x00, 0x00, 0x49, 0x62, 0x63, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x6f, 0x72,
  42. }
  43. var IbcTranslatorModuleStr = string(IbcTranslatorModule[:])
  44. // WormholeRelayerModule is the identifier of the Wormhole Relayer module (which is used for governance messages).
  45. // It is the hex representation of "WormholeRelayer" left padded with zeroes.
  46. var WormholeRelayerModule = [32]byte{
  47. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  48. 0x00, 0x57, 0x6f, 0x72, 0x6d, 0x68, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72,
  49. }
  50. var WormholeRelayerModuleStr = string(WormholeRelayerModule[:])
  51. var GeneralPurposeGovernanceModule = [32]byte{
  52. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x6C,
  53. 0x50, 0x75, 0x72, 0x70, 0x6F, 0x73, 0x65, 0x47, 0x6F, 0x76, 0x65, 0x72, 0x6E, 0x61, 0x6E,
  54. 0x63, 0x65,
  55. }
  56. var GeneralPurposeGovernanceModuleStr = string(GeneralPurposeGovernanceModule[:])
  57. type GovernanceAction uint8
  58. var (
  59. // Wormhole core governance actions
  60. // See e.g. GovernanceStructs.sol for semantic meaning of these
  61. ActionContractUpgrade GovernanceAction = 1
  62. ActionGuardianSetUpdate GovernanceAction = 2
  63. ActionCoreSetMessageFee GovernanceAction = 3
  64. ActionCoreTransferFees GovernanceAction = 4
  65. ActionCoreRecoverChainId GovernanceAction = 5
  66. // Wormchain cosmwasm/middleware governance actions
  67. ActionStoreCode GovernanceAction = 1
  68. ActionInstantiateContract GovernanceAction = 2
  69. ActionMigrateContract GovernanceAction = 3
  70. ActionAddWasmInstantiateAllowlist GovernanceAction = 4
  71. ActionDeleteWasmInstantiateAllowlist GovernanceAction = 5
  72. // Gateway governance actions
  73. ActionScheduleUpgrade GovernanceAction = 1
  74. ActionCancelUpgrade GovernanceAction = 2
  75. ActionSetIbcComposabilityMwContract GovernanceAction = 3
  76. ActionSlashingParamsUpdate GovernanceAction = 4
  77. // Accountant governance actions
  78. ActionModifyBalance GovernanceAction = 1
  79. // Wormhole tokenbridge governance actions
  80. ActionRegisterChain GovernanceAction = 1
  81. ActionUpgradeTokenBridge GovernanceAction = 2
  82. ActionTokenBridgeRecoverChainId GovernanceAction = 3
  83. // Circle Integration governance actions
  84. CircleIntegrationActionUpdateWormholeFinality GovernanceAction = 1
  85. CircleIntegrationActionRegisterEmitterAndDomain GovernanceAction = 2
  86. CircleIntegrationActionUpgradeContractImplementation GovernanceAction = 3
  87. // Ibc Receiver governance actions
  88. IbcReceiverActionUpdateChannelChain GovernanceAction = 1
  89. // Ibc Translator governance actions
  90. IbcTranslatorActionUpdateChannelChain GovernanceAction = 1
  91. // Wormhole relayer governance actions
  92. WormholeRelayerSetDefaultDeliveryProvider GovernanceAction = 3
  93. // General purpose governance
  94. GeneralPurposeGovernanceEvmAction GovernanceAction = 1
  95. GeneralPurposeGovernanceSolanaAction GovernanceAction = 2
  96. )
  97. type (
  98. // BodyContractUpgrade is a governance message to perform a contract upgrade of the core module
  99. BodyContractUpgrade struct {
  100. ChainID ChainID
  101. NewContract Address
  102. }
  103. // BodyGuardianSetUpdate is a governance message to set a new guardian set
  104. BodyGuardianSetUpdate struct {
  105. Keys []ethcommon.Address
  106. NewIndex uint32
  107. }
  108. // BodyTokenBridgeRegisterChain is a governance message to register a chain on the token bridge
  109. BodyTokenBridgeRegisterChain struct {
  110. Module string
  111. ChainID ChainID
  112. EmitterAddress Address
  113. }
  114. // BodyTokenBridgeUpgradeContract is a governance message to upgrade the token bridge.
  115. BodyTokenBridgeUpgradeContract struct {
  116. Module string
  117. TargetChainID ChainID
  118. NewContract Address
  119. }
  120. // BodyRecoverChainId is a governance message to recover a chain id.
  121. BodyRecoverChainId struct {
  122. Module string
  123. EvmChainID *uint256.Int
  124. NewChainID ChainID
  125. }
  126. // BodyTokenBridgeModifyBalance is a governance message to modify accountant balances for the tokenbridge.
  127. BodyAccountantModifyBalance struct {
  128. Module string
  129. TargetChainID ChainID
  130. Sequence uint64
  131. ChainId ChainID
  132. TokenChain ChainID
  133. TokenAddress Address
  134. Kind uint8
  135. Amount *uint256.Int
  136. Reason string
  137. }
  138. // BodyWormchainStoreCode is a governance message to upload a new cosmwasm contract to wormchain
  139. BodyWormchainStoreCode struct {
  140. WasmHash [32]byte
  141. }
  142. // BodyWormchainInstantiateContract is a governance message to instantiate a cosmwasm contract on wormchain
  143. BodyWormchainInstantiateContract struct {
  144. InstantiationParamsHash [32]byte
  145. }
  146. // BodyWormchainInstantiateContract is a governance message to migrate a cosmwasm contract on wormchain
  147. BodyWormchainMigrateContract struct {
  148. MigrationParamsHash [32]byte
  149. }
  150. // BodyWormchainAllowlistInstantiateContract is a governance message to allowlist a specific contract address to instantiate a specific wasm code id.
  151. BodyWormchainWasmAllowlistInstantiate struct {
  152. ContractAddr [32]byte
  153. CodeId uint64
  154. }
  155. // BodyGatewayScheduleUpgrade is a governance message to schedule an upgrade on Gateway
  156. BodyGatewayScheduleUpgrade struct {
  157. Name string
  158. Height uint64
  159. }
  160. // BodyGatewayIbcComposabilityMwContract is a governance message to set a specific contract (i.e. IBC Translator) for the ibc composability middleware to use
  161. BodyGatewayIbcComposabilityMwContract struct {
  162. ContractAddr [32]byte
  163. }
  164. // BodyGatewaySlashingParamsUpdate is a governance message to update the slashing parameters on Wormchain.
  165. //
  166. // It is important to note that the slashing keeper only accepts `int64` values as input, so we need to convert
  167. // the `uint64` values to `int64` before passing them to the keeper. This conversion can introduce overflow
  168. // issues if the `uint64` values are too large. To combat this, the Wormchain CLI and the slashing keeper run
  169. // validation checks on the new parameter values.
  170. //
  171. // Below documents the entire process of updating the slashing parameters:
  172. // 1. The CLI command receives the new slashing parameters from the user as `uint64` values for `SignedBlocksWindow` and `DowntimeJailDuration` and as `string` values
  173. // for `MinSignedPerWindow`, `SlashFractionDoubleSign`, and `SlashFractionDowntime`. The command accepts `string` values for ease of use when providing decimal values.
  174. // 2. The CLI command converts the `string` values into `sdk.Dec` values and then into `uint64` values.
  175. // 3. The CLI command validates that the `uint64` values are within the acceptable range for the slashing parameters.
  176. // 4. The CLI command serializes the new slashing parameters into a governance VAA.
  177. // 5. The governance VAA is signed & broadcasted to the Wormchain.
  178. // 6. Wormchain deserializes the governance VAA and extracts every new slashing parameter as a uint64 value.
  179. // 7. Wormchain converts the uint64 values to int64 values and passes them to the slashing keeper.
  180. // 8. The slashing keeper runs validation checks on the new slashing parameters and throws an error if they are invalid.
  181. // 9. If the new slashing parameters pass the validation checks, the slashing keeper updates its parameters.
  182. BodyGatewaySlashingParamsUpdate struct {
  183. SignedBlocksWindow uint64
  184. MinSignedPerWindow uint64
  185. DowntimeJailDuration uint64
  186. SlashFractionDoubleSign uint64
  187. SlashFractionDowntime uint64
  188. }
  189. // BodyCircleIntegrationUpdateWormholeFinality is a governance message to update the wormhole finality for Circle Integration.
  190. BodyCircleIntegrationUpdateWormholeFinality struct {
  191. TargetChainID ChainID
  192. Finality uint8
  193. }
  194. // BodyCircleIntegrationRegisterEmitterAndDomain is a governance message to register an emitter and domain for Circle Integration.
  195. BodyCircleIntegrationRegisterEmitterAndDomain struct {
  196. TargetChainID ChainID
  197. ForeignEmitterChainId ChainID
  198. ForeignEmitterAddress [32]byte
  199. CircleDomain uint32
  200. }
  201. // BodyCircleIntegrationUpgradeContractImplementation is a governance message to upgrade the contract implementation for Circle Integration.
  202. BodyCircleIntegrationUpgradeContractImplementation struct {
  203. TargetChainID ChainID
  204. NewImplementationAddress [32]byte
  205. }
  206. // BodyIbcUpdateChannelChain is a governance message to update the ibc channel_id -> chain_id mapping in either of the ibc_receiver or ibc_translator contracts
  207. BodyIbcUpdateChannelChain struct {
  208. // The chain that this governance VAA should be redeemed on
  209. TargetChainId ChainID
  210. // This should follow the IBC channel identifier standard: https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements#paths-identifiers-separators
  211. // If the identifier string is shorter than 64 bytes, the correct number of 0x00 bytes should be prepended.
  212. ChannelId [64]byte
  213. ChainId ChainID
  214. }
  215. // BodyWormholeRelayerSetDefaultDeliveryProvider is a governance message to set the default relay provider for the Wormhole Relayer.
  216. BodyWormholeRelayerSetDefaultDeliveryProvider struct {
  217. ChainID ChainID
  218. NewDefaultDeliveryProviderAddress Address
  219. }
  220. // BodyGeneralPurposeGovernanceEvm is a general purpose governance message for EVM chains
  221. BodyGeneralPurposeGovernanceEvm struct {
  222. ChainID ChainID
  223. GovernanceContract ethcommon.Address
  224. TargetContract ethcommon.Address
  225. Payload []byte
  226. }
  227. // BodyGeneralPurposeGovernanceSolana is a general purpose governance message for Solana chains
  228. BodyGeneralPurposeGovernanceSolana struct {
  229. ChainID ChainID
  230. GovernanceContract Address
  231. // NOTE: unlike in EVM, no target contract in the schema here, the
  232. // instruction encodes the target contract address (unlike in EVM, where
  233. // an abi encoded calldata doesn't include the target contract address)
  234. Instruction []byte
  235. }
  236. // BodyCoreBridgeSetMessageFee is a governance message to set the message fee for the core bridge.
  237. BodyCoreBridgeSetMessageFee struct {
  238. ChainID ChainID
  239. MessageFee *uint256.Int
  240. }
  241. )
  242. //nolint:unparam // TODO: The error is always nil here. This function should not return an error.
  243. func (b BodyContractUpgrade) Serialize() ([]byte, error) {
  244. buf := new(bytes.Buffer)
  245. // Module
  246. buf.Write(CoreModule)
  247. // Action
  248. MustWrite(buf, binary.BigEndian, ActionContractUpgrade)
  249. // ChainID
  250. MustWrite(buf, binary.BigEndian, uint16(b.ChainID))
  251. buf.Write(b.NewContract[:])
  252. return buf.Bytes(), nil
  253. }
  254. //nolint:unparam // TODO: The error is always nil here. This function should not return an error.
  255. func (b BodyGuardianSetUpdate) Serialize() ([]byte, error) {
  256. buf := new(bytes.Buffer)
  257. // Module
  258. buf.Write(CoreModule)
  259. // Action
  260. MustWrite(buf, binary.BigEndian, ActionGuardianSetUpdate)
  261. // ChainID - 0 for universal
  262. MustWrite(buf, binary.BigEndian, uint16(0))
  263. MustWrite(buf, binary.BigEndian, b.NewIndex)
  264. MustWrite(buf, binary.BigEndian, uint8(len(b.Keys))) // #nosec G115 -- There will never be 256 guardians
  265. for _, k := range b.Keys {
  266. buf.Write(k[:])
  267. }
  268. return buf.Bytes(), nil
  269. }
  270. func (r BodyTokenBridgeRegisterChain) Serialize() ([]byte, error) {
  271. payload := &bytes.Buffer{}
  272. MustWrite(payload, binary.BigEndian, r.ChainID)
  273. payload.Write(r.EmitterAddress[:])
  274. // target chain 0 = universal
  275. return serializeBridgeGovernanceVaa(r.Module, ActionRegisterChain, 0, payload.Bytes())
  276. }
  277. func (r BodyTokenBridgeUpgradeContract) Serialize() ([]byte, error) {
  278. return serializeBridgeGovernanceVaa(r.Module, ActionUpgradeTokenBridge, r.TargetChainID, r.NewContract[:])
  279. }
  280. func (r BodyRecoverChainId) Serialize() ([]byte, error) {
  281. // Module
  282. buf, err := LeftPadBytes(r.Module, 32)
  283. if err != nil {
  284. return nil, fmt.Errorf("failed to left pad module: %w", err)
  285. }
  286. // Action
  287. var action GovernanceAction
  288. if r.Module == "Core" {
  289. action = ActionCoreRecoverChainId
  290. } else {
  291. action = ActionTokenBridgeRecoverChainId
  292. }
  293. MustWrite(buf, binary.BigEndian, action)
  294. // EvmChainID
  295. MustWrite(buf, binary.BigEndian, r.EvmChainID.Bytes32())
  296. // NewChainID
  297. MustWrite(buf, binary.BigEndian, r.NewChainID)
  298. return buf.Bytes(), nil
  299. }
  300. const AccountantModifyBalanceReasonLength = 32
  301. func (r BodyAccountantModifyBalance) Serialize() ([]byte, error) {
  302. payload := &bytes.Buffer{}
  303. MustWrite(payload, binary.BigEndian, r.Sequence)
  304. MustWrite(payload, binary.BigEndian, r.ChainId)
  305. MustWrite(payload, binary.BigEndian, r.TokenChain)
  306. payload.Write(r.TokenAddress[:])
  307. payload.WriteByte(r.Kind)
  308. amount_bytes := r.Amount.Bytes32()
  309. payload.Write(amount_bytes[:])
  310. reason := make([]byte, AccountantModifyBalanceReasonLength)
  311. // truncate or pad "reason"
  312. count := copy(reason, r.Reason)
  313. for i := range reason[count:] {
  314. reason[i] = ' '
  315. }
  316. payload.Write(reason)
  317. return serializeBridgeGovernanceVaa(r.Module, ActionModifyBalance, r.TargetChainID, payload.Bytes())
  318. }
  319. func (r BodyWormchainStoreCode) Serialize() ([]byte, error) {
  320. return serializeBridgeGovernanceVaa(WasmdModuleStr, ActionStoreCode, ChainIDWormchain, r.WasmHash[:])
  321. }
  322. func (r BodyWormchainInstantiateContract) Serialize() ([]byte, error) {
  323. return serializeBridgeGovernanceVaa(WasmdModuleStr, ActionInstantiateContract, ChainIDWormchain, r.InstantiationParamsHash[:])
  324. }
  325. func (r BodyWormchainMigrateContract) Serialize() ([]byte, error) {
  326. return serializeBridgeGovernanceVaa(WasmdModuleStr, ActionMigrateContract, ChainIDWormchain, r.MigrationParamsHash[:])
  327. }
  328. func (r BodyWormchainWasmAllowlistInstantiate) Serialize(action GovernanceAction) ([]byte, error) {
  329. payload := &bytes.Buffer{}
  330. payload.Write(r.ContractAddr[:])
  331. MustWrite(payload, binary.BigEndian, r.CodeId)
  332. return serializeBridgeGovernanceVaa(WasmdModuleStr, action, ChainIDWormchain, payload.Bytes())
  333. }
  334. func (r *BodyWormchainWasmAllowlistInstantiate) Deserialize(bz []byte) error {
  335. if len(bz) != 40 {
  336. return fmt.Errorf("incorrect payload length, should be 40, is %d", len(bz))
  337. }
  338. var contractAddr [32]byte
  339. copy(contractAddr[:], bz[0:32])
  340. codeId := binary.BigEndian.Uint64(bz[32:40])
  341. r.ContractAddr = contractAddr
  342. r.CodeId = codeId
  343. return nil
  344. }
  345. func (r BodyGatewayIbcComposabilityMwContract) Serialize() ([]byte, error) {
  346. payload := &bytes.Buffer{}
  347. payload.Write(r.ContractAddr[:])
  348. return serializeBridgeGovernanceVaa(GatewayModuleStr, ActionSetIbcComposabilityMwContract, ChainIDWormchain, payload.Bytes())
  349. }
  350. func (r *BodyGatewayIbcComposabilityMwContract) Deserialize(bz []byte) error {
  351. if len(bz) != 32 {
  352. return fmt.Errorf("incorrect payload length, should be 32, is %d", len(bz))
  353. }
  354. var contractAddr [32]byte
  355. copy(contractAddr[:], bz[0:32])
  356. r.ContractAddr = contractAddr
  357. return nil
  358. }
  359. func (b BodyGatewaySlashingParamsUpdate) Serialize() ([]byte, error) {
  360. payload := new(bytes.Buffer)
  361. MustWrite(payload, binary.BigEndian, b.SignedBlocksWindow)
  362. MustWrite(payload, binary.BigEndian, b.MinSignedPerWindow)
  363. MustWrite(payload, binary.BigEndian, b.DowntimeJailDuration)
  364. MustWrite(payload, binary.BigEndian, b.SlashFractionDoubleSign)
  365. MustWrite(payload, binary.BigEndian, b.SlashFractionDowntime)
  366. return serializeBridgeGovernanceVaa(GatewayModuleStr, ActionSlashingParamsUpdate, ChainIDWormchain, payload.Bytes())
  367. }
  368. func (r *BodyGatewaySlashingParamsUpdate) Deserialize(bz []byte) error {
  369. if len(bz) != 40 {
  370. return fmt.Errorf("incorrect payload length, should be 40, is %d", len(bz))
  371. }
  372. r.SignedBlocksWindow = binary.BigEndian.Uint64(bz[0:8])
  373. r.MinSignedPerWindow = binary.BigEndian.Uint64(bz[8:16])
  374. r.DowntimeJailDuration = binary.BigEndian.Uint64(bz[16:24])
  375. r.SlashFractionDoubleSign = binary.BigEndian.Uint64(bz[24:32])
  376. r.SlashFractionDowntime = binary.BigEndian.Uint64(bz[32:40])
  377. return nil
  378. }
  379. func (r BodyGatewayScheduleUpgrade) Serialize() ([]byte, error) {
  380. payload := &bytes.Buffer{}
  381. payload.Write([]byte(r.Name))
  382. MustWrite(payload, binary.BigEndian, r.Height)
  383. return serializeBridgeGovernanceVaa(GatewayModuleStr, ActionScheduleUpgrade, ChainIDWormchain, payload.Bytes())
  384. }
  385. //nolint:unparam // TODO: The error is always nil here. This function should not return an error.
  386. func (r *BodyGatewayScheduleUpgrade) Deserialize(bz []byte) error {
  387. r.Name = string(bz[0 : len(bz)-8])
  388. r.Height = binary.BigEndian.Uint64(bz[len(bz)-8:])
  389. return nil
  390. }
  391. func (r BodyCircleIntegrationUpdateWormholeFinality) Serialize() ([]byte, error) {
  392. return serializeBridgeGovernanceVaa(CircleIntegrationModuleStr, CircleIntegrationActionUpdateWormholeFinality, r.TargetChainID, []byte{r.Finality})
  393. }
  394. func (r BodyCircleIntegrationRegisterEmitterAndDomain) Serialize() ([]byte, error) {
  395. payload := &bytes.Buffer{}
  396. MustWrite(payload, binary.BigEndian, r.ForeignEmitterChainId)
  397. payload.Write(r.ForeignEmitterAddress[:])
  398. MustWrite(payload, binary.BigEndian, r.CircleDomain)
  399. return serializeBridgeGovernanceVaa(CircleIntegrationModuleStr, CircleIntegrationActionRegisterEmitterAndDomain, r.TargetChainID, payload.Bytes())
  400. }
  401. func (r BodyCircleIntegrationUpgradeContractImplementation) Serialize() ([]byte, error) {
  402. payload := &bytes.Buffer{}
  403. payload.Write(r.NewImplementationAddress[:])
  404. return serializeBridgeGovernanceVaa(CircleIntegrationModuleStr, CircleIntegrationActionUpgradeContractImplementation, r.TargetChainID, payload.Bytes())
  405. }
  406. func (r BodyIbcUpdateChannelChain) Serialize(module string) ([]byte, error) {
  407. if module != IbcReceiverModuleStr && module != IbcTranslatorModuleStr {
  408. return nil, errors.New("module for BodyIbcUpdateChannelChain must be either IbcReceiver or IbcTranslator")
  409. }
  410. payload := &bytes.Buffer{}
  411. payload.Write(r.ChannelId[:])
  412. MustWrite(payload, binary.BigEndian, r.ChainId)
  413. return serializeBridgeGovernanceVaa(module, IbcReceiverActionUpdateChannelChain, r.TargetChainId, payload.Bytes())
  414. }
  415. func (r BodyWormholeRelayerSetDefaultDeliveryProvider) Serialize() ([]byte, error) {
  416. payload := &bytes.Buffer{}
  417. payload.Write(r.NewDefaultDeliveryProviderAddress[:])
  418. return serializeBridgeGovernanceVaa(WormholeRelayerModuleStr, WormholeRelayerSetDefaultDeliveryProvider, r.ChainID, payload.Bytes())
  419. }
  420. func (r BodyCoreBridgeSetMessageFee) Serialize() ([]byte, error) {
  421. payload := &bytes.Buffer{}
  422. feeBytes := r.MessageFee.Bytes()
  423. if len(feeBytes) > 32 {
  424. return nil, fmt.Errorf("message fee too large")
  425. }
  426. padded := make([]byte, 32)
  427. copy(padded[32-len(feeBytes):], feeBytes)
  428. payload.Write(padded)
  429. return serializeBridgeGovernanceVaa(CoreModuleStr, ActionCoreSetMessageFee, r.ChainID, payload.Bytes())
  430. }
  431. func (r BodyGeneralPurposeGovernanceEvm) Serialize() ([]byte, error) {
  432. payload := &bytes.Buffer{}
  433. payload.Write(r.GovernanceContract[:])
  434. payload.Write(r.TargetContract[:])
  435. // write payload len as uint16
  436. if len(r.Payload) > math.MaxUint16 {
  437. return nil, fmt.Errorf("payload too long; expected at most %d bytes", math.MaxUint16)
  438. }
  439. MustWrite(payload, binary.BigEndian, uint16(len(r.Payload))) // #nosec G115 -- This is checked above
  440. payload.Write(r.Payload)
  441. return serializeBridgeGovernanceVaa(GeneralPurposeGovernanceModuleStr, GeneralPurposeGovernanceEvmAction, r.ChainID, payload.Bytes())
  442. }
  443. func (r BodyGeneralPurposeGovernanceSolana) Serialize() ([]byte, error) {
  444. payload := &bytes.Buffer{}
  445. payload.Write(r.GovernanceContract[:])
  446. // NOTE: unlike in EVM, we don't write the payload length here, because we're using
  447. // a custom instruction encoding (there is no standard encoding like evm ABI
  448. // encoding), generated by an external tool. That tool length-prefixes all
  449. // the relevant dynamic fields.
  450. payload.Write(r.Instruction)
  451. return serializeBridgeGovernanceVaa(GeneralPurposeGovernanceModuleStr, GeneralPurposeGovernanceSolanaAction, r.ChainID, payload.Bytes())
  452. }
  453. func EmptyPayloadVaa(module string, actionId GovernanceAction, chainId ChainID) ([]byte, error) {
  454. return serializeBridgeGovernanceVaa(module, actionId, chainId, []byte{})
  455. }
  456. func serializeBridgeGovernanceVaa(module string, actionId GovernanceAction, chainId ChainID, payload []byte) ([]byte, error) {
  457. buf, err := LeftPadBytes(module, 32)
  458. if err != nil {
  459. return nil, fmt.Errorf("failed to left pad module: %w", err)
  460. }
  461. // Write action ID
  462. MustWrite(buf, binary.BigEndian, actionId)
  463. // Write target chain
  464. MustWrite(buf, binary.BigEndian, chainId)
  465. // Write emitter address of chain to be registered
  466. buf.Write(payload[:])
  467. return buf.Bytes(), nil
  468. }
  469. func LeftPadIbcChannelId(channelId string) ([64]byte, error) {
  470. channelIdBuf, err := LeftPadBytes(channelId, 64)
  471. if err != nil {
  472. return [64]byte{}, fmt.Errorf("failed to left pad module: %w", err)
  473. }
  474. var channelIdIdLeftPadded [64]byte
  475. copy(channelIdIdLeftPadded[:], channelIdBuf.Bytes())
  476. return channelIdIdLeftPadded, nil
  477. }
  478. // Prepends 0x00 bytes to the payload buffer, up to a size of `length`
  479. func LeftPadBytes(payload string, length int) (*bytes.Buffer, error) {
  480. if length < 0 {
  481. return nil, errors.New("cannot prepend bytes to a negative length buffer")
  482. }
  483. if len(payload) > length {
  484. return nil, fmt.Errorf("payload longer than %d bytes", length)
  485. }
  486. buf := &bytes.Buffer{}
  487. // Prepend correct number of 0x00 bytes to the payload slice
  488. for i := 0; i < (length - len(payload)); i++ {
  489. buf.WriteByte(0x00)
  490. }
  491. // add the payload slice
  492. buf.Write([]byte(payload))
  493. return buf, nil
  494. }