iota_bridge/
eth_transaction_builder.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use ethers::{prelude::*, types::Address as EthAddress};
6
7use crate::{
8    abi::{
9        EthBridgeCommittee, EthBridgeConfig, EthBridgeLimiter, EthCommitteeUpgradeableContract,
10        EthIotaBridge, eth_bridge_committee, eth_bridge_config, eth_bridge_limiter,
11        eth_committee_upgradeable_contract, eth_iota_bridge,
12    },
13    error::{BridgeError, BridgeResult},
14    types::{
15        AddTokensOnEvmAction, AssetPriceUpdateAction, BlocklistCommitteeAction, BridgeAction,
16        BridgeCommitteeValiditySignInfo, EmergencyAction, EvmContractUpgradeAction,
17        LimitUpdateAction, VerifiedCertifiedBridgeAction,
18    },
19    utils::EthSigner,
20};
21
22pub async fn build_eth_transaction(
23    contract_address: EthAddress,
24    signer: EthSigner,
25    action: VerifiedCertifiedBridgeAction,
26) -> BridgeResult<ContractCall<EthSigner, ()>> {
27    if !action.is_governace_action() {
28        return Err(BridgeError::ActionIsNotGovernanceAction(
29            action.data().clone(),
30        ));
31    }
32    // TODO: Check chain id?
33    let sigs = action.auth_sig();
34    match action.data() {
35        BridgeAction::IotaToEthBridgeAction(_) => {
36            unreachable!()
37        }
38        BridgeAction::EthToIotaBridgeAction(_) => {
39            unreachable!()
40        }
41        BridgeAction::EmergencyAction(action) => {
42            build_emergency_op_approve_transaction(contract_address, signer, action.clone(), sigs)
43                .await
44        }
45        BridgeAction::BlocklistCommitteeAction(action) => {
46            build_committee_blocklist_approve_transaction(
47                contract_address,
48                signer,
49                action.clone(),
50                sigs,
51            )
52            .await
53        }
54        BridgeAction::LimitUpdateAction(action) => {
55            build_limit_update_approve_transaction(contract_address, signer, action.clone(), sigs)
56                .await
57        }
58        BridgeAction::AssetPriceUpdateAction(action) => {
59            build_asset_price_update_approve_transaction(
60                contract_address,
61                signer,
62                action.clone(),
63                sigs,
64            )
65            .await
66        }
67        BridgeAction::EvmContractUpgradeAction(action) => {
68            build_evm_upgrade_transaction(signer, action.clone(), sigs).await
69        }
70        BridgeAction::AddTokensOnIotaAction(_) => {
71            unreachable!();
72        }
73        BridgeAction::AddTokensOnEvmAction(action) => {
74            build_add_tokens_on_evm_transaction(contract_address, signer, action.clone(), sigs)
75                .await
76        }
77    }
78}
79
80pub async fn build_emergency_op_approve_transaction(
81    contract_address: EthAddress,
82    signer: EthSigner,
83    action: EmergencyAction,
84    sigs: &BridgeCommitteeValiditySignInfo,
85) -> BridgeResult<ContractCall<EthSigner, ()>> {
86    let contract = EthIotaBridge::new(contract_address, signer.into());
87
88    let message: eth_iota_bridge::Message = action.clone().into();
89    let signatures = sigs
90        .signatures
91        .values()
92        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
93        .collect::<Vec<_>>();
94    Ok(contract.execute_emergency_op_with_signatures(signatures, message))
95}
96
97pub async fn build_committee_blocklist_approve_transaction(
98    contract_address: EthAddress,
99    signer: EthSigner,
100    action: BlocklistCommitteeAction,
101    sigs: &BridgeCommitteeValiditySignInfo,
102) -> BridgeResult<ContractCall<EthSigner, ()>> {
103    let contract = EthBridgeCommittee::new(contract_address, signer.into());
104
105    let message: eth_bridge_committee::Message = action.clone().into();
106    let signatures = sigs
107        .signatures
108        .values()
109        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
110        .collect::<Vec<_>>();
111    Ok(contract.update_blocklist_with_signatures(signatures, message))
112}
113
114pub async fn build_limit_update_approve_transaction(
115    contract_address: EthAddress,
116    signer: EthSigner,
117    action: LimitUpdateAction,
118    sigs: &BridgeCommitteeValiditySignInfo,
119) -> BridgeResult<ContractCall<EthSigner, ()>> {
120    let contract = EthBridgeLimiter::new(contract_address, signer.into());
121
122    let message: eth_bridge_limiter::Message = action.clone().into();
123    let signatures = sigs
124        .signatures
125        .values()
126        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
127        .collect::<Vec<_>>();
128    Ok(contract.update_limit_with_signatures(signatures, message))
129}
130
131pub async fn build_asset_price_update_approve_transaction(
132    contract_address: EthAddress,
133    signer: EthSigner,
134    action: AssetPriceUpdateAction,
135    sigs: &BridgeCommitteeValiditySignInfo,
136) -> BridgeResult<ContractCall<EthSigner, ()>> {
137    let contract = EthBridgeConfig::new(contract_address, signer.into());
138    let message: eth_bridge_config::Message = action.clone().into();
139    let signatures = sigs
140        .signatures
141        .values()
142        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
143        .collect::<Vec<_>>();
144    Ok(contract.update_token_price_with_signatures(signatures, message))
145}
146
147pub async fn build_add_tokens_on_evm_transaction(
148    contract_address: EthAddress,
149    signer: EthSigner,
150    action: AddTokensOnEvmAction,
151    sigs: &BridgeCommitteeValiditySignInfo,
152) -> BridgeResult<ContractCall<EthSigner, ()>> {
153    let contract = EthBridgeConfig::new(contract_address, signer.into());
154    let message: eth_bridge_config::Message = action.clone().into();
155    let signatures = sigs
156        .signatures
157        .values()
158        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
159        .collect::<Vec<_>>();
160    Ok(contract.add_tokens_with_signatures(signatures, message))
161}
162
163pub async fn build_evm_upgrade_transaction(
164    signer: EthSigner,
165    action: EvmContractUpgradeAction,
166    sigs: &BridgeCommitteeValiditySignInfo,
167) -> BridgeResult<ContractCall<EthSigner, ()>> {
168    let contract_address = action.proxy_address;
169    let contract = EthCommitteeUpgradeableContract::new(contract_address, signer.into());
170    let message: eth_committee_upgradeable_contract::Message = action.clone().into();
171    let signatures = sigs
172        .signatures
173        .values()
174        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
175        .collect::<Vec<_>>();
176    Ok(contract.upgrade_with_signatures(signatures, message))
177}
178
179// TODO: add tests for eth transaction building