Skip to content

Commit

Permalink
fix: emit OrderCancelled event when an order is cancelled by a new one (
Browse files Browse the repository at this point in the history
#486)

## Description

- Add missing emit of `OrderCancelled` event when an order is cancelled
by a new one.
- Fix local deployment
- SDK: add missing `quantity` field in `FulfillInfo`

<!--
Please do not leave this blank.
Describe the changes in this PR. What does it [add/remove/fix/replace]?

For crafting a good description, consider using ChatGPT to help
articulate your changes.
-->

## What type of PR is this? (check all applicable)

- [ ] 🍕 Feature (`feat:`)
- [x] 🐛 Bug Fix (`fix:`)
- [ ] 📝 Documentation Update (`docs:`)
- [ ] 🎨 Style (`style:`)
- [ ] 🧑‍💻 Code Refactor (`refactor:`)
- [ ] 🔥 Performance Improvements (`perf:`)
- [x] ✅ Test (`test:`)
- [ ] 🤖 Build (`build:`)
- [ ] 🔁 CI (`ci:`)
- [ ] 📦 Chore (`chore:`)
- [ ] ⏩ Revert (`revert:`)
- [ ] 🚀 Breaking Changes (`BREAKING CHANGE:`)

## Related Tickets & Documents

<!--
Please use this format to link related issues: Fixes #<issue_number>
More info:
https://docs.github.com/en/free-pro-team@latest/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword
-->

## Added tests?

- [x] 👍 yes
- [ ] 🙅 no, because they aren't needed
- [ ] 🙋 no, because I need help

## Added to documentation?

- [ ] 📜 README.md
- [ ] 📓 Documentation
- [ ] 🙅 no documentation needed

## [optional] Are there any post-deployment tasks we need to perform?

<!-- Describe any additional tasks, if any, and provide steps. -->

## [optional] What gif best describes this PR or how it makes you feel?

<!-- Share a fun gif related to your PR! -->

### PR Title and Description Guidelines:

- Ensure your PR title follows semantic versioning standards. This helps
automate releases and changelogs.
- Use types like `feat:`, `fix:`, `chore:`, `BREAKING CHANGE:` etc. in
your PR title.
- Your PR title will be used as a commit message when merging. Make sure
it adheres to [Conventional Commits
standards](https://www.conventionalcommits.org/).

## Closing Issues

<!--
Use keywords to close related issues. This ensures that the associated
issues will automatically close when the PR is merged.

- `Fixes #123` will close issue 123 when the PR is merged.
- `Closes #123` will also close issue 123 when the PR is merged.
- `Resolves #123` will also close issue 123 when the PR is merged.

You can also use multiple keywords in one comment:
- `Fixes #123, Resolves #456`

More info:
https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue
-->
  • Loading branch information
ptisserand authored Oct 23, 2024
1 parent 446631d commit d81ed8d
Show file tree
Hide file tree
Showing 10 changed files with 234 additions and 4 deletions.
24 changes: 24 additions & 0 deletions contracts/ark_component/src/orderbook/orderbook.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,18 @@ pub mod OrderbookComponent {
let cancelled_order_hash = self._process_previous_order(token_hash, order.offerer);
order_write(order_hash, order_type, order);
self.token_listings.write(token_hash, order_hash);
if (cancelled_order_hash.is_some()) {
let cancelled_order_hash = cancelled_order_hash.unwrap();
self
.emit(
OrderCancelled {
order_hash: cancelled_order_hash,
reason: OrderStatus::CancelledByNewOrder.into(),
order_type,
version: ORDER_CANCELLED_EVENT_VERSION,
}
)
}
self
.emit(
OrderPlaced {
Expand Down Expand Up @@ -710,6 +722,18 @@ pub mod OrderbookComponent {
let cancelled_order_hash = self._process_previous_order(token_hash, order.offerer);
order_write(order_hash, order_type, order);
self.auctions.write(token_hash, (order_hash, order.end_date, 0));
if (cancelled_order_hash.is_some()) {
let cancelled_order_hash = cancelled_order_hash.unwrap();
self
.emit(
OrderCancelled {
order_hash: cancelled_order_hash,
reason: OrderStatus::CancelledByNewOrder.into(),
order_type,
version: ORDER_CANCELLED_EVENT_VERSION,
}
)
}
self
.emit(
OrderPlaced {
Expand Down
194 changes: 193 additions & 1 deletion contracts/ark_starknet/tests/integration/create_order.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use ark_tokens::erc20::IFreeMintDispatcherTrait as Erc20DispatcherTrait;
use ark_tokens::erc721::IFreeMintDispatcher as Erc721Dispatcher;
use ark_tokens::erc721::IFreeMintDispatcherTrait as Erc721DispatcherTrait;

use openzeppelin::token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait};

use snforge_std::{
cheat_caller_address, CheatSpan, spy_events, EventSpyAssertionsTrait,
start_cheat_block_timestamp_global, stop_cheat_block_timestamp_global
Expand Down Expand Up @@ -523,7 +525,6 @@ fn test_create_order_erc1155_to_erc20_ok() {
fn test_create_order_offerer_not_own_enough_erc1155_token() {
let (executor_address, erc20_address, erc1155_address) = setup_erc1155();
let offerer = erc1155_address;
let other = contract_address_const::<'other'>();
let quantity = 50_u256;

let token_id = Erc1155Dispatcher { contract_address: erc1155_address }.mint(offerer, 2_u256);
Expand Down Expand Up @@ -582,3 +583,194 @@ fn test_create_order_erc1155_to_erc20_disabled() {
IExecutorDispatcher { contract_address: executor_address }.create_order(order);
}


#[test]
fn test_create_listing_order_transfer_token_to_other_user() {
let (executor_address, erc20_address, nft_address) = setup();
let offerer = contract_address_const::<'offerer'>();
let other_offerer = contract_address_const::<'other_offerer'>();

let start_amount = 10_000_000;
let other_start_amount = 20_000_000;

let token_id: u256 = Erc721Dispatcher { contract_address: nft_address }
.get_current_token_id()
.into();
Erc721Dispatcher { contract_address: nft_address }.mint(offerer, 'base_uri');

let order = setup_listing_order(erc20_address, nft_address, offerer, token_id, start_amount);
let order_hash = order.compute_order_hash();

cheat_caller_address(executor_address, offerer, CheatSpan::TargetCalls(1));
IExecutorDispatcher { contract_address: executor_address }.create_order(order);

cheat_caller_address(nft_address, offerer, CheatSpan::TargetCalls(1));
IERC721Dispatcher { contract_address: nft_address }
.transfer_from(offerer, other_offerer, token_id);

let other_order = setup_listing_order(
erc20_address, nft_address, other_offerer, token_id, other_start_amount
);
let other_order_hash = other_order.compute_order_hash();
let order_version = other_order.get_version();

let mut spy = spy_events();
cheat_caller_address(executor_address, other_offerer, CheatSpan::TargetCalls(1));
IExecutorDispatcher { contract_address: executor_address }.create_order(other_order);

spy
.assert_emitted(
@array![
(
executor_address,
executor::Event::OrderbookEvent(
OrderbookComponent::Event::OrderCancelled(
OrderbookComponent::OrderCancelled {
order_hash,
reason: OrderStatus::CancelledByNewOrder.into(),
order_type: OrderType::Listing,
version: OrderbookComponent::ORDER_CANCELLED_EVENT_VERSION,
}
)
)
),
(
executor_address,
executor::Event::OrderbookEvent(
OrderbookComponent::Event::OrderPlaced(
OrderbookComponent::OrderPlaced {
order_hash: other_order_hash,
order_version,
order_type: OrderType::Listing,
version: OrderbookComponent::ORDER_PLACED_EVENT_VERSION,
cancelled_order_hash: Option::Some(order_hash),
order: other_order,
}
)
)
)
]
);

assert_eq!(
IOrderbookDispatcher { contract_address: executor_address }.get_order_type(order_hash),
OrderType::Listing,
"Wrong order type"
);
assert_eq!(
IOrderbookDispatcher { contract_address: executor_address }
.get_order_type(other_order_hash),
OrderType::Listing,
"Wrong other order type"
);

assert_eq!(
IOrderbookDispatcher { contract_address: executor_address }.get_order_status(order_hash),
OrderStatus::CancelledByNewOrder,
"Wrong order status"
);

assert_eq!(
IOrderbookDispatcher { contract_address: executor_address }
.get_order_status(other_order_hash),
OrderStatus::Open,
"Wrong other order status"
);
}

#[test]
fn test_create_auction_order_transfer_token_to_other_user() {
let (executor_address, erc20_address, nft_address) = setup();
let offerer = contract_address_const::<'offerer'>();
let other_offerer = contract_address_const::<'other_offerer'>();

let start_amount = 10_000_000;
let other_start_amount = 15_000_000;
let end_amount = start_amount * 2;

let token_id: u256 = Erc721Dispatcher { contract_address: nft_address }
.get_current_token_id()
.into();
Erc721Dispatcher { contract_address: nft_address }.mint(offerer, 'base_uri');

let order = setup_auction_order(
erc20_address, nft_address, offerer, token_id, start_amount, end_amount
);
let order_hash = order.compute_order_hash();

cheat_caller_address(executor_address, offerer, CheatSpan::TargetCalls(1));
IExecutorDispatcher { contract_address: executor_address }.create_order(order);

cheat_caller_address(nft_address, offerer, CheatSpan::TargetCalls(1));
IERC721Dispatcher { contract_address: nft_address }
.transfer_from(offerer, other_offerer, token_id);

let other_order = setup_auction_order(
erc20_address, nft_address, other_offerer, token_id, other_start_amount, end_amount
);
let other_order_hash = other_order.compute_order_hash();
let order_version = other_order.get_version();

let mut spy = spy_events();
cheat_caller_address(executor_address, other_offerer, CheatSpan::TargetCalls(1));
IExecutorDispatcher { contract_address: executor_address }.create_order(other_order);

spy
.assert_emitted(
@array![
(
executor_address,
executor::Event::OrderbookEvent(
OrderbookComponent::Event::OrderCancelled(
OrderbookComponent::OrderCancelled {
order_hash,
reason: OrderStatus::CancelledByNewOrder.into(),
order_type: OrderType::Auction,
version: OrderbookComponent::ORDER_CANCELLED_EVENT_VERSION,
}
)
)
),
(
executor_address,
executor::Event::OrderbookEvent(
OrderbookComponent::Event::OrderPlaced(
OrderbookComponent::OrderPlaced {
order_hash: other_order_hash,
order_version,
order_type: OrderType::Auction,
version: OrderbookComponent::ORDER_PLACED_EVENT_VERSION,
cancelled_order_hash: Option::Some(order_hash),
order: other_order,
}
)
)
)
]
);

assert_eq!(
IOrderbookDispatcher { contract_address: executor_address }.get_order_type(order_hash),
OrderType::Auction,
"Wrong order type"
);
assert_eq!(
IOrderbookDispatcher { contract_address: executor_address }
.get_order_type(other_order_hash),
OrderType::Auction,
"Wrong other order type"
);

assert_eq!(
IOrderbookDispatcher { contract_address: executor_address }.get_order_status(order_hash),
OrderStatus::CancelledByNewOrder,
"Wrong order status"
);

assert_eq!(
IOrderbookDispatcher { contract_address: executor_address }
.get_order_status(other_order_hash),
OrderStatus::Open,
"Wrong other order status"
);
}
3 changes: 3 additions & 0 deletions packages/core/src/actions/order/fulfillAuction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface FulfillAuctionParameters {
relatedOrderHash: bigint;
tokenAddress: string;
tokenId: bigint;
quantity: bigint;
currencyAddress?: string;
waitForTransaction?: boolean;
}
Expand Down Expand Up @@ -44,6 +45,7 @@ export async function fulfillAuction(
relatedOrderHash,
tokenAddress,
tokenId,
quantity,
waitForTransaction = true
} = parameters;
const chainId = await config.starknetProvider.getChainId();
Expand All @@ -61,6 +63,7 @@ export async function fulfillAuction(
CairoOptionVariant.Some,
cairo.uint256(tokenId)
),
quantity: cairo.uint256(quantity),
fulfillBrokerAddress: brokerAddress
};

Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/actions/order/fulfillListing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface FulfillListingParameters {
orderHash: bigint;
tokenAddress: string;
tokenId: bigint;
quantity: bigint;
amount: bigint;
waitForTransaction?: boolean;
}
Expand Down Expand Up @@ -45,6 +46,7 @@ export async function fulfillListing(
orderHash,
tokenAddress,
tokenId,
quantity,
amount,
waitForTransaction = true
} = parameters;
Expand All @@ -66,6 +68,7 @@ export async function fulfillListing(
CairoOptionVariant.Some,
cairo.uint256(tokenId)
),
quantity: cairo.uint256(quantity),
fulfillBrokerAddress: brokerAddress
};

Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/actions/order/fulfillOffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface FulfillOfferParameters {
orderHash: bigint;
tokenAddress: string;
tokenId: bigint;
quantity: bigint;
waitForTransaction?: boolean;
}

Expand All @@ -41,6 +42,7 @@ export async function fulfillOffer(
orderHash,
tokenAddress,
tokenId,
quantity,
waitForTransaction = true
} = parameters;
const chainId = await config.starknetProvider.getChainId();
Expand All @@ -55,6 +57,7 @@ export async function fulfillOffer(
CairoOptionVariant.Some,
cairo.uint256(tokenId)
),
quantity: cairo.uint256(quantity),
fulfillBrokerAddress: brokerAddress
};

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export type FulfillInfo = {
tokenChainId: constants.StarknetChainId;
tokenAddress: string;
tokenId: CairoOption<Uint256>;
quantity: Uint256;
fulfillBrokerAddress: string;
};

Expand Down
3 changes: 2 additions & 1 deletion packages/core/tests/fulfillAuction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ describe("fulfillAuction", () => {
orderHash,
relatedOrderHash: offerOrderHash,
tokenAddress,
tokenId
tokenId,
quantity: BigInt(1),
});

const { orderStatus } = await getOrderStatus(config, {
Expand Down
1 change: 1 addition & 0 deletions packages/core/tests/fulfillListing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe("fulfillOffer", () => {
orderHash,
tokenAddress,
tokenId,
quantity: BigInt(1),
amount: startAmount
});

Expand Down
4 changes: 3 additions & 1 deletion packages/core/tests/fulfillOffer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ describe("fulfillOffer", () => {
brokerAddress: saleBroker.address,
orderHash,
tokenAddress,
tokenId
tokenId,
quantity: BigInt(1),
});

const { orderStatus: orderStatusFulfilled } = await getOrderStatus(config, {
Expand Down Expand Up @@ -66,6 +67,7 @@ describe("fulfillOffer", () => {
orderHash,
tokenAddress,
tokenId,
quantity: BigInt(1),
brokerAddress: saleBroker.address
});

Expand Down
2 changes: 1 addition & 1 deletion packages/deployer/src/contracts/erc721royalties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export async function deployERC721Royalties(
constructorCalldata: contractConstructor
});

setDefaultFees(
await setDefaultFees(
provider,
deployerAccount,
deployR.deploy.contract_address,
Expand Down

0 comments on commit d81ed8d

Please sign in to comment.