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

Check NFT total value #6

Merged
merged 3 commits into from
Feb 26, 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
24 changes: 15 additions & 9 deletions contracts/dex-lock/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use ckb_std::{

pub fn main() -> Result<(), Error> {
let args = DexArgs::from_script()?;
// When the inputs contain a cell whose lock script is owner, it means that the owner is
// cancelling the maker order.
// When the inputs contain a cell whose lock script is owner, it means that the owner can do
// anything including cancel the order
if inputs_contain_owner_cell(&args) {
return Ok(());
}
Expand All @@ -27,13 +27,19 @@ pub fn main() -> Result<(), Error> {
let dex_input_capacity = load_cell_capacity(dex_index, Source::Input)? as u128;
let output_capacity = load_cell_capacity(dex_index, Source::Output)? as u128;

// Prevent total_value(u128) from overflowing
let total_capacity = args
.total_value
.checked_add(dex_input_capacity)
.ok_or(Error::TotalValueOverflow)?;
if total_capacity > output_capacity {
return Err(Error::DexTotalValueNotMatch);
if args.is_nft() {
if args.total_value > output_capacity {
return Err(Error::DexNFTTotalValueNotMatch);
}
} else if args.is_udt() {
// Prevent total_value(u128) from overflowing
let total_capacity = args
.total_value
.checked_add(dex_input_capacity)
.ok_or(Error::TotalValueOverflow)?;
if total_capacity > output_capacity {
return Err(Error::DexFTTotalValueNotMatch);
}
}

Ok(())
Expand Down
5 changes: 3 additions & 2 deletions contracts/dex-lock/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ pub enum Error {
Encoding,
LockArgsInvalid = 5,
DexOwnerLockNotMatch,
DexTotalValueNotMatch,
DexFTTotalValueNotMatch,
DexNFTTotalValueNotMatch,
DexSetupInvalid,
TotalValueOverflow,
TotalValueOverflow = 10,
}

impl From<SysError> for Error {
Expand Down
13 changes: 11 additions & 2 deletions contracts/dex-lock/src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const MIN_ARGS_SIZE: usize = 66;
pub struct DexArgs {
// the minimum length of serialized lock script is 49bytes
pub owner_lock: Script,
// 0b_xxxx_x0xx is for FT asset and 0b_xxxx_x1xx is for NFT asset
pub setup: u8,
pub total_value: u128,
}
Expand All @@ -33,8 +34,8 @@ impl DexArgs {

let owner_lock = Script::from_slice(&data[..owner_size]).map_err(|_e| Error::Encoding)?;
let setup = data[owner_size];
// If the third bit of setup is 0, it means FT(0b0000_0000), otherwise it means
// NFT(0b0000_0100)
// If the third bit of setup is 0, it means FT(0b_xxxx_x0xx), otherwise it means
// NFT(0b_xxxx_x1xx). The remaining bits are temporarily reserved or not implemented
if setup != 0 && setup != 4 {
return Err(Error::DexSetupInvalid);
}
Expand All @@ -47,6 +48,14 @@ impl DexArgs {
total_value,
})
}

pub fn is_udt(&self) -> bool {
self.setup | 0b0000_0000 == 0b0000_0000
}

pub fn is_nft(&self) -> bool {
self.setup & 0b0000_0100 == 0b0000_0100
}
}

pub fn position_dex_lock_in_inputs() -> Result<usize, Error> {
Expand Down
10 changes: 5 additions & 5 deletions tests/src/cancel_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ const MAX_CYCLES: u64 = 70_000_000;

// error numbers
const LOCK_ARGS_INVALID: i8 = 5;
const DEX_TOTAL_VALUE_NOT_MATCH: i8 = 7;
const DEX_FT_TOTAL_VALUE_NOT_MATCH: i8 = 7;

#[derive(PartialEq, Eq, Clone, Copy)]
enum DexError {
NoError,
LockArgsInvalid,
DexTotalValueNotMatch,
DexFTTotalValueNotMatch,
}

fn create_test_context(error: DexError) -> (Context, TransactionView) {
Expand Down Expand Up @@ -113,7 +113,7 @@ fn create_test_context(error: DexError) -> (Context, TransactionView) {
.previous_output(input_out_point2)
.build(),
];
if error != DexError::DexTotalValueNotMatch {
if error != DexError::DexFTTotalValueNotMatch {
inputs.push(
CellInput::new_builder()
.previous_output(input_out_point3)
Expand Down Expand Up @@ -181,8 +181,8 @@ fn test_dex_cancel_order_lock_args_error() {

#[test]
fn test_dex_cancel_order_owner_lock_not_match_error() {
let (context, tx) = create_test_context(DexError::DexTotalValueNotMatch);
let (context, tx) = create_test_context(DexError::DexFTTotalValueNotMatch);
// run
let err = context.verify_tx(&tx, MAX_CYCLES).unwrap_err();
assert_script_error(err, DEX_TOTAL_VALUE_NOT_MATCH);
assert_script_error(err, DEX_FT_TOTAL_VALUE_NOT_MATCH);
}
30 changes: 22 additions & 8 deletions tests/src/taker_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@ const MAX_CYCLES: u64 = 70_000_000;
// error numbers
const LOCK_ARGS_INVALID: i8 = 5;
const DEX_OWNER_LOCK_NOT_MATCH: i8 = 6;
const DEX_TOTAL_VALUE_NOT_MATCH: i8 = 7;
const DEX_SETUP_INVALID: i8 = 8;
const TOTAL_VALUE_OVERFLOW: i8 = 9;
const DEX_FT_TOTAL_VALUE_NOT_MATCH: i8 = 7;
const DEX_NFT_TOTAL_VALUE_NOT_MATCH: i8 = 8;
const DEX_SETUP_INVALID: i8 = 9;
const TOTAL_VALUE_OVERFLOW: i8 = 10;

#[derive(PartialEq, Eq, Clone, Copy)]
enum DexError {
NoError,
LockArgsInvalid,
DexOwnerLockNotMatch,
DexTotalValueNotMatch,
DexFTTotalValueNotMatch,
DexNFTTotalValueNotMatch,
DexSetupInvalid,
TotalValueOverflow,
}
Expand Down Expand Up @@ -68,6 +70,8 @@ fn create_test_context(error: DexError) -> (Context, TransactionView) {

let setup = if error == DexError::DexSetupInvalid {
3u8
} else if error == DexError::DexNFTTotalValueNotMatch {
4u8
} else {
0u8
};
Expand Down Expand Up @@ -135,8 +139,10 @@ fn create_test_context(error: DexError) -> (Context, TransactionView) {
.build(),
];

let output1_capacity = if error == DexError::DexTotalValueNotMatch {
let output1_capacity = if error == DexError::DexFTTotalValueNotMatch {
1234_5678_0000u64
} else if error == DexError::DexNFTTotalValueNotMatch {
1000_5678_0000u64
} else {
1234_5678_0000u64 + 300_0000_0000u64
};
Expand Down Expand Up @@ -208,11 +214,19 @@ fn test_dex_taker_order_owner_lock_not_match_error() {
}

#[test]
fn test_dex_taker_order_total_value_not_match_error() {
let (context, tx) = create_test_context(DexError::DexTotalValueNotMatch);
fn test_dex_ft_taker_order_total_value_not_match_error() {
let (context, tx) = create_test_context(DexError::DexFTTotalValueNotMatch);
// run
let err = context.verify_tx(&tx, MAX_CYCLES).unwrap_err();
assert_script_error(err, DEX_TOTAL_VALUE_NOT_MATCH);
assert_script_error(err, DEX_FT_TOTAL_VALUE_NOT_MATCH);
}

#[test]
fn test_dex_nft_taker_order_total_value_not_match_error() {
let (context, tx) = create_test_context(DexError::DexNFTTotalValueNotMatch);
// run
let err = context.verify_tx(&tx, MAX_CYCLES).unwrap_err();
assert_script_error(err, DEX_NFT_TOTAL_VALUE_NOT_MATCH);
}

#[test]
Expand Down
Loading