Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Li/dev/fmt #20

Merged
merged 7 commits into from
Dec 5, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/contracts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ jobs:

- name: Run tests and generate report
run: snforge test
working-directory: packages/onchain
working-directory: packages/onchain
29 changes: 16 additions & 13 deletions packages/onchain/src/orderbook/interface.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use core::starknet::contract_address::ContractAddress;
#[derive(Default, Drop, PartialEq, starknet::Store)]
pub enum Status {
Open,
Locked,
Canceled,
Locked,
Canceled,
Closed,
#[default]
Undefined,
Expand All @@ -13,12 +13,12 @@ pub enum Status {
#[starknet::interface]
pub trait IOrderbook<TContractState> {
fn request_inscription(
ref self: TContractState,
ref self: TContractState,
inscription_data: ByteArray,
receiving_address: ByteArray,
satoshi: felt252,
currency_fee: felt252,
submitter_fee: u256
satoshi: felt252,
currency_fee: felt252,
submitter_fee: u256,
) -> u32;
fn cancel_inscription(ref self: TContractState, inscription_id: u32, currency_fee: felt252);
fn lock_inscription(ref self: TContractState, inscription_id: u32, tx_hash: ByteArray);
Expand All @@ -31,12 +31,12 @@ pub trait IOrderbook<TContractState> {
#[starknet::interface]
pub trait OrderbookABI<TContractState> {
fn request_inscription(
ref self: TContractState,
ref self: TContractState,
inscription_data: ByteArray,
receiving_address: ByteArray,
satoshi: felt252,
currency_fee: felt252,
submitter_fee: u256
satoshi: felt252,
currency_fee: felt252,
submitter_fee: u256,
) -> u32;
fn cancel_inscription(ref self: TContractState, inscription_id: u32, currency_fee: felt252);
fn lock_inscription(ref self: TContractState, inscription_id: u32, tx_hash: ByteArray);
Expand All @@ -49,11 +49,14 @@ pub trait OrderbookABI<TContractState> {
fn balance_of(self: @TContractState, account: ContractAddress) -> felt252;
fn transfer(ref self: TContractState, recipient: ContractAddress, amount: felt252);
fn transfer_from(
ref self: TContractState, sender: ContractAddress, recipient: ContractAddress, amount: felt252
ref self: TContractState,
sender: ContractAddress,
recipient: ContractAddress,
amount: felt252,
);
fn approve(ref self: TContractState, spender: ContractAddress, amount: felt252);
fn increase_allowance(ref self: TContractState, spender: ContractAddress, added_value: felt252);
fn decrease_allowance(
ref self: TContractState, spender: ContractAddress, subtracted_value: felt252
ref self: TContractState, spender: ContractAddress, subtracted_value: felt252,
);
}
}
115 changes: 46 additions & 69 deletions packages/onchain/src/orderbook/orderbook.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ mod Orderbook {
use core::byte_array::ByteArray;
use onchain::orderbook::interface::Status;
use openzeppelin_token::erc20::{ERC20ABIDispatcher, ERC20ABIDispatcherTrait};
use starknet::storage::{
Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePathEntry,
StoragePointerReadAccess, StoragePointerWriteAccess,
use starknet::storage::{
Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePathEntry,
StoragePointerReadAccess, StoragePointerWriteAccess,
};
use starknet::{ContractAddress, get_caller_address, get_contract_address, get_block_number};

#[storage]
struct Storage {
// ID of the next inscription.
new_inscription_id: u32,
// A map from the inscription ID to a tuple with the inscribed
// A map from the inscription ID to a tuple with the inscribed
// data and submitter fee.
inscriptions: Map<u32, (ByteArray, u256)>,
// A map from the inscription ID to status. Possible values:
Expand All @@ -26,22 +26,20 @@ mod Orderbook {
// Locks on inscriptions. Maps the inscription ID to a tuple of
// submitter address, precomputed transaction hash, and block number.
inscription_locks: Map<u32, (ContractAddress, ByteArray, u64)>,
// STRK fee token.
// STRK fee token.
strk_token: ERC20ABIDispatcher,
}

#[constructor]
fn constructor(
ref self: ContractState, strk_token: ContractAddress
) {
fn constructor(ref self: ContractState, strk_token: ContractAddress) {
// initialize contract
self.initializer(:strk_token);
}

#[abi(embed_v0)]
impl OrderbookImpl of super::IOrderbook<ContractState> {
/// Called by a user.
/// Inputs:
/// Called by a user.
/// Inputs:
/// - `inscription_data: ByteArray`, the data to be inscribed on Bitcoin.
/// - `receiving_address: ByteArray`, the taproot address that will own the inscription.
/// - `satoshi: felt252`, the Sat where the user wants to inscribe data.
Expand All @@ -50,27 +48,27 @@ mod Orderbook {
/// Returns:
/// - `id: felt252`, the ID of the created inscription.
fn request_inscription(
ref self: ContractState,
ref self: ContractState,
inscription_data: ByteArray,
receiving_address: ByteArray,
satoshi: felt252,
currency_fee: felt252,
satoshi: felt252,
currency_fee: felt252,
submitter_fee: u256,
) -> u32 {
assert(
self.is_valid_bitcoin_address(receiving_address) == true,
'Not a valid bitcoin address'
);
assert(
currency_fee == 'STRK'.into(),
'The currency is not supported'
self.is_valid_bitcoin_address(receiving_address) == true,
'Not a valid bitcoin address',
);
assert(currency_fee == 'STRK'.into(), 'The currency is not supported');
let caller = get_caller_address();
let escrow_address = get_contract_address();
if (currency_fee == 'STRK'.into()) {
let strk_token = self.strk_token.read();
// TODO: change the transfer to the escrow contract once it's implemented.
strk_token.transfer_from(sender: caller, recipient: escrow_address, amount: submitter_fee);
strk_token
.transfer_from(
sender: caller, recipient: escrow_address, amount: submitter_fee,
);
}
let id = self.new_inscription_id.read();
self.inscriptions.write(id, (inscription_data, submitter_fee));
Expand All @@ -79,7 +77,7 @@ mod Orderbook {
}

/// Helper function that checks the format of the taproot address.
/// Inputs:
/// Inputs:
/// - `receiving_address: ByteArray`, the ID of the inscription.
/// Returns:
/// - `bool`
Expand All @@ -88,37 +86,25 @@ mod Orderbook {
true
}

/// Inputs:
/// Inputs:
/// - `inscription_id: felt252`, the ID of the inscription.
/// Returns:
/// - `(ByteArray, felt252)`, the tuple with the inscribed data and the fee.
fn query_inscription(self: @ContractState, inscription_id: u32) -> (ByteArray, u256) {
self.inscriptions.read(inscription_id)
}

/// Called by a user.
/// Inputs:
/// - `inscription_id: felt252`, the ID of the inscription the user wants to
/// cancel.
/// Called by a user.
/// Inputs:
/// - `inscription_id: felt252`, the ID of the inscription the user wants to
/// cancel.
/// - `currency_fee: felt252`, the token that the user paid the submitter fee in.
fn cancel_inscription(ref self: ContractState, inscription_id: u32, currency_fee: felt252) {
let status = self.inscription_statuses.read(inscription_id);
assert(
status != Status::Undefined,
'Inscription does not exist'
);
assert(
status != Status::Locked,
'The inscription is locked'
);
assert(
status != Status::Canceled,
'The inscription is canceled'
);
assert(
status != Status::Closed,
'The inscription has been closed'
);
assert(status != Status::Undefined, 'Inscription does not exist');
assert(status != Status::Locked, 'The inscription is locked');
assert(status != Status::Canceled, 'The inscription is canceled');
assert(status != Status::Closed, 'The inscription has been closed');

let caller = get_caller_address();
// TODO: change the address to the actual escrow contract once it's implemented.
Expand All @@ -133,35 +119,26 @@ mod Orderbook {
self.inscription_statuses.write(inscription_id, Status::Canceled);
}

/// Called by a submitter. Multiple submitters are allowed to lock the
/// inscription simultaneously. The fee will be received only by the
/// submitter that will actually create the inscription on Bitcoin.
/// Assert that the inscription has not been closed yet. If there is a
/// Called by a submitter. Multiple submitters are allowed to lock the
/// inscription simultaneously. The fee will be received only by the
/// submitter that will actually create the inscription on Bitcoin.
/// Assert that the inscription has not been closed yet. If there is a
/// prior lock on the inscription, X blocks have to pass before a new
/// lock can be created.
/// Inputs:
/// - `inscription_id: u32`, the ID of the inscription being locked.
/// Inputs:
/// - `inscription_id: u32`, the ID of the inscription being locked.
/// - `tx_hash: ByteArray`, the precomputed bitcoin transaction hash that will be
/// submitted onchain by the submitter.
/// submitted onchain by the submitter.
fn lock_inscription(ref self: ContractState, inscription_id: u32, tx_hash: ByteArray) {
let status = self.inscription_statuses.read(inscription_id);
assert(
status != Status::Undefined,
'Inscription does not exist'
);
assert(
status != Status::Canceled,
'The inscription is canceled'
);
assert(
status != Status::Closed,
'The inscription has been closed'
);
assert(status != Status::Undefined, 'Inscription does not exist');
assert(status != Status::Canceled, 'The inscription is canceled');
assert(status != Status::Closed, 'The inscription has been closed');

if (status == Status::Locked) {
let (_, _, blocknumber) = self.inscription_locks.read(inscription_id);
// TODO: replace block time delta
assert(get_block_number() - blocknumber < 100, 'Prior lock has not expired');
assert(get_block_number() - blocknumber < 100, 'Prior lock has not expired');
}

let submitter = get_caller_address();
Expand All @@ -171,11 +148,11 @@ mod Orderbook {
self.inscription_statuses.write(inscription_id, Status::Locked);
}

/// Called by a submitter. The fee is transferred to the submitter if
/// the inscription on Bitcoin has been made. The submitted hash must
/// match the precomputed transaction hash in storage. If successful,
/// Called by a submitter. The fee is transferred to the submitter if
/// the inscription on Bitcoin has been made. The submitted hash must
/// match the precomputed transaction hash in storage. If successful,
/// the status of the inscription changes from 'Locked' to 'Closed'.
/// Inputs:
/// Inputs:
/// - `inscription_id: felt252`, the ID of the inscription being locked.
/// - `tx_hash: ByteArray`, the hash of the transaction submitted to Bitcoin.
fn submit_inscription(ref self: ContractState, inscription_id: u32, tx_hash: ByteArray) {
Expand All @@ -188,8 +165,8 @@ mod Orderbook {
}

/// Helper function that checks if the inscription has already been locked.
/// Inputs:
/// - `tx_hash: ByteArray`, the precomputed transaction hash for the inscription
/// Inputs:
/// - `tx_hash: ByteArray`, the precomputed transaction hash for the inscription
/// being locked.
/// Returns:
/// - `(bool, ContractAddress)`
Expand All @@ -203,7 +180,7 @@ mod Orderbook {

#[generate_trait]
pub impl InternalImpl of InternalTrait {
/// Executed once when the Orderbook contract is deployed. Used to set
/// Executed once when the Orderbook contract is deployed. Used to set
/// initial values for contract storage variables for the fee tokens.
fn initializer(ref self: ContractState, strk_token: ContractAddress) {
self.strk_token.write(ERC20ABIDispatcher { contract_address: strk_token });
Expand Down
Loading
Loading