Skip to content

Instantly share code, notes, and snippets.

@mfw78
Created June 23, 2024 16:44
Show Gist options
  • Save mfw78/98d1e8839de72d9f1889348a5ce43dbe to your computer and use it in GitHub Desktop.
Save mfw78/98d1e8839de72d9f1889348a5ce43dbe to your computer and use it in GitHub Desktop.
Eth Flow Refunder
use alloy::{
network::{EthereumWallet, TransactionBuilder},
primitives::bytes::Buf,
providers::{Provider, ProviderBuilder},
rpc::types::TransactionRequest,
signers::local::PrivateKeySigner,
sol,
sol_types::{SolCall, SolEvent},
};
use CoWSwapOnchainOrders::{invalidateOrderCall, EthFlowOrderData};
#[tokio::main]
async fn main() -> eyre::Result<()> {
let rpc_url = match std::env::var("RPC_URL") {
Ok(url) => match url.parse() {
Ok(url) => url,
Err(_) => {
eprintln!("Invalid URL: {}", url);
std::process::exit(1);
}
},
Err(_) => {
eprintln!("Environment variable `RPC_URL` is not set");
eprintln!("Usage: RPC_URL=<URL> indexer");
std::process::exit(1);
}
};
let signer: PrivateKeySigner = std::env::var("PRIVATE_KEY")
.expect("Must supply PRIVATE_KEY via env variable")
.parse()
.expect("Failed to parse private key");
let wallet = EthereumWallet::from(signer);
let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(wallet)
.on_http(rpc_url);
let receipts = provider
.get_transaction_receipt(
std::env::var("TX_HASH")
.expect("Must specify TX_HASH via env variable")
.parse()
.expect("Invalid TX_HASH specified"),
)
.await
.unwrap()
.unwrap();
// Get the first (and only) log from the transaction
let log = receipts.inner.logs().iter().next().unwrap();
let event = CoWSwapOnchainOrders::OrderPlacement::decode_log_data(&log.data(), true)?;
// Reassemble the on-chain order data
let order = EthFlowOrderData {
buyToken: event.order.buyToken,
receiver: event.order.receiver,
sellAmount: event.order.sellAmount,
buyAmount: event.order.buyAmount,
appData: event.order.appData,
feeAmount: event.order.feeAmount,
validTo: event.order.validTo,
partiallyFillable: event.order.partiallyFillable,
// quoteId is tightly packed in `event.data`
quoteId: event.data.slice(..8).get_i64(),
};
// Build the transaction to invalidate the order
let tx = TransactionRequest::default()
.with_to(log.address())
.with_call(&invalidateOrderCall::new((order,)));
println!("{:?}", tx);
let tx_hash = provider.send_transaction(tx).await?.watch().await?;
println!("Sent transaction: {}", tx_hash);
Ok(())
}
sol! {
#[allow(missing_docs)]
#[derive(Debug)]
contract CoWSwapOnchainOrders {
enum OnchainSigningScheme {
Eip1271,
PreSign
}
struct OnchainSignature {
/// @dev The signing scheme used by the signature data.
OnchainSigningScheme scheme;
/// @dev The data used as an order signature.
bytes data;
}
event OrderPlacement(
address indexed sender,
Data order,
OnchainSignature signature,
bytes data
);
struct Data {
address sellToken;
address buyToken;
address receiver;
uint256 sellAmount;
uint256 buyAmount;
uint32 validTo;
bytes32 appData;
uint256 feeAmount;
bytes32 kind;
bool partiallyFillable;
bytes32 sellTokenBalance;
bytes32 buyTokenBalance;
}
struct EthFlowOrderData {
address buyToken;
address receiver;
uint256 sellAmount;
uint256 buyAmount;
bytes32 appData;
uint256 feeAmount;
uint32 validTo;
bool partiallyFillable;
int64 quoteId;
}
function invalidateOrder(EthFlowOrderData calldata order) public {
_invalidateOrder(order, true);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment