Skip to content

Commit

Permalink
Merge pull request #8 from khaeljy/khaeljy/issue7
Browse files Browse the repository at this point in the history
feat: Implement router contract for JediSwap
  • Loading branch information
khaeljy authored Sep 17, 2023
2 parents 54477bb + 1c8259d commit 3be206b
Show file tree
Hide file tree
Showing 9 changed files with 353 additions and 11 deletions.
5 changes: 4 additions & 1 deletion Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ version = "0.0.1"
[dependencies]
starknet = ">=2.2.0"

[[target.starknet-contract]]
[[target.starknet-contract]]

[scripts]
test = "scarb fmt && scarb cairo-test"
36 changes: 26 additions & 10 deletions src/account/account.cairo
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ use starknet::ContractAddress;
// STRUCTS / CONST
// *************************************************************************

/// @title Represents a call to a target contract
/// @param to The target contract address
/// @param selector The target function selector
/// @param calldata The serialized function parameters
/// Represents a call to a target contract
///
/// `to` - The target contract address
/// `selector` - The target function selector
/// `calldata` - The serialized function parameters
#[derive(Drop, Serde)]
struct Call {
to: ContractAddress,
Expand All @@ -30,29 +31,44 @@ const SRC6_TRAIT_ID: felt252 =
#[starknet::interface]
trait IAccount<TContractState> {
/// Initialize the contract
/// @param public_key The public key allowed to interact with the account.
///
/// # Arguments
///
/// * `public_key` - The public key allowed to interact with the account
fn initialize(ref self: TContractState, public_key: felt252);

/// Execute a transaction through the account
/// @param calls The list of calls to execute
///
/// # Arguments
///
/// * `calls` - The list of calls to execute
/// @return The list of each call's serialized return value
fn __execute__(ref self: TContractState, calls: Array<Call>) -> Array<Span<felt252>>;

/// Assert whether the transaction is valid to be executed
/// @param calls The list of calls to execute
///
/// # Arguments
///
/// * `calls` - The list of calls to validate
/// @return The string 'VALID' represented as felt when is valid
fn __validate__(ref self: TContractState, calls: Array<Call>) -> felt252;

/// Assert whether a given signature for a given hash is valid
/// @param hash The hash of the data
/// @param signature The signature to validate
///
/// # Arguments
///
/// * `hash` - The hash of the data
/// * `signature` - The signature to validate
/// @return The string 'VALID' represented as felt when the signature is valid
fn is_valid_signature(
ref self: TContractState, hash: felt252, signature: Array<felt252>
) -> felt252;

/// Query if a contract implements an interface
/// @param interface_id The interface identifier, as specified in SRC-5
///
/// # Arguments
///
/// * `interface_id` - The interface identifier, as specified in SRC-5
/// @return `true` if the contract implements `interface_id`, `false` otherwise
fn supports_interface(ref self: TContractState, interface_id: felt252) -> bool;

Expand Down
6 changes: 6 additions & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@ mod account {
mod error;
}

mod router {
mod router;
mod error;
mod jedi_swap_router;
}

#[cfg(test)]
mod tests;
5 changes: 5 additions & 0 deletions src/router/error.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod RouterError {
const ALREADY_INITIALIZED: felt252 = 'ALREADY_INITIALIZED';
const ONLY_OWNER: felt252 = 'ONLY_OWNER';
const ROUTER_ADDRESS_UNDEFINED: felt252 = 'ROUTER_ADDRESS_UNDEFINED';
}
106 changes: 106 additions & 0 deletions src/router/jedi_swap_router.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#[starknet::contract]
mod JediSwapRouter {
// *************************************************************************
// IMPORTS
// *************************************************************************

// Core lib imports.
use core::zeroable::Zeroable;
use starknet::{get_caller_address, ContractAddress};

// Local imports.
use swappy::router::router::IRouter;
use swappy::router::error::RouterError;

// *************************************************************************
// STORAGE
// *************************************************************************
#[storage]
struct Storage {
owner: ContractAddress,
router_address: ContractAddress
}

// *************************************************************************
// CONSTRUCTOR
// *************************************************************************

/// Constructor of the contract.
/// # Arguments
/// * `owner` - The owner address.
#[constructor]
fn constructor(ref self: ContractState, owner: ContractAddress) {
self.initialize(owner);
}

// *************************************************************************
// EXTERNAL FUNCTIONS
// *************************************************************************
#[external(v0)]
impl JediSwapRouterImpl of IRouter<ContractState> {
fn initialize(ref self: ContractState, owner: ContractAddress) {
// Make sure the contract is not already initialized.
assert(self.owner.read().is_zero(), RouterError::ALREADY_INITIALIZED);

self.owner.write(owner);
}

fn get_owner(ref self: ContractState) -> ContractAddress {
self.owner.read()
}

fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) {
self.only_owner();
self.owner.write(new_owner);
}

fn get_router_address(ref self: ContractState) -> ContractAddress {
self.router_address.read()
}

fn set_router_address(ref self: ContractState, router_address: ContractAddress) {
self.only_owner();
self.router_address.write(router_address)
}

fn swap_exact_tokens_for_tokens(
ref self: ContractState,
amount_in: u256,
amount_out_min: u256,
path: Span<ContractAddress>,
to: ContractAddress,
deadline: u32
) {
self
.swap_exact_tokens_for_tokens_internal(
amount_in, amount_out_min, path, to, deadline
);
}
}

#[generate_trait]
impl JediSwapRouterInternalImpl of JediSwapRouterInternal {
fn only_owner(self: @ContractState) {
let sender = get_caller_address();
let owner = self.owner.read();

assert(sender == owner, RouterError::ONLY_OWNER);
}

fn swap_exact_tokens_for_tokens_internal(
ref self: ContractState,
amount_in: u256,
amount_out_min: u256,
path: Span<ContractAddress>,
to: ContractAddress,
deadline: u32
) {
let router_address = self.router_address.read();
assert(router_address.is_non_zero(), RouterError::ROUTER_ADDRESS_UNDEFINED);

// TODO : Call router address swap_exact_tokens_for_tokens
// Until JediSwap is updated to Cairo 1, panic with 'NOT_IMPLEMENTED'
panic_with_felt252('NOT_IMPLEMENTED');
}
}
}
59 changes: 59 additions & 0 deletions src/router/router.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// *************************************************************************
// IMPORTS
// *************************************************************************
use starknet::ContractAddress;

// *************************************************************************
// STRUCTS / CONST
// *************************************************************************

// *************************************************************************
// Interfaces of the `Router` contract.
// *************************************************************************
#[starknet::interface]
trait IRouter<TContractState> {
/// Initialize the contract
///
/// # Arguments
///
/// * `owner` - The contract owner address
fn initialize(ref self: TContractState, owner: ContractAddress);

/// Get the owner address
fn get_owner(ref self: TContractState) -> ContractAddress;

/// Transfer the ownership
///
/// # Arguments
///
/// * `new_owner` - The new owner address
fn transfer_ownership(ref self: TContractState, new_owner: ContractAddress);

/// Get the router address
fn get_router_address(ref self: TContractState) -> ContractAddress;

/// Set the router address
///
/// # Arguments
///
/// * `router_address` - The router address
fn set_router_address(ref self: TContractState, router_address: ContractAddress);

/// Swap exact tokens for tokens
///
/// # Arguments
///
/// * `amount_in` - Amount of token to swap
/// * `amount_out_min` - Min out token amount
/// * `path` - Route path
/// * `to` - The recipient of swap
/// * `deadline` - The deadline of the swap transaction
fn swap_exact_tokens_for_tokens(
ref self: TContractState,
amount_in: u256,
amount_out_min: u256,
path: Span<ContractAddress>,
to: ContractAddress,
deadline: u32
);
}
6 changes: 6 additions & 0 deletions src/tests.cairo
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
#[cfg(test)]
mod test_account;

#[cfg(test)]
mod router {
#[cfg(test)]
mod test_jedi_swap_router;
}
Loading

0 comments on commit 3be206b

Please sign in to comment.