hotshot_contract_adapter/
sol_types.rs

1//! Solidity types for interacting with contracts
2//! Re-export types that are used, sometimes renamed to avoid collision.
3//!
4//! TODO: (alex) Due to <https://github.com/foundry-rs/foundry/issues/10153>,
5//! try to re-export the same type from the "youngest" child contract since that is the contract whose functions are being called,
6//! thus from whom the rust bindings are expected.
7//! E.g. Both PlonkVerifier and LightClient, and LightClientV2 depends on BN254. The inheritance relationship is:
8//!   BN254 <- PlonkVerifier <- LIghtClient <- LightClientV2
9//! Most of the time, we interact with PlonkVerifier's function via LightClientV2, thus import BN254.G1Point from `bindings::plonkverifierv2`.
10//! When we need to directly interact with PlonkVerifier's method, implement stupid plain `From<lc2::BN254::G1Point> for pv::BN254::G1Point`.
11//! If you are lazy, you can even use unsafe memory transmute since they are literally the same representation, duplicated in different modules,
12//! thus treated by the rust type systems as distinct types.
13//!
14//! Another usage is in the differential testing in Solidity tests. In those cases, the actual types don't matter, since they will all `abi_encode()`
15//! into the exact same bytes before being communicated over to contract via FFI. Thus using any one of them is fine.
16
17use alloy::sol;
18
19/// # What to re-export, what to hide?
20/// - export contract struct itself, but try to avoid export instance type (instead, use ::new() to get a handle)
21/// - avoid exporting `xxCall` and `xxReturn` types, they usually can be converted/transmuted from existing struct
22/// - Event types should be exported
23/// - structs should be exported and renamed with `xxSol` suffix to avoid confusion with other rust types
24///   - see module doc for more explanation on types duplication issue in alloy
25pub use crate::bindings::{
26    erc1967proxy::ERC1967Proxy,
27    esptoken::EspToken,
28    feecontract::FeeContract::{self, Deposit},
29    lightclient::{
30        IPlonkVerifier::{PlonkProof as PlonkProofSol, VerifyingKey as VerifyingKeySol},
31        LightClient::{
32            self, LightClientErrors, LightClientInstance, LightClientState as LightClientStateSol,
33            StakeTableState as StakeTableStateSol,
34        },
35        BN254::G1Point as G1PointSol,
36    },
37    lightclientmock::{self, LightClientMock},
38    lightclientv2::{self, LightClientV2},
39    lightclientv2mock::{self, LightClientV2Mock},
40    plonkverifier::PlonkVerifier,
41    plonkverifierv2::PlonkVerifierV2,
42    staketable::{
43        self, EdOnBN254::EdOnBN254Point as EdOnBN254PointSol, StakeTable,
44        BN254::G2Point as G2PointSol,
45    },
46    timelock::Timelock,
47};
48
49// For types that we need to interact with some functions but their bindings are not generated
50// we manually declare them there. It's possible that they get included in the future commits,
51// at which point, the rust type system will complain and we simply remove the manual declaration
52// and re-export the type from bindings instead.
53sol! {
54    /// types in src/legacy/Transcript.sol
55    struct TranscriptDataSol {
56        bytes32 state;
57        bytes transcript;
58    }
59
60    /// types in src/libraries/PlonkVerifierV2.sol
61    struct ChallengesSol {
62        uint256 alpha;
63        uint256 alpha2;
64        uint256 alpha3;
65        uint256 beta;
66        uint256 gamma;
67        uint256 zeta;
68        uint256 v;
69        uint256 u;
70    }
71
72}
73
74// Due to <https://github.com/foundry-rs/foundry/issues/10153> the rust bindings contain duplicate types for our solidity types.
75// In order to avoid writing a lot of boilerplate code we use transmute to convert between these duplicated types.
76// Since all the types we transmute between are generated by foundry from the same underlying solidity type
77// we expect that the order of fields and types of fields are always the same.
78impl From<LightClient::genesisStateReturn> for LightClientStateSol {
79    fn from(v: LightClient::genesisStateReturn) -> Self {
80        unsafe { std::mem::transmute(v) }
81    }
82}
83
84impl From<lightclientmock::LightClient::LightClientState> for LightClientStateSol {
85    fn from(v: lightclientmock::LightClient::LightClientState) -> Self {
86        unsafe { std::mem::transmute(v) }
87    }
88}
89impl From<lightclientmock::LightClientMock::finalizedStateReturn> for LightClientStateSol {
90    fn from(v: lightclientmock::LightClientMock::finalizedStateReturn) -> Self {
91        unsafe { std::mem::transmute(v) }
92    }
93}
94
95impl From<LightClientStateSol> for lightclientmock::LightClient::LightClientState {
96    fn from(v: LightClientStateSol) -> Self {
97        unsafe { std::mem::transmute(v) }
98    }
99}
100
101impl From<PlonkProofSol> for lightclientmock::IPlonkVerifier::PlonkProof {
102    fn from(v: PlonkProofSol) -> Self {
103        unsafe { std::mem::transmute(v) }
104    }
105}
106
107impl From<lightclientmock::LightClientMock::genesisStateReturn> for LightClientStateSol {
108    fn from(v: lightclientmock::LightClientMock::genesisStateReturn) -> Self {
109        unsafe { std::mem::transmute(v) }
110    }
111}
112
113impl From<LightClientV2::finalizedStateReturn> for LightClientStateSol {
114    fn from(v: LightClientV2::finalizedStateReturn) -> Self {
115        unsafe { std::mem::transmute(v) }
116    }
117}
118
119impl From<LightClientV2::votingStakeTableStateReturn> for StakeTableStateSol {
120    fn from(v: LightClientV2::votingStakeTableStateReturn) -> Self {
121        unsafe { std::mem::transmute(v) }
122    }
123}
124
125impl From<lightclientv2mock::LightClient::LightClientState> for LightClientStateSol {
126    fn from(v: lightclientv2mock::LightClient::LightClientState) -> Self {
127        unsafe { std::mem::transmute(v) }
128    }
129}
130impl From<LightClientStateSol> for lightclientv2mock::LightClient::LightClientState {
131    fn from(v: LightClientStateSol) -> Self {
132        unsafe { std::mem::transmute(v) }
133    }
134}
135impl From<LightClientStateSol> for lightclientv2::LightClient::LightClientState {
136    fn from(v: LightClientStateSol) -> Self {
137        unsafe { std::mem::transmute(v) }
138    }
139}
140
141impl From<StakeTableStateSol> for lightclientv2::LightClient::StakeTableState {
142    fn from(v: StakeTableStateSol) -> Self {
143        unsafe { std::mem::transmute(v) }
144    }
145}
146impl From<StakeTableStateSol> for lightclientv2mock::LightClient::StakeTableState {
147    fn from(v: StakeTableStateSol) -> Self {
148        unsafe { std::mem::transmute(v) }
149    }
150}
151
152impl From<LightClientV2Mock::genesisStateReturn> for LightClientStateSol {
153    fn from(v: LightClientV2Mock::genesisStateReturn) -> Self {
154        unsafe { std::mem::transmute(v) }
155    }
156}
157
158impl From<LightClientV2Mock::finalizedStateReturn> for LightClientStateSol {
159    fn from(v: LightClientV2Mock::finalizedStateReturn) -> Self {
160        unsafe { std::mem::transmute(v) }
161    }
162}
163
164impl From<PlonkProofSol> for lightclientv2::IPlonkVerifier::PlonkProof {
165    fn from(v: PlonkProofSol) -> Self {
166        unsafe { std::mem::transmute(v) }
167    }
168}
169
170impl From<LightClientV2Mock::votingStakeTableStateReturn> for StakeTableStateSol {
171    fn from(v: LightClientV2Mock::votingStakeTableStateReturn) -> Self {
172        unsafe { std::mem::transmute(v) }
173    }
174}
175
176impl From<G1PointSol> for staketable::BN254::G1Point {
177    fn from(v: G1PointSol) -> Self {
178        unsafe { std::mem::transmute(v) }
179    }
180}
181
182use serde::{Deserialize, Deserializer, Serialize, Serializer};
183
184use self::{
185    staketable::{EdOnBN254::EdOnBN254Point, BN254::G2Point},
186    StakeTable::{
187        ConsensusKeysUpdated, Delegated, Undelegated, ValidatorExit, ValidatorRegistered,
188    },
189};
190
191impl PartialEq for ValidatorRegistered {
192    fn eq(&self, other: &Self) -> bool {
193        self.account == other.account
194            && self.blsVk == other.blsVk
195            && self.schnorrVk == other.schnorrVk
196            && self.commission == other.commission
197    }
198}
199
200impl PartialEq for ConsensusKeysUpdated {
201    fn eq(&self, other: &Self) -> bool {
202        self.account == other.account
203            && self.blsVK == other.blsVK
204            && self.schnorrVK == other.schnorrVK
205    }
206}
207
208impl Serialize for ValidatorRegistered {
209    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
210    where
211        S: Serializer,
212    {
213        (&self.account, &self.blsVk, &self.schnorrVk, self.commission).serialize(serializer)
214    }
215}
216
217#[allow(non_snake_case)]
218impl<'de> Deserialize<'de> for ValidatorRegistered {
219    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
220    where
221        D: Deserializer<'de>,
222    {
223        let (account, blsVk, schnorrVk, commission) = <(_, _, _, u16)>::deserialize(deserializer)?;
224        Ok(ValidatorRegistered {
225            account,
226            blsVk,
227            schnorrVk,
228            commission,
229        })
230    }
231}
232
233impl Serialize for EdOnBN254Point {
234    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
235    where
236        S: Serializer,
237    {
238        (self.x, self.y).serialize(serializer)
239    }
240}
241
242impl<'de> Deserialize<'de> for EdOnBN254Point {
243    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
244    where
245        D: Deserializer<'de>,
246    {
247        let (x, y) = Deserialize::deserialize(deserializer)?;
248        Ok(EdOnBN254Point { x, y })
249    }
250}
251
252impl Serialize for G2Point {
253    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
254    where
255        S: Serializer,
256    {
257        (&self.x0, &self.x1, &self.y0, &self.y1).serialize(serializer)
258    }
259}
260
261impl<'de> Deserialize<'de> for G2Point {
262    fn deserialize<D>(deserializer: D) -> Result<G2Point, D::Error>
263    where
264        D: Deserializer<'de>,
265    {
266        let (x0, x1, y0, y1) = Deserialize::deserialize(deserializer)?;
267
268        Ok(G2Point { x0, x1, y0, y1 })
269    }
270}
271
272impl Serialize for ValidatorExit {
273    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
274    where
275        S: Serializer,
276    {
277        (&self.validator,).serialize(serializer)
278    }
279}
280
281impl<'de> Deserialize<'de> for ValidatorExit {
282    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
283    where
284        D: Deserializer<'de>,
285    {
286        let (validator,): (alloy::sol_types::private::Address,) =
287            Deserialize::deserialize(deserializer)?;
288        Ok(ValidatorExit { validator })
289    }
290}
291
292impl Serialize for Delegated {
293    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
294    where
295        S: Serializer,
296    {
297        (&self.delegator, &self.validator, &self.amount).serialize(serializer)
298    }
299}
300
301impl<'de> Deserialize<'de> for Delegated {
302    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
303    where
304        D: Deserializer<'de>,
305    {
306        let (delegator, validator, amount) = Deserialize::deserialize(deserializer)?;
307
308        Ok(Delegated {
309            delegator,
310            validator,
311            amount,
312        })
313    }
314}
315
316impl Serialize for Undelegated {
317    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
318    where
319        S: Serializer,
320    {
321        (&self.delegator, &self.validator, &self.amount).serialize(serializer)
322    }
323}
324
325impl<'de> Deserialize<'de> for Undelegated {
326    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
327    where
328        D: Deserializer<'de>,
329    {
330        let (delegator, validator, amount) = Deserialize::deserialize(deserializer)?;
331
332        Ok(Undelegated {
333            delegator,
334            validator,
335            amount,
336        })
337    }
338}
339
340impl Serialize for ConsensusKeysUpdated {
341    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
342    where
343        S: Serializer,
344    {
345        (&self.account, &self.blsVK, &self.schnorrVK).serialize(serializer)
346    }
347}
348
349#[allow(non_snake_case)]
350impl<'de> Deserialize<'de> for ConsensusKeysUpdated {
351    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
352    where
353        D: Deserializer<'de>,
354    {
355        let (account, blsVK, schnorrVK) = Deserialize::deserialize(deserializer)?;
356
357        Ok(ConsensusKeysUpdated {
358            account,
359            blsVK,
360            schnorrVK,
361        })
362    }
363}