mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-28 06:29:38 +00:00
93 lines
3 KiB
Rust
93 lines
3 KiB
Rust
|
use std::{sync::Arc, time::Duration, fs::File, collections::HashMap};
|
||
|
|
||
|
use rand_core::OsRng;
|
||
|
|
||
|
use group::ff::PrimeField;
|
||
|
use k256::{Scalar, ProjectivePoint};
|
||
|
use frost::{curve::Secp256k1, Participant, ThresholdKeys, tests::key_gen as frost_key_gen};
|
||
|
|
||
|
use ethers_core::{
|
||
|
types::{H160, Signature as EthersSignature},
|
||
|
abi::Abi,
|
||
|
};
|
||
|
use ethers_contract::ContractFactory;
|
||
|
use ethers_providers::{Middleware, Provider, Http};
|
||
|
|
||
|
use crate::crypto::PublicKey;
|
||
|
|
||
|
mod crypto;
|
||
|
mod schnorr;
|
||
|
mod router;
|
||
|
|
||
|
pub fn key_gen() -> (HashMap<Participant, ThresholdKeys<Secp256k1>>, PublicKey) {
|
||
|
let mut keys = frost_key_gen::<_, Secp256k1>(&mut OsRng);
|
||
|
let mut group_key = keys[&Participant::new(1).unwrap()].group_key();
|
||
|
|
||
|
let mut offset = Scalar::ZERO;
|
||
|
while PublicKey::new(group_key).is_none() {
|
||
|
offset += Scalar::ONE;
|
||
|
group_key += ProjectivePoint::GENERATOR;
|
||
|
}
|
||
|
for keys in keys.values_mut() {
|
||
|
*keys = keys.offset(offset);
|
||
|
}
|
||
|
let public_key = PublicKey::new(group_key).unwrap();
|
||
|
|
||
|
(keys, public_key)
|
||
|
}
|
||
|
|
||
|
// TODO: Replace with a contract deployment from an unknown account, so the environment solely has
|
||
|
// to fund the deployer, not create/pass a wallet
|
||
|
// TODO: Deterministic deployments across chains
|
||
|
pub async fn deploy_contract(
|
||
|
chain_id: u32,
|
||
|
client: Arc<Provider<Http>>,
|
||
|
wallet: &k256::ecdsa::SigningKey,
|
||
|
name: &str,
|
||
|
) -> eyre::Result<H160> {
|
||
|
let abi: Abi =
|
||
|
serde_json::from_reader(File::open(format!("./artifacts/{name}.abi")).unwrap()).unwrap();
|
||
|
|
||
|
let hex_bin_buf = std::fs::read_to_string(format!("./artifacts/{name}.bin")).unwrap();
|
||
|
let hex_bin =
|
||
|
if let Some(stripped) = hex_bin_buf.strip_prefix("0x") { stripped } else { &hex_bin_buf };
|
||
|
let bin = hex::decode(hex_bin).unwrap();
|
||
|
let factory = ContractFactory::new(abi, bin.into(), client.clone());
|
||
|
|
||
|
let mut deployment_tx = factory.deploy(())?.tx;
|
||
|
deployment_tx.set_chain_id(chain_id);
|
||
|
deployment_tx.set_gas(1_000_000);
|
||
|
let (max_fee_per_gas, max_priority_fee_per_gas) = client.estimate_eip1559_fees(None).await?;
|
||
|
deployment_tx.as_eip1559_mut().unwrap().max_fee_per_gas = Some(max_fee_per_gas);
|
||
|
deployment_tx.as_eip1559_mut().unwrap().max_priority_fee_per_gas = Some(max_priority_fee_per_gas);
|
||
|
|
||
|
let sig_hash = deployment_tx.sighash();
|
||
|
let (sig, rid) = wallet.sign_prehash_recoverable(sig_hash.as_ref()).unwrap();
|
||
|
|
||
|
// EIP-155 v
|
||
|
let mut v = u64::from(rid.to_byte());
|
||
|
assert!((v == 0) || (v == 1));
|
||
|
v += u64::from((chain_id * 2) + 35);
|
||
|
|
||
|
let r = sig.r().to_repr();
|
||
|
let r_ref: &[u8] = r.as_ref();
|
||
|
let s = sig.s().to_repr();
|
||
|
let s_ref: &[u8] = s.as_ref();
|
||
|
let deployment_tx =
|
||
|
deployment_tx.rlp_signed(&EthersSignature { r: r_ref.into(), s: s_ref.into(), v });
|
||
|
|
||
|
let pending_tx = client.send_raw_transaction(deployment_tx).await?;
|
||
|
|
||
|
let mut receipt;
|
||
|
while {
|
||
|
receipt = client.get_transaction_receipt(pending_tx.tx_hash()).await?;
|
||
|
receipt.is_none()
|
||
|
} {
|
||
|
tokio::time::sleep(Duration::from_secs(6)).await;
|
||
|
}
|
||
|
let receipt = receipt.unwrap();
|
||
|
assert!(receipt.status == Some(1.into()));
|
||
|
|
||
|
Ok(receipt.contract_address.unwrap())
|
||
|
}
|