mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Set a fixed fee transferred to the caller for publication
Avoids the risk of the gas used by the contract exceeding the gas presumed to be used (causing an insolvency).
This commit is contained in:
@@ -18,7 +18,7 @@ use crate::{output::OutputId, machine::ClonableTransctionMachine};
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub(crate) enum Action {
|
||||
SetKey { chain_id: U256, nonce: u64, key: PublicKey },
|
||||
Batch { chain_id: U256, nonce: u64, coin: Coin, fee_per_gas: U256, outs: Vec<(Address, U256)> },
|
||||
Batch { chain_id: U256, nonce: u64, coin: Coin, fee: U256, outs: Vec<(Address, U256)> },
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
@@ -36,11 +36,11 @@ impl Action {
|
||||
Action::SetKey { chain_id, nonce, key } => {
|
||||
Router::update_serai_key_message(*chain_id, *nonce, key)
|
||||
}
|
||||
Action::Batch { chain_id, nonce, coin, fee_per_gas, outs } => Router::execute_message(
|
||||
Action::Batch { chain_id, nonce, coin, fee, outs } => Router::execute_message(
|
||||
*chain_id,
|
||||
*nonce,
|
||||
*coin,
|
||||
*fee_per_gas,
|
||||
*fee,
|
||||
OutInstructions::from(outs.as_ref()),
|
||||
),
|
||||
}
|
||||
@@ -51,10 +51,9 @@ impl Action {
|
||||
Self::SetKey { chain_id: _, nonce, key } => {
|
||||
Executed::SetKey { nonce: *nonce, key: key.eth_repr() }
|
||||
}
|
||||
Self::Batch { nonce, .. } => Executed::Batch {
|
||||
nonce: *nonce,
|
||||
message_hash: keccak256(self.message()),
|
||||
},
|
||||
Self::Batch { nonce, .. } => {
|
||||
Executed::Batch { nonce: *nonce, message_hash: keccak256(self.message()) }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -106,9 +105,9 @@ impl SignableTransaction for Action {
|
||||
1 => {
|
||||
let coin = Coin::read(reader)?;
|
||||
|
||||
let mut fee_per_gas = [0; 32];
|
||||
reader.read_exact(&mut fee_per_gas)?;
|
||||
let fee_per_gas = U256::from_le_bytes(fee_per_gas);
|
||||
let mut fee = [0; 32];
|
||||
reader.read_exact(&mut fee)?;
|
||||
let fee = U256::from_le_bytes(fee);
|
||||
|
||||
let mut outs_len = [0; 4];
|
||||
reader.read_exact(&mut outs_len)?;
|
||||
@@ -124,7 +123,7 @@ impl SignableTransaction for Action {
|
||||
|
||||
outs.push((address, amount));
|
||||
}
|
||||
Action::Batch { chain_id, nonce, coin, fee_per_gas, outs }
|
||||
Action::Batch { chain_id, nonce, coin, fee, outs }
|
||||
}
|
||||
_ => unreachable!(),
|
||||
})
|
||||
@@ -137,12 +136,12 @@ impl SignableTransaction for Action {
|
||||
writer.write_all(&nonce.to_le_bytes())?;
|
||||
writer.write_all(&key.eth_repr())
|
||||
}
|
||||
Self::Batch { chain_id, nonce, coin, fee_per_gas, outs } => {
|
||||
Self::Batch { chain_id, nonce, coin, fee, outs } => {
|
||||
writer.write_all(&[1])?;
|
||||
writer.write_all(&chain_id.as_le_bytes())?;
|
||||
writer.write_all(&nonce.to_le_bytes())?;
|
||||
coin.write(writer)?;
|
||||
writer.write_all(&fee_per_gas.as_le_bytes())?;
|
||||
writer.write_all(&fee.as_le_bytes())?;
|
||||
writer.write_all(&u32::try_from(outs.len()).unwrap().to_le_bytes())?;
|
||||
for (address, amount) in outs {
|
||||
borsh::BorshSerialize::serialize(address, writer)?;
|
||||
|
||||
@@ -89,8 +89,8 @@ impl<D: Db> signers::TransactionPublisher<Transaction> for TransactionPublisher<
|
||||
// Convert from an Action (an internal representation of a signable event) to a TxLegacy
|
||||
let tx = match tx.0 {
|
||||
Action::SetKey { chain_id: _, nonce: _, key } => router.update_serai_key(&key, &tx.1),
|
||||
Action::Batch { chain_id: _, nonce: _, coin, fee_per_gas, outs } => {
|
||||
router.execute(coin, fee_per_gas, OutInstructions::from(outs.as_ref()), &tx.1)
|
||||
Action::Batch { chain_id: _, nonce: _, coin, fee, outs } => {
|
||||
router.execute(coin, fee, OutInstructions::from(outs.as_ref()), &tx.1)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -111,16 +111,19 @@ impl<D: Db> smart_contract_scheduler::SmartContract<Rpc<D>> for SmartContract {
|
||||
|
||||
// Push each batch onto the result
|
||||
for outs in batches {
|
||||
let base_gas = BASE_GAS.div_ceil(u32::try_from(outs.len()).unwrap());
|
||||
let mut total_gas = 0;
|
||||
|
||||
let base_gas_per_payment = BASE_GAS.div_ceil(u32::try_from(outs.len()).unwrap());
|
||||
// Deduce the fee from each out
|
||||
for out in &mut outs {
|
||||
let payment_gas = base_gas +
|
||||
let payment_gas = base_gas_per_payment +
|
||||
match out.0 {
|
||||
Address::Address(_) => ADDRESS_PAYMENT_GAS,
|
||||
Address::Contract(deployment) => CONTRACT_PAYMENT_GAS + deployment.gas_limit(),
|
||||
};
|
||||
total_gas += payment_gas;
|
||||
|
||||
let payment_gas_cost = fee_per_gas * U256::try_from(payment_gas).unwrap();
|
||||
let payment_gas_cost = U256::try_from(payment_gas).unwrap() * fee_per_gas;
|
||||
out.1 -= payment_gas_cost;
|
||||
}
|
||||
|
||||
@@ -128,7 +131,7 @@ impl<D: Db> smart_contract_scheduler::SmartContract<Rpc<D>> for SmartContract {
|
||||
chain_id: self.chain_id,
|
||||
nonce,
|
||||
coin: coin_to_ethereum_coin(coin),
|
||||
fee_per_gas,
|
||||
fee: U256::try_from(total_gas).unwrap() * fee_per_gas,
|
||||
outs,
|
||||
});
|
||||
nonce += 1;
|
||||
|
||||
Reference in New Issue
Block a user