Skip to content

Commit

Permalink
liquidy retreival: initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
chachaleo committed Sep 16, 2024
1 parent 1799f4e commit bfa0270
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 4 deletions.
3 changes: 3 additions & 0 deletions contracts/src/contracts/ramps/revolut.cairo
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
pub mod interface;
pub mod revolut;

#[cfg(test)]
pub mod revolut_test;
4 changes: 2 additions & 2 deletions contracts/src/contracts/ramps/revolut/interface.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use starknet::ContractAddress;
use zkramp::components::registry::interface::OffchainId;

#[derive(Drop, Serde)]
struct Proof {
pub struct Proof {
foo: felt252
}

#[starknet::interface]
trait zkRampABI<TState> {
pub trait IzkRampABI<TState> {
// check if a contract address is linked to an offchain ID
fn is_registered(self: @TState, contract_address: ContractAddress, offchain_id: OffchainId) -> bool;

Expand Down
103 changes: 101 additions & 2 deletions contracts/src/contracts/ramps/revolut/revolut.cairo
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
#[starknet::contract]
pub mod RevolutRamp {
use core::hash::{HashStateTrait, HashStateExTrait};
use core::num::traits::Zero;
use core::poseidon::PoseidonTrait;
use core::starknet::storage::{StoragePointerReadAccess};
use openzeppelin::access::ownable::OwnableComponent;
use starknet::ContractAddress;
use starknet::storage::Map;
use starknet::{ContractAddress, get_caller_address};
use zkramp::components::escrow::interface::{IEscrowDispatcher, IEscrowDispatcherTrait};
use zkramp::components::registry::interface::OffchainId;
use zkramp::contracts::ramps::revolut::interface;


component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);

Expand All @@ -18,6 +27,21 @@ pub mod RevolutRamp {
struct Storage {
#[substorage(v0)]
ownable: OwnableComponent::Storage,
// liquidity_id -> (amount, token)
liquidity: Map::<felt252, (u256, ContractAddress)>,
// liquidity_id -> caller
locked_liquidity: Map::<felt252, ContractAddress>,
escrow: ContractAddress
}

//
// Errors
//

pub mod Errors {
pub const WRONG_CALLER_ADDRESS: felt252 = 'Wrong caller address';
pub const EMPTY_LIQUIDITY_RETREIVAL: felt252 = 'Empty liquidity retreival';
pub const LOCKED_LIQUIDITY_RETREIVAL: felt252 = 'Locked liquidity retreival';
}

//
Expand All @@ -29,15 +53,90 @@ pub mod RevolutRamp {
enum Event {
#[flat]
OwnableEvent: OwnableComponent::Event,
LiquidityLocked: LiquidityLocked,
}

// Emitted when liquidity is locked
#[derive(Drop, starknet::Event)]
pub struct LiquidityLocked {
#[key]
pub liquidity_id: felt252,
#[key]
pub caller: ContractAddress,
}

// Emitted when liquidity is locked
#[derive(Drop, starknet::Event)]
pub struct LiquidityRetreived {
#[key]
pub liquidity_id: felt252,
#[key]
pub caller: ContractAddress,
}

//
// Constructor
//

#[constructor]
fn constructor(ref self: ContractState, owner: ContractAddress,) {
fn constructor(ref self: ContractState, owner: ContractAddress, escrow: ContractAddress) {
// initialize owner
self.ownable.initializer(:owner);
// initialize escrow
self.escrow.write(escrow);
}

//
// ZK Ramp impl
//

#[abi(embed_v0)]
pub impl RevolutImpl of interface::IzkRampABI<ContractState> {
fn is_registered(self: @ContractState, contract_address: ContractAddress, offchain_id: OffchainId) -> bool {
false
} // TODO
fn register(ref self: ContractState, offchain_id: OffchainId) {} // TODO
fn add_liquidity(ref self: ContractState, amount: u256, offchain_id: OffchainId) -> felt252 {
0
} // TODO

fn initiate_liquidity_retrieval(ref self: ContractState, liquidity_id: felt252) {
// asserts liquidity is non null
assert(self.liquidity.read(liquidity_id) != (0, Zero::zero()), Errors::EMPTY_LIQUIDITY_RETREIVAL);
//TODO: retreive offchain id
let offchain_id = 0;
let caller = get_caller_address();
// asserts caller is the liquidity owner
assert(
liquidity_id == PoseidonTrait::new().update_with(caller).update_with(offchain_id).finalize(),
Errors::WRONG_CALLER_ADDRESS
);

// asserts liquidity is not locked
assert(self.locked_liquidity.read(liquidity_id).is_non_zero(), Errors::LOCKED_LIQUIDITY_RETREIVAL);

// locks liquidity
self.locked_liquidity.write(liquidity_id, caller);

// emits LiquidityLocked event
self.emit(LiquidityLocked { liquidity_id, caller });
}

fn retrieve_liquidity(ref self: ContractState, liquidity_id: felt252) {
let caller = get_caller_address();

self.initiate_liquidity_retrieval(liquidity_id);

let (amount, token) = self.liquidity.read(liquidity_id);
let mut escrow = IEscrowDispatcher { contract_address: self.escrow.read() };

// calls the escrow to unlock the funds
escrow.unlock_to(caller, token, caller, amount);
// emits LiquidityRetreived event
self.emit(LiquidityLocked { liquidity_id, caller });
}

fn initiate_liquidity_withdrawal(ref self: ContractState, liquidity_id: felt252, amount: u256) {} // TODO
fn withdraw_liquidity(ref self: ContractState, liquidity_id: felt252, proof: interface::Proof) {} // TODO
}
}
41 changes: 41 additions & 0 deletions contracts/src/contracts/ramps/revolut/revolut_test.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use core::hash::{HashStateTrait, HashStateExTrait};
use core::poseidon::PoseidonTrait;

use core::starknet::{ContractAddress, contract_address_const, get_caller_address};

use snforge_std::{declare, ContractClassTrait, start_cheat_caller_address, test_address};
use zkramp::contracts::ramps::revolut::interface::{IzkRampABIDispatcher, IzkRampABIDispatcherTrait};
use zkramp::contracts::ramps::revolut::revolut::RevolutRamp::RevolutImpl;

use zkramp::tests::constants;

fn deploy_revolut_ramp() -> (IzkRampABIDispatcher, ContractAddress) {
let contract = declare("RevolutRamp").unwrap();
let owner: ContractAddress = contract_address_const::<'owner'>();
let escrow: ContractAddress = contract_address_const::<'escrow'>();

let mut constructor_calldata = array![owner.into(), escrow.into()];

let (contract_address, _) = contract.deploy(@constructor_calldata).unwrap();

let dispatcher = IzkRampABIDispatcher { contract_address };

(dispatcher, contract_address)
}

#[test]
#[should_panic(expected: 'Empty liquidity retreival')]
fn test_retreive_uninitialized_liquidity_should_panic() {
let test_address: ContractAddress = test_address();

start_cheat_caller_address(test_address, constants::CALLER());

let (revolut_ramp, _) = deploy_revolut_ramp();

let liquidity_id = PoseidonTrait::new()
.update_with(get_caller_address())
.update_with(constants::REVOLUT_ID())
.finalize();

revolut_ramp.retrieve_liquidity(liquidity_id);
}

0 comments on commit bfa0270

Please sign in to comment.