sui_bridge/
eth_transaction_builder.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::abi::{
5    eth_bridge_committee, eth_bridge_config, eth_bridge_limiter,
6    eth_committee_upgradeable_contract, eth_sui_bridge,
7};
8use crate::error::{BridgeError, BridgeResult};
9use crate::types::{
10    AddTokensOnEvmAction, AssetPriceUpdateAction, BlocklistCommitteeAction, BridgeAction,
11    BridgeCommitteeValiditySignInfo, EmergencyAction, EvmContractUpgradeAction, LimitUpdateAction,
12    VerifiedCertifiedBridgeAction,
13};
14use alloy::network::TransactionBuilder;
15use alloy::primitives::{Address as EthAddress, Bytes};
16use alloy::rpc::types::TransactionRequest;
17use alloy::sol_types::SolCall;
18
19pub async fn build_eth_transaction(
20    contract_address: EthAddress,
21    action: VerifiedCertifiedBridgeAction,
22) -> BridgeResult<TransactionRequest> {
23    if !action.is_governance_action() {
24        return Err(BridgeError::ActionIsNotGovernanceAction(Box::new(
25            action.data().clone(),
26        )));
27    }
28    // TODO: Check chain id?
29    let sigs = action.auth_sig();
30    match action.data() {
31        BridgeAction::SuiToEthBridgeAction(_) => {
32            unreachable!()
33        }
34        BridgeAction::SuiToEthTokenTransfer(_) => {
35            unreachable!()
36        }
37        BridgeAction::SuiToEthTokenTransferV2(_) => {
38            unreachable!()
39        }
40        BridgeAction::EthToSuiBridgeAction(_) => {
41            unreachable!()
42        }
43        BridgeAction::EthToSuiTokenTransferV2(_) => {
44            unreachable!()
45        }
46        BridgeAction::EmergencyAction(action) => {
47            build_emergency_op_approve_transaction(contract_address, action.clone(), sigs)
48        }
49        BridgeAction::BlocklistCommitteeAction(action) => {
50            build_committee_blocklist_approve_transaction(contract_address, action.clone(), sigs)
51        }
52        BridgeAction::LimitUpdateAction(action) => {
53            build_limit_update_approve_transaction(contract_address, action.clone(), sigs)
54        }
55        BridgeAction::AssetPriceUpdateAction(action) => {
56            build_asset_price_update_approve_transaction(contract_address, action.clone(), sigs)
57        }
58        BridgeAction::EvmContractUpgradeAction(action) => {
59            build_evm_upgrade_transaction(action.clone(), sigs)
60        }
61        BridgeAction::AddTokensOnSuiAction(_) => {
62            unreachable!();
63        }
64        BridgeAction::AddTokensOnEvmAction(action) => {
65            build_add_tokens_on_evm_transaction(contract_address, action.clone(), sigs)
66        }
67    }
68}
69
70pub fn build_emergency_op_approve_transaction(
71    contract_address: EthAddress,
72    action: EmergencyAction,
73    sigs: &BridgeCommitteeValiditySignInfo,
74) -> BridgeResult<TransactionRequest> {
75    let message: eth_sui_bridge::BridgeUtils::Message = action.clone().try_into()?;
76    let signatures = sigs
77        .signatures
78        .values()
79        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
80        .collect::<Vec<_>>();
81
82    let call = eth_sui_bridge::EthSuiBridge::executeEmergencyOpWithSignaturesCall {
83        signatures,
84        message,
85    };
86    Ok(TransactionRequest::default()
87        .with_to(contract_address)
88        .with_input(call.abi_encode()))
89}
90
91pub fn build_committee_blocklist_approve_transaction(
92    contract_address: EthAddress,
93    action: BlocklistCommitteeAction,
94    sigs: &BridgeCommitteeValiditySignInfo,
95) -> BridgeResult<TransactionRequest> {
96    let message: eth_bridge_committee::BridgeUtils::Message = action.clone().try_into()?;
97    let signatures = sigs
98        .signatures
99        .values()
100        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
101        .collect::<Vec<_>>();
102
103    let call = eth_bridge_committee::EthBridgeCommittee::updateBlocklistWithSignaturesCall {
104        signatures,
105        message,
106    };
107    Ok(TransactionRequest::default()
108        .with_to(contract_address)
109        .with_input(call.abi_encode()))
110}
111
112pub fn build_limit_update_approve_transaction(
113    contract_address: EthAddress,
114    action: LimitUpdateAction,
115    sigs: &BridgeCommitteeValiditySignInfo,
116) -> BridgeResult<TransactionRequest> {
117    let message: eth_bridge_limiter::BridgeUtils::Message = action.clone().try_into()?;
118    let signatures = sigs
119        .signatures
120        .values()
121        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
122        .collect::<Vec<_>>();
123
124    let call = eth_bridge_limiter::EthBridgeLimiter::updateLimitWithSignaturesCall {
125        signatures,
126        message,
127    };
128    Ok(TransactionRequest::default()
129        .with_to(contract_address)
130        .with_input(call.abi_encode()))
131}
132
133pub fn build_asset_price_update_approve_transaction(
134    contract_address: EthAddress,
135    action: AssetPriceUpdateAction,
136    sigs: &BridgeCommitteeValiditySignInfo,
137) -> BridgeResult<TransactionRequest> {
138    let message: eth_bridge_config::BridgeUtils::Message = action.clone().try_into()?;
139    let signatures = sigs
140        .signatures
141        .values()
142        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
143        .collect::<Vec<_>>();
144
145    let call = eth_bridge_config::EthBridgeConfig::updateTokenPriceWithSignaturesCall {
146        signatures,
147        message,
148    };
149    Ok(TransactionRequest::default()
150        .with_to(contract_address)
151        .with_input(call.abi_encode()))
152}
153
154pub fn build_add_tokens_on_evm_transaction(
155    contract_address: EthAddress,
156    action: AddTokensOnEvmAction,
157    sigs: &BridgeCommitteeValiditySignInfo,
158) -> BridgeResult<TransactionRequest> {
159    let message: eth_bridge_config::BridgeUtils::Message = action.clone().try_into()?;
160    let signatures = sigs
161        .signatures
162        .values()
163        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
164        .collect::<Vec<_>>();
165
166    let call = eth_bridge_config::EthBridgeConfig::addTokensWithSignaturesCall {
167        signatures,
168        message,
169    };
170    Ok(TransactionRequest::default()
171        .with_to(contract_address)
172        .with_input(call.abi_encode()))
173}
174
175pub fn build_evm_upgrade_transaction(
176    action: EvmContractUpgradeAction,
177    sigs: &BridgeCommitteeValiditySignInfo,
178) -> BridgeResult<TransactionRequest> {
179    let contract_address = action.proxy_address;
180    let message: eth_committee_upgradeable_contract::BridgeUtils::Message =
181        action.clone().try_into()?;
182    let signatures = sigs
183        .signatures
184        .values()
185        .map(|sig| Bytes::from(sig.as_ref().to_vec()))
186        .collect::<Vec<_>>();
187
188    let call = eth_committee_upgradeable_contract::EthCommitteeUpgradeableContract::upgradeWithSignaturesCall {
189        signatures,
190        message,
191    };
192    Ok(TransactionRequest::default()
193        .with_to(contract_address)
194        .with_input(call.abi_encode()))
195}
196
197// TODO: add tests for eth transaction building