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    esptokenv2::EspTokenV2,
29    feecontract::FeeContract::{self, Deposit},
30    lightclient::{
31        IPlonkVerifier::{PlonkProof as PlonkProofSol, VerifyingKey as VerifyingKeySol},
32        LightClient::{
33            self, LightClientErrors, LightClientInstance, LightClientState as LightClientStateSol,
34            StakeTableState as StakeTableStateSol,
35        },
36        BN254::G1Point as G1PointSol,
37    },
38    lightclientmock::{self, LightClientMock},
39    lightclientv2::{self, LightClientV2},
40    lightclientv2mock::{self, LightClientV2Mock},
41    lightclientv3::{self, LightClientV3},
42    lightclientv3mock::{self, LightClientV3Mock},
43    opstimelock::OpsTimelock,
44    ownableupgradeable::OwnableUpgradeable,
45    plonkverifier::PlonkVerifier,
46    plonkverifierv2::PlonkVerifierV2,
47    plonkverifierv3::PlonkVerifierV3,
48    rewardclaimprototypemock::{
49        RewardClaimPrototypeMock,
50        RewardMerkleTreeVerifier::AccruedRewardsProof as AccruedRewardsProofSol,
51    },
52    safeexittimelock::SafeExitTimelock,
53    staketable::StakeTable,
54    staketablev2::{
55        self, EdOnBN254::EdOnBN254Point as EdOnBN254PointSol, StakeTableV2,
56        BN254::G2Point as G2PointSol,
57    },
58};
59
60// For types that we need to interact with some functions but their bindings are not generated
61// we manually declare them there. It's possible that they get included in the future commits,
62// at which point, the rust type system will complain and we simply remove the manual declaration
63// and re-export the type from bindings instead.
64sol! {
65    /// types in src/legacy/Transcript.sol
66    struct TranscriptDataSol {
67        bytes32 state;
68        bytes transcript;
69    }
70
71    /// types in src/libraries/PlonkVerifierV2.sol
72    struct ChallengesSol {
73        uint256 alpha;
74        uint256 alpha2;
75        uint256 alpha3;
76        uint256 beta;
77        uint256 gamma;
78        uint256 zeta;
79        uint256 v;
80        uint256 u;
81    }
82
83}
84
85// Due to <https://github.com/foundry-rs/foundry/issues/10153> the rust bindings contain duplicate types for our solidity types.
86// In order to avoid writing a lot of boilerplate code we use transmute to convert between these duplicated types.
87// Since all the types we transmute between are generated by foundry from the same underlying solidity type
88// we expect that the order of fields and types of fields are always the same.
89impl From<LightClient::genesisStateReturn> for LightClientStateSol {
90    fn from(v: LightClient::genesisStateReturn) -> Self {
91        unsafe { std::mem::transmute(v) }
92    }
93}
94
95impl From<lightclientmock::LightClient::LightClientState> for LightClientStateSol {
96    fn from(v: lightclientmock::LightClient::LightClientState) -> Self {
97        unsafe { std::mem::transmute(v) }
98    }
99}
100impl From<lightclientmock::LightClientMock::finalizedStateReturn> for LightClientStateSol {
101    fn from(v: lightclientmock::LightClientMock::finalizedStateReturn) -> Self {
102        unsafe { std::mem::transmute(v) }
103    }
104}
105
106impl From<LightClientStateSol> for lightclientmock::LightClient::LightClientState {
107    fn from(v: LightClientStateSol) -> Self {
108        unsafe { std::mem::transmute(v) }
109    }
110}
111
112impl From<PlonkProofSol> for lightclientmock::IPlonkVerifier::PlonkProof {
113    fn from(v: PlonkProofSol) -> Self {
114        unsafe { std::mem::transmute(v) }
115    }
116}
117
118impl From<lightclientmock::LightClientMock::genesisStateReturn> for LightClientStateSol {
119    fn from(v: lightclientmock::LightClientMock::genesisStateReturn) -> Self {
120        unsafe { std::mem::transmute(v) }
121    }
122}
123
124impl From<LightClientV2::finalizedStateReturn> for LightClientStateSol {
125    fn from(v: LightClientV2::finalizedStateReturn) -> Self {
126        unsafe { std::mem::transmute(v) }
127    }
128}
129
130impl From<LightClientV2::votingStakeTableStateReturn> for StakeTableStateSol {
131    fn from(v: LightClientV2::votingStakeTableStateReturn) -> Self {
132        unsafe { std::mem::transmute(v) }
133    }
134}
135
136impl From<lightclientv2mock::LightClient::LightClientState> for LightClientStateSol {
137    fn from(v: lightclientv2mock::LightClient::LightClientState) -> Self {
138        unsafe { std::mem::transmute(v) }
139    }
140}
141impl From<LightClientStateSol> for lightclientv2mock::LightClient::LightClientState {
142    fn from(v: LightClientStateSol) -> Self {
143        unsafe { std::mem::transmute(v) }
144    }
145}
146impl From<LightClientStateSol> for lightclientv2::LightClient::LightClientState {
147    fn from(v: LightClientStateSol) -> Self {
148        unsafe { std::mem::transmute(v) }
149    }
150}
151
152impl From<StakeTableStateSol> for lightclientv2::LightClient::StakeTableState {
153    fn from(v: StakeTableStateSol) -> Self {
154        unsafe { std::mem::transmute(v) }
155    }
156}
157impl From<StakeTableStateSol> for lightclientv2mock::LightClient::StakeTableState {
158    fn from(v: StakeTableStateSol) -> Self {
159        unsafe { std::mem::transmute(v) }
160    }
161}
162
163impl From<LightClientV2Mock::genesisStateReturn> for LightClientStateSol {
164    fn from(v: LightClientV2Mock::genesisStateReturn) -> Self {
165        unsafe { std::mem::transmute(v) }
166    }
167}
168
169impl From<LightClientV2Mock::finalizedStateReturn> for LightClientStateSol {
170    fn from(v: LightClientV2Mock::finalizedStateReturn) -> Self {
171        unsafe { std::mem::transmute(v) }
172    }
173}
174
175impl From<PlonkProofSol> for lightclientv2::IPlonkVerifier::PlonkProof {
176    fn from(v: PlonkProofSol) -> Self {
177        unsafe { std::mem::transmute(v) }
178    }
179}
180
181impl From<LightClientV2Mock::votingStakeTableStateReturn> for StakeTableStateSol {
182    fn from(v: LightClientV2Mock::votingStakeTableStateReturn) -> Self {
183        unsafe { std::mem::transmute(v) }
184    }
185}
186
187impl From<G1PointSol> for staketablev2::BN254::G1Point {
188    fn from(v: G1PointSol) -> Self {
189        unsafe { std::mem::transmute(v) }
190    }
191}
192
193impl From<staketablev2::BN254::G1Point> for G1PointSol {
194    fn from(v: staketablev2::BN254::G1Point) -> Self {
195        unsafe { std::mem::transmute(v) }
196    }
197}
198
199// Transmute conversion functions for LightClientV3
200impl From<LightClientV3::finalizedStateReturn> for LightClientStateSol {
201    fn from(v: LightClientV3::finalizedStateReturn) -> Self {
202        unsafe { std::mem::transmute(v) }
203    }
204}
205
206impl From<LightClientV3::votingStakeTableStateReturn> for StakeTableStateSol {
207    fn from(v: LightClientV3::votingStakeTableStateReturn) -> Self {
208        unsafe { std::mem::transmute(v) }
209    }
210}
211
212impl From<LightClientStateSol> for lightclientv3::LightClient::LightClientState {
213    fn from(v: LightClientStateSol) -> Self {
214        unsafe { std::mem::transmute(v) }
215    }
216}
217
218impl From<StakeTableStateSol> for lightclientv3::LightClient::StakeTableState {
219    fn from(v: StakeTableStateSol) -> Self {
220        unsafe { std::mem::transmute(v) }
221    }
222}
223
224impl From<PlonkProofSol> for lightclientv3::IPlonkVerifier::PlonkProof {
225    fn from(v: PlonkProofSol) -> Self {
226        unsafe { std::mem::transmute(v) }
227    }
228}
229
230// Transmute conversion functions for LightClientV3Mock
231impl From<lightclientv3mock::LightClient::LightClientState> for LightClientStateSol {
232    fn from(v: lightclientv3mock::LightClient::LightClientState) -> Self {
233        unsafe { std::mem::transmute(v) }
234    }
235}
236
237impl From<LightClientStateSol> for lightclientv3mock::LightClient::LightClientState {
238    fn from(v: LightClientStateSol) -> Self {
239        unsafe { std::mem::transmute(v) }
240    }
241}
242
243impl From<StakeTableStateSol> for lightclientv3mock::LightClient::StakeTableState {
244    fn from(v: StakeTableStateSol) -> Self {
245        unsafe { std::mem::transmute(v) }
246    }
247}
248
249impl From<LightClientV3Mock::genesisStateReturn> for LightClientStateSol {
250    fn from(v: LightClientV3Mock::genesisStateReturn) -> Self {
251        unsafe { std::mem::transmute(v) }
252    }
253}
254
255impl From<LightClientV3Mock::finalizedStateReturn> for LightClientStateSol {
256    fn from(v: LightClientV3Mock::finalizedStateReturn) -> Self {
257        unsafe { std::mem::transmute(v) }
258    }
259}
260
261impl From<LightClientV3Mock::votingStakeTableStateReturn> for StakeTableStateSol {
262    fn from(v: LightClientV3Mock::votingStakeTableStateReturn) -> Self {
263        unsafe { std::mem::transmute(v) }
264    }
265}
266
267use serde::{Deserialize, Deserializer, Serialize, Serializer};
268
269use self::{
270    staketablev2::{EdOnBN254::EdOnBN254Point, BN254::G2Point},
271    StakeTableV2::{
272        ConsensusKeysUpdated, ConsensusKeysUpdatedV2, Delegated, Undelegated, ValidatorExit,
273        ValidatorRegistered, ValidatorRegisteredV2,
274    },
275};
276
277impl PartialEq for ValidatorRegistered {
278    fn eq(&self, other: &Self) -> bool {
279        self.account == other.account
280            && self.blsVk == other.blsVk
281            && self.schnorrVk == other.schnorrVk
282            && self.commission == other.commission
283    }
284}
285
286impl PartialEq for ValidatorRegisteredV2 {
287    fn eq(&self, other: &Self) -> bool {
288        self.account == other.account
289            && self.blsVK == other.blsVK
290            && self.schnorrVK == other.schnorrVK
291            && self.commission == other.commission
292            && self.blsSig == other.blsSig
293            && self.schnorrSig == other.schnorrSig
294    }
295}
296
297impl PartialEq for ConsensusKeysUpdated {
298    fn eq(&self, other: &Self) -> bool {
299        self.account == other.account
300            && self.blsVK == other.blsVK
301            && self.schnorrVK == other.schnorrVK
302    }
303}
304
305impl PartialEq for ConsensusKeysUpdatedV2 {
306    fn eq(&self, other: &Self) -> bool {
307        self.account == other.account
308            && self.blsVK == other.blsVK
309            && self.schnorrVK == other.schnorrVK
310            && self.blsSig == other.blsSig
311            && self.schnorrSig == other.schnorrSig
312    }
313}
314
315impl Serialize for ValidatorRegistered {
316    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
317    where
318        S: Serializer,
319    {
320        (&self.account, &self.blsVk, &self.schnorrVk, self.commission).serialize(serializer)
321    }
322}
323
324#[allow(non_snake_case)]
325impl<'de> Deserialize<'de> for ValidatorRegistered {
326    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
327    where
328        D: Deserializer<'de>,
329    {
330        let (account, blsVk, schnorrVk, commission) = <(_, _, _, u16)>::deserialize(deserializer)?;
331        Ok(Self {
332            account,
333            blsVk,
334            schnorrVk,
335            commission,
336        })
337    }
338}
339
340impl Serialize for ValidatorRegisteredV2 {
341    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
342    where
343        S: Serializer,
344    {
345        (
346            &self.account,
347            &self.blsVK,
348            &self.schnorrVK,
349            self.commission,
350            &self.blsSig,
351            &self.schnorrSig,
352        )
353            .serialize(serializer)
354    }
355}
356
357#[allow(non_snake_case)]
358impl<'de> Deserialize<'de> for ValidatorRegisteredV2 {
359    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
360    where
361        D: Deserializer<'de>,
362    {
363        let (account, blsVK, schnorrVK, commission, blsSig, schnorrSig) =
364            <(_, _, _, u16, _, _)>::deserialize(deserializer)?;
365        Ok(ValidatorRegisteredV2 {
366            account,
367            blsVK,
368            schnorrVK,
369            commission,
370            blsSig,
371            schnorrSig,
372        })
373    }
374}
375
376impl Serialize for EdOnBN254Point {
377    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
378    where
379        S: Serializer,
380    {
381        (self.x, self.y).serialize(serializer)
382    }
383}
384
385impl<'de> Deserialize<'de> for EdOnBN254Point {
386    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
387    where
388        D: Deserializer<'de>,
389    {
390        let (x, y) = Deserialize::deserialize(deserializer)?;
391        Ok(Self { x, y })
392    }
393}
394
395impl Serialize for G2Point {
396    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
397    where
398        S: Serializer,
399    {
400        (&self.x0, &self.x1, &self.y0, &self.y1).serialize(serializer)
401    }
402}
403
404impl<'de> Deserialize<'de> for G2Point {
405    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
406    where
407        D: Deserializer<'de>,
408    {
409        let (x0, x1, y0, y1) = Deserialize::deserialize(deserializer)?;
410
411        Ok(Self { x0, x1, y0, y1 })
412    }
413}
414
415impl Serialize for staketablev2::BN254::G1Point {
416    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
417    where
418        S: Serializer,
419    {
420        (&self.x, &self.y).serialize(serializer)
421    }
422}
423
424impl<'de> Deserialize<'de> for staketablev2::BN254::G1Point {
425    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
426    where
427        D: Deserializer<'de>,
428    {
429        let (x, y) = Deserialize::deserialize(deserializer)?;
430        Ok(Self { x, y })
431    }
432}
433
434impl Serialize for ValidatorExit {
435    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
436    where
437        S: Serializer,
438    {
439        (&self.validator,).serialize(serializer)
440    }
441}
442
443impl<'de> Deserialize<'de> for ValidatorExit {
444    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
445    where
446        D: Deserializer<'de>,
447    {
448        let (validator,): (alloy::sol_types::private::Address,) =
449            Deserialize::deserialize(deserializer)?;
450        Ok(ValidatorExit { validator })
451    }
452}
453
454impl Serialize for Delegated {
455    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
456    where
457        S: Serializer,
458    {
459        (&self.delegator, &self.validator, &self.amount).serialize(serializer)
460    }
461}
462
463impl<'de> Deserialize<'de> for Delegated {
464    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
465    where
466        D: Deserializer<'de>,
467    {
468        let (delegator, validator, amount) = Deserialize::deserialize(deserializer)?;
469
470        Ok(Delegated {
471            delegator,
472            validator,
473            amount,
474        })
475    }
476}
477
478impl Serialize for Undelegated {
479    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
480    where
481        S: Serializer,
482    {
483        (&self.delegator, &self.validator, &self.amount).serialize(serializer)
484    }
485}
486
487impl<'de> Deserialize<'de> for Undelegated {
488    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
489    where
490        D: Deserializer<'de>,
491    {
492        let (delegator, validator, amount) = Deserialize::deserialize(deserializer)?;
493
494        Ok(Undelegated {
495            delegator,
496            validator,
497            amount,
498        })
499    }
500}
501
502impl Serialize for ConsensusKeysUpdated {
503    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
504    where
505        S: Serializer,
506    {
507        (&self.account, &self.blsVK, &self.schnorrVK).serialize(serializer)
508    }
509}
510
511#[allow(non_snake_case)]
512impl<'de> Deserialize<'de> for ConsensusKeysUpdated {
513    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
514    where
515        D: Deserializer<'de>,
516    {
517        let (account, blsVK, schnorrVK) = Deserialize::deserialize(deserializer)?;
518
519        Ok(ConsensusKeysUpdated {
520            account,
521            blsVK,
522            schnorrVK,
523        })
524    }
525}
526
527impl Serialize for ConsensusKeysUpdatedV2 {
528    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
529    where
530        S: Serializer,
531    {
532        (
533            &self.account,
534            &self.blsVK,
535            &self.schnorrVK,
536            &self.blsSig,
537            &self.schnorrSig,
538        )
539            .serialize(serializer)
540    }
541}
542
543#[allow(non_snake_case)]
544impl<'de> Deserialize<'de> for ConsensusKeysUpdatedV2 {
545    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
546    where
547        D: Deserializer<'de>,
548    {
549        let (account, blsVK, schnorrVK, blsSig, schnorrSig) =
550            Deserialize::deserialize(deserializer)?;
551
552        Ok(ConsensusKeysUpdatedV2 {
553            account,
554            blsVK,
555            schnorrVK,
556            blsSig,
557            schnorrSig,
558        })
559    }
560}