feat: Add permit2 draft

This commit is contained in:
Diana Carvalho
2025-01-13 17:57:54 +00:00
parent fa462ee9f3
commit 5d79da44f3
4 changed files with 62 additions and 2 deletions

View File

@@ -1,5 +1,6 @@
mod approvals_manager;
mod models;
mod permit2;
mod router_encoder;
mod strategy_encoder;
mod swap_encoder;

View File

@@ -18,7 +18,7 @@ pub struct Order {
/// True if the order is an exact output order.
pub exact_out: bool,
/// The token being sold (exact in) or bought (exact out).
given_token: Bytes,
pub given_token: Bytes,
/// Amount of the given token.
pub given_amount: BigUint,
/// The token being bought (exact in) or sold (exact out).
@@ -26,7 +26,7 @@ pub struct Order {
/// Amount of the checked token.
checked_amount: BigUint,
/// Address of the sender.
sender: Bytes,
pub sender: Bytes,
/// Address of the receiver.
pub receiver: Bytes,
/// List of swaps to fulfill the order.

44
src/encoding/permit2.rs Normal file
View File

@@ -0,0 +1,44 @@
use alloy_primitives::{Address, U256};
use num_bigint::BigUint;
use std::str::FromStr;
use tycho_core::Bytes;
pub struct PermitRequest {
pub token: Bytes,
pub amount: BigUint,
pub spender: Bytes,
pub router_address: Address,
}
pub struct Permit2 {
pub address: Address,
}
impl Permit2 {
pub fn new() -> Self {
Self {
address: Address::from_str("0x000000000022D473030F116dDEE9F6B43aC78BA3")
.expect("Permit2 address not valid"),
}
}
pub fn encode_permit(&self, details: Vec<PermitRequest>) -> Vec<u8> {
// calls get_allowance_data to get nonce
// checks if we are not permitted already
// puts data into a permitSingle struct if there is only 1 PermitDetails, if there are several, use PermitBatch
// adds the nonce and the expiration (uniswap recommends 30 days for expiration)
// signs data
// returns encoded data
todo!()
}
fn get_allowance_data(
&self,
user: Address,
router_address: Address,
token: Address,
) -> (U256, u64, U256) {
// get allowance data (if it exists) and the nonce
// returns permitAmount, expiration, nonce
todo!()
}
}

View File

@@ -1,4 +1,5 @@
use crate::encoding::models::{Order, Solution};
use crate::encoding::permit2::{Permit2, PermitRequest};
use crate::encoding::strategy_encoder::{
SequentialExactInStrategyEncoder, SingleSwapStrategyEncoder, SlipSwapStrategyEncoder,
StrategyEncoder,
@@ -24,6 +25,7 @@ impl RouterEncoder {
}
pub fn encode_router_calldata(&self, solution: Solution) -> Result<Vec<u8>, Error> {
let permit_calldata = self.handle_approvals(&solution)?; // TODO: where should we append this?
let mut calldata_list: Vec<Vec<u8>> = Vec::new();
let encode_for_batch_execute = solution.orders.len() > 1;
for order in solution.orders {
@@ -47,6 +49,19 @@ impl RouterEncoder {
}
}
fn handle_approvals(&self, solution: &Solution) -> Result<Vec<u8>, Error> {
let mut permits = Vec::new();
for order in solution.orders.iter() {
permits.push(PermitRequest {
token: order.given_token.clone(),
spender: order.sender.clone(),
amount: order.given_amount.clone(),
router_address: solution.router_address.unwrap_or(self.router_address),
});
}
Ok(Permit2::new().encode_permit(permits))
}
fn get_strategy(&self, order: &Order) -> &dyn StrategyEncoder {
if order.swaps.len() == 1 {
&SingleSwapStrategyEncoder {}