Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
scarb 2.8.2
starknet-foundry 0.31.0
starknet-foundry









48 changes: 47 additions & 1 deletion src/escrow/escrow_contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod EscrowContract {
use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess, StoragePathEntry};
use starknet::get_block_timestamp;
use core::starknet::{get_caller_address, get_contract_address};
use crate::escrow::{types::Escrow, errors::Errors};
use crate::escrow::{types::Escrow, types::Milestone, errors::Errors};
use crate::interface::iescrow::{IEscrow};
use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait};

Expand All @@ -28,8 +28,12 @@ mod EscrowContract {
deposit_time: Map::<u64, u64>,
// Track the funded escrows. Start as false and is setted to true when successfully funds.
escrow_funded: Map::<u64, bool>,
milestone_count: u64,
// mapping to track milestones
milestones: Map::<u64, Milestone>,
}


#[event]
#[derive(Drop, starknet::Event)]
pub enum Event {
Expand Down Expand Up @@ -282,6 +286,48 @@ mod EscrowContract {
);
}

// add milestone for escrows to help in tracking
fn add_milestone(
ref self: ContractState, description: ByteArray, amount: u256, dueDate: u256,
) {
assert(amount > 0, 'amount too low');
let milestone_id: u64 = self.milestone_count.read() + 1;

let milestone: Milestone = Milestone {
id: milestone_id,
description: description,
amount: amount,
dueDate: dueDate,
isCompleted: false,
isApprovedDepositor: false,
isApprovedBeneficiary: false,
isPaid: false
};

self.milestones.write(milestone_id, milestone)
}

fn request_milestone_payment(
ref self: ContractState, id: u64, token_address: ContractAddress
) -> bool {
let mut milestone: Milestone = self.milestones.read(id);

assert(!milestone.isPaid, 'Milestone has been paid');
assert(milestone.isApprovedBeneficiary, 'Milestone must be approved');
assert(milestone.isApprovedDepositor, 'Milestone must be approved');
assert(milestone.isCompleted, 'Milestone must be completed');

let milestone_amount = milestone.amount;

let token = IERC20Dispatcher { contract_address: token_address };
let caller_address = get_caller_address();
milestone.isPaid = true;

token.transfer(caller_address, milestone_amount);

return true;
}

fn fund_escrow(
ref self: ContractState, escrow_id: u64, amount: u256, token_address: ContractAddress,
) {
Expand Down
19 changes: 19 additions & 0 deletions src/escrow/escrow_factory.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub use starknet::{
ContractAddress, class_hash::ClassHash, syscalls::deploy_syscall, SyscallResultTrait,
};
use escrownet_contract::interface::iescrow::{IEscrowDispatcher, IEscrowDispatcherTrait};

#[starknet::interface]
pub trait IEscrowFactory<TContractState> {
Expand All @@ -11,13 +12,18 @@ pub trait IEscrowFactory<TContractState> {
depositor: ContractAddress,
arbiter: ContractAddress,
salt: felt252,
milestone_description: ByteArray,
milestone_amount: u256,
milestone_dueDate: u256,
) -> ContractAddress;

fn get_escrow_contracts(self: @TContractState) -> Array<ContractAddress>;
}

#[starknet::component]
pub mod EscrowFactory {
use super::IEscrowDispatcherTrait;
use super::IEscrowDispatcher;
use super::IEscrowFactory;
use starknet::{
ContractAddress, class_hash::ClassHash, syscalls::deploy_syscall, SyscallResultTrait,
Expand All @@ -44,6 +50,9 @@ pub mod EscrowFactory {
depositor: ContractAddress,
arbiter: ContractAddress,
salt: felt252,
milestone_description: ByteArray,
milestone_amount: u256,
milestone_dueDate: u256,
) -> ContractAddress {
let escrow_id = self.escrow_count.read() + 1;

Expand All @@ -60,6 +69,16 @@ pub mod EscrowFactory {
self.escrow_addresses.write(escrow_id, escrow_address);
self.escrow_count.write(escrow_id);

// Initialize milestone for every deployed escrow
let escrow_contract = IEscrowDispatcher { contract_address: escrow_address };

escrow_contract
.add_milestone(
description: milestone_description,
amount: milestone_amount,
dueDate: milestone_dueDate
);

escrow_address
}

Expand Down
12 changes: 12 additions & 0 deletions src/escrow/types.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ pub struct Escrow {
pub balance: u256,
}

#[derive(Drop, Serde, starknet::Store)]
pub struct Milestone {
pub id: u64,
pub description: ByteArray,
pub amount: u256,
pub dueDate: u256,
pub isCompleted: bool,
pub isApprovedDepositor: bool,
pub isApprovedBeneficiary: bool,
pub isPaid: bool,
}

#[starknet::interface]
pub trait IEscrow<TContractState> {
fn get_escrow(self: @TContractState, escrow_id: u256) -> Escrow;
Expand Down
8 changes: 7 additions & 1 deletion src/interface/iescrow.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use starknet::ContractAddress;
use crate::escrow::types::Escrow;
use crate::escrow::types::{Escrow, Milestone};

#[starknet::interface]
pub trait IEscrow<TContractState> {
Expand All @@ -10,6 +10,12 @@ pub trait IEscrow<TContractState> {
provider_address: ContractAddress,
amount: u256,
);
fn add_milestone(
ref self: TContractState, description: ByteArray, amount: u256, dueDate: u256,
);
fn request_milestone_payment(
ref self: TContractState, id: u64, token_address: ContractAddress
) -> bool;
fn get_escrow_details(ref self: TContractState, escrow_id: u64) -> Escrow;
fn get_depositor(self: @TContractState) -> ContractAddress;
fn get_beneficiary(self: @TContractState) -> ContractAddress;
Expand Down