hopr_chain_types/payload/mod.rs
1//! Module defining various Ethereum transaction payload generators for the actions.
2//!
3//! This module defines the basic [`PayloadGenerator`] trait that describes how an action
4//! is translated into a [`TransactionRequest`] that can be submitted on-chain.
5//!
6//! There are two main implementations:
7//! - [`BasicPayloadGenerator`] which implements generation of a direct EIP1559 transaction payload. This is currently
8//! not used by a HOPR node.
9//! - [`SafePayloadGenerator`] which implements generation of a payload that embeds the transaction data into the SAFE
10//! transaction. This is currently the main mode of HOPR node operation.
11//!
12//! These are currently based on the `hopr-bindings` crate.
13
14#[cfg(feature = "use-bindings")]
15mod bindings_based;
16
17#[cfg(feature = "use-bindings")]
18pub(crate) use bindings_based::KeyBindAndAnnouncePayload;
19#[cfg(feature = "use-bindings")]
20pub use bindings_based::{BasicPayloadGenerator, SafePayloadGenerator, TransactionRequest};
21use hopr_crypto_types::prelude::*;
22use hopr_internal_types::prelude::*;
23use hopr_primitive_types::prelude::*;
24
25type Result<T> = std::result::Result<T, crate::errors::ChainTypesError>;
26
27/// Estimated gas parameters for a transaction.
28#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29pub struct GasEstimation {
30 /// Gas limit for the transaction.
31 ///
32 /// Defaults to 10 000 000.
33 pub gas_limit: u64,
34 /// Maximal fee per gas for the transaction.
35 ///
36 /// Defaults to 0.01 Gwei
37 pub max_fee_per_gas: u128,
38 /// Maximal priority fee per gas for the transaction.
39 ///
40 /// Defaults to 0.002 Gwei
41 pub max_priority_fee_per_gas: u128,
42}
43
44impl Default for GasEstimation {
45 fn default() -> Self {
46 Self {
47 gas_limit: 10_000_000,
48 max_fee_per_gas: 10_000_000, // 0.01 Gwei
49 max_priority_fee_per_gas: 2_000_000, // 0.002 Gwei
50 }
51 }
52}
53
54/// Trait for transaction payloads that can be signed and encoded to EIP2718 format.
55#[async_trait::async_trait]
56pub trait SignableTransaction {
57 /// Sign the transaction using the given chain keypair and encode it to EIP2718 format.
58 async fn sign_and_encode_to_eip2718(
59 self,
60 nonce: u64,
61 chain_id: u64,
62 max_gas: Option<GasEstimation>,
63 chain_keypair: &ChainKeypair,
64 ) -> Result<Box<[u8]>>;
65}
66
67/// Trait for various implementations of common on-chain transaction payloads generators.
68pub trait PayloadGenerator {
69 type TxRequest: SignableTransaction + Send;
70
71 /// Create an ERC20 approve transaction payload. Pre-requisite to open payment channels.
72 /// The `spender` address is typically the HOPR Channels contract address.
73 fn approve(&self, spender: Address, amount: HoprBalance) -> Result<Self::TxRequest>;
74
75 /// Create a ERC20 transfer transaction payload
76 fn transfer<C: Currency>(&self, destination: Address, amount: Balance<C>) -> Result<Self::TxRequest>;
77
78 /// Creates the transaction payload to announce a node on-chain.
79 fn announce(&self, announcement: AnnouncementData, key_binding_fee: HoprBalance) -> Result<Self::TxRequest>;
80
81 /// Creates the transaction payload to open a payment channel
82 fn fund_channel(&self, dest: Address, amount: HoprBalance) -> Result<Self::TxRequest>;
83
84 /// Creates the transaction payload to immediately close an incoming payment channel
85 fn close_incoming_channel(&self, source: Address) -> Result<Self::TxRequest>;
86
87 /// Creates the transaction payload that initiates the closure of a payment channel.
88 /// Once the notice period is due, the funds can be withdrawn using a
89 /// finalizeChannelClosure transaction.
90 fn initiate_outgoing_channel_closure(&self, destination: Address) -> Result<Self::TxRequest>;
91
92 /// Creates a transaction payload that withdraws funds from
93 /// an outgoing payment channel. This will succeed once the closure
94 /// notice period is due.
95 fn finalize_outgoing_channel_closure(&self, destination: Address) -> Result<Self::TxRequest>;
96
97 /// Used to create the payload to claim incentives for relaying a mixnet packet.
98 fn redeem_ticket(&self, acked_ticket: RedeemableTicket) -> Result<Self::TxRequest>;
99
100 /// Creates a transaction payload to register a Safe instance which is used
101 /// to manage the node's funds
102 fn register_safe_by_node(&self, safe_addr: Address) -> Result<Self::TxRequest>;
103
104 /// Creates a transaction payload to remove the Safe instance. Once succeeded,
105 /// the node no longer manages the funds.
106 fn deregister_node_by_safe(&self) -> Result<Self::TxRequest>;
107
108 /// Creates a transaction payload to deploy a new Safe instance with the initial
109 /// `balance` transferred from the signer and `admins` as Safe owners.
110 ///
111 /// If `include_node` is true, the signer will be included in the module after deployment.
112 ///
113 /// The resulting transaction requires that the signer owns at least the `balance` of wxHOPR tokens. The given
114 /// `nonce` must be randomly generated for each deployment.
115 fn deploy_safe(
116 &self,
117 balance: HoprBalance,
118 admins: &[Address],
119 include_node: bool,
120 nonce: [u8; 64],
121 ) -> Result<Self::TxRequest>;
122}
123
124#[cfg(test)]
125pub(crate) mod tests {
126 use crate::ContractAddresses;
127
128 lazy_static::lazy_static! {
129 pub static ref CONTRACT_ADDRS: ContractAddresses = serde_json::from_str(r#"{
130 "announcements": "0xf1c143B1bA20C7606d56aA2FA94502D25744b982",
131 "channels": "0x77C9414043d27fdC98A6A2d73fc77b9b383092a7",
132 "module_implementation": "0x32863c4974fBb6253E338a0cb70C382DCeD2eFCb",
133 "network_registry": "0x15a315E1320cFF0de84671c0139042EE320CE38d",
134 "network_registry_proxy": "0x20559cbD3C2eDcD0b396431226C00D2Cd102eB3F",
135 "node_safe_registry": "0x4F7C7dE3BA2B29ED8B2448dF2213cA43f94E45c0",
136 "node_safe_migration": "0x222222222222890352Ed9Ca694EdeAC49528D8F3",
137 "node_stake_factory": "0x791d190b2c95397F4BcE7bD8032FD67dCEA7a5F2",
138 "token": "0xD4fdec44DB9D44B8f2b6d529620f9C0C7066A2c1",
139 "ticket_price_oracle": "0x442df1d946303fB088C9377eefdaeA84146DA0A6",
140 "winning_probability_oracle": "0xC15675d4CCa538D91a91a8D3EcFBB8499C3B0471"
141 }"#).unwrap();
142 }
143}