-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Withdrawal intent 32byte pubkey (#288)
* use 32 byte calldata for bridge out precompile and withdrawal intent * require withdrawal to equal 10btc burn bridge out amount add checks to funtional test * resolve pr comments * address PR comments
- Loading branch information
Showing
11 changed files
with
149 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,9 @@ | ||
pub use crate::precompiles::bridge::BRIDGEOUT_ADDRESS; | ||
use revm_primitives::{address, Address, U256}; | ||
|
||
use crate::utils::{u256_from, WEI_PER_BTC}; | ||
|
||
/// The address for the Bridgeout precompile contract. | ||
pub const BRIDGEOUT_ADDRESS: Address = address!("000000000000000000000000000000000b121d9e"); | ||
|
||
/// The fixed withdrawal amount in wei (10 BTC equivalent). | ||
pub const FIXED_WITHDRAWAL_WEI: U256 = u256_from(10 * WEI_PER_BTC); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,84 +1,84 @@ | ||
use std::array::TryFromSliceError; | ||
|
||
use revm::{ContextStatefulPrecompile, Database}; | ||
use revm_primitives::{ | ||
address, Address, Bytes, Log, LogData, PrecompileError, PrecompileErrors, PrecompileOutput, | ||
Bytes, FixedBytes, Log, LogData, PrecompileError, PrecompileErrors, PrecompileOutput, | ||
PrecompileResult, U256, | ||
}; | ||
|
||
use crate::primitives::WithdrawalIntentEvent; | ||
pub use crate::constants::BRIDGEOUT_ADDRESS; | ||
use crate::{primitives::WithdrawalIntentEvent, utils::wei_to_sats}; | ||
|
||
// TODO: address? | ||
pub const BRIDGEOUT_ADDRESS: Address = address!("000000000000000000000000000000000b121d9e"); | ||
const MIN_WITHDRAWAL_WEI: u128 = 1_000_000_000_000_000_000u128; | ||
/// Ensure that input is exactly 32 bytes | ||
fn try_into_pubkey(maybe_pubkey: &Bytes) -> Result<FixedBytes<32>, TryFromSliceError> { | ||
maybe_pubkey.as_ref().try_into() | ||
} | ||
|
||
/// Custom precompile to burn rollup native token and add bridge out intent of equal amount. | ||
/// Bridge out intent is created during block payload generation. | ||
/// This precompile validates transaction and burns the bridge out amount. | ||
pub struct BridgeoutPrecompile { | ||
min_withdrawal_wei: U256, | ||
fixed_withdrawal_wei: U256, | ||
} | ||
|
||
impl Default for BridgeoutPrecompile { | ||
fn default() -> Self { | ||
impl BridgeoutPrecompile { | ||
pub fn new(fixed_withdrawal_wei: U256) -> Self { | ||
Self { | ||
min_withdrawal_wei: U256::from(MIN_WITHDRAWAL_WEI), | ||
fixed_withdrawal_wei, | ||
} | ||
} | ||
} | ||
|
||
impl<DB: Database> ContextStatefulPrecompile<DB> for BridgeoutPrecompile { | ||
fn call( | ||
&self, | ||
bytes: &Bytes, | ||
dest_pk_bytes: &Bytes, | ||
_gas_limit: u64, | ||
evmctx: &mut revm::InnerEvmContext<DB>, | ||
) -> PrecompileResult { | ||
// ensure valid calldata | ||
if bytes.len() != 64 { | ||
return Err(PrecompileErrors::Error(PrecompileError::other( | ||
"invalid data", | ||
))); | ||
} | ||
// Validate the length of the destination public key | ||
let dest_pk = try_into_pubkey(dest_pk_bytes) | ||
.map_err(|_| PrecompileError::other("Invalid public key length: expected 32 bytes"))?; | ||
|
||
// ensure minimum bridgeout amount | ||
let value = evmctx.env.tx.value; | ||
if value < self.min_withdrawal_wei { | ||
return Err(PrecompileErrors::Error(PrecompileError::other( | ||
"below min withdrawal amt", | ||
))); | ||
// Verify that the transaction value matches the required withdrawal amount | ||
let withdrawal_amount = evmctx.env.tx.value; | ||
if withdrawal_amount != self.fixed_withdrawal_wei { | ||
return Err(PrecompileError::other( | ||
"Invalid withdrawal value: must be exactly 10 BTC in wei", | ||
) | ||
.into()); | ||
} | ||
|
||
let (sats, rem) = value.div_rem(U256::from(10_000_000_000u128)); | ||
// Convert wei to satoshis | ||
let (sats, _) = wei_to_sats(withdrawal_amount); | ||
|
||
if !rem.is_zero() { | ||
// ensure there are no leftovers that get lost. | ||
// is this important? | ||
return Err(PrecompileErrors::Error(PrecompileError::other( | ||
"value must be exact sats", | ||
))); | ||
} | ||
// Try converting sats (U256) into u64 amount | ||
let amount: u64 = sats.try_into().map_err(|_| PrecompileErrors::Fatal { | ||
msg: "Withdrawal amount exceeds maximum allowed value".into(), | ||
})?; | ||
|
||
let Ok(amount) = sats.try_into() else { | ||
// should never happen. 2^64 ~ 8700 x total_btc_stats | ||
return Err(PrecompileErrors::Error(PrecompileError::other( | ||
"above max withdrawal amt", | ||
))); | ||
}; | ||
|
||
// log bridge withdrawal intent | ||
let evt = WithdrawalIntentEvent { | ||
amount, | ||
dest_pk: bytes.clone(), | ||
}; | ||
// Log the bridge withdrawal intent | ||
let evt = WithdrawalIntentEvent { amount, dest_pk }; | ||
let logdata = LogData::from(&evt); | ||
|
||
evmctx.journaled_state.log(Log { | ||
address: BRIDGEOUT_ADDRESS, | ||
data: logdata, | ||
}); | ||
|
||
// TODO: burn value | ||
// Burn value sent to bridge by adjusting the account balance of bridge precompile | ||
let (account, _) = evmctx | ||
.load_account(BRIDGEOUT_ADDRESS) | ||
// Error case should never occur | ||
.map_err(|_| PrecompileErrors::Fatal { | ||
msg: "Failed to load BRIDGEOUT_ADDRESS account".into(), | ||
})?; | ||
|
||
account.info.balance = U256::ZERO; | ||
|
||
// TODO: Properly calculate and deduct gas for the bridge out operation | ||
let gas_cost = 0; | ||
|
||
// TODO: gas for bridge out, using 0 gas currently | ||
Ok(PrecompileOutput::new(0, Bytes::new())) | ||
Ok(PrecompileOutput::new(gas_cost, Bytes::new())) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,24 @@ | ||
use alloy_sol_types::sol; | ||
use reth_primitives::B512; | ||
use reth_primitives::B256; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
/// Type for withdrawal_intents in rpc. | ||
/// Distinct from [`bridge_ops::WithdrawalIntents`] as this will live in reth repo eventually | ||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
pub struct WithdrawalIntent { | ||
/// Amount of currency to be withdrawn. | ||
/// Amount to be withdrawn in sats. | ||
pub amt: u64, | ||
|
||
/// Destination public key for the withdrawal | ||
pub dest_pk: B512, | ||
pub dest_pk: B256, | ||
} | ||
|
||
sol! { | ||
#[allow(missing_docs)] | ||
event WithdrawalIntentEvent( | ||
/// Withdrawal amount in sats | ||
uint64 amount, | ||
bytes dest_pk, | ||
/// 32 bytes pubkey for withdrawal address in L1 | ||
bytes32 dest_pk, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
use revm_primitives::U256; | ||
|
||
pub const fn u256_from(val: u128) -> U256 { | ||
U256::from_limbs([(val & ((1 << 64) - 1)) as u64, (val >> 64) as u64, 0, 0]) | ||
} | ||
|
||
/// Number of wei per rollup BTC (1e18). | ||
pub const WEI_PER_BTC: u128 = 1_000_000_000_000_000_000u128; | ||
|
||
/// Number of wei per satoshi (1e10). | ||
const WEI_PER_SAT: U256 = u256_from(10_000_000_000u128); | ||
|
||
/// Converts wei to satoshis. | ||
/// Returns a tuple of (satoshis, remainder_in_wei). | ||
pub fn wei_to_sats(wei: U256) -> (U256, U256) { | ||
wei.div_rem(WEI_PER_SAT) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.