|
1 | | -//SPDX-License-Identifier: MIT |
| 1 | +// SPDX-License-Identifier: MIT |
2 | 2 | pragma solidity >=0.8.0 <0.9.0; |
3 | 3 |
|
4 | 4 | import { IListingType } from "./IListingType.sol"; |
5 | 5 |
|
6 | 6 | contract Marketplace { |
7 | | - // Custom errors |
8 | | - error ListingTypeZeroAddress(); |
| 7 | + error ListingCreationFailed(); |
| 8 | + error OnlyListingTypeCanModify(); |
9 | 9 | error ListingNotFound(); |
10 | | - error NotCreator(); |
11 | | - error BeforeCreateFailed(); |
12 | | - error InnerIdZero(); |
13 | | - error AfterCreateFailed(); |
14 | | - error BeforePreBuyFailed(); |
15 | | - error OnPreBuyFailed(); |
16 | | - error AfterPreBuyFailed(); |
17 | | - error BeforeSaleFailed(); |
18 | | - error OnSaleFailed(); |
19 | | - error AfterSaleFailed(); |
20 | | - error BeforeCloseFailed(); |
21 | | - error OnCloseFailed(); |
22 | | - error AfterCloseFailed(); |
| 10 | + |
23 | 11 | struct ListingPointer { |
24 | 12 | address creator; |
25 | | - address listingType; // contract implementing IListingType |
26 | | - uint256 listingId; // ID inside the listing type contract |
| 13 | + address listingType; |
| 14 | + bytes32 contenthash; |
| 15 | + bool active; |
27 | 16 | } |
28 | 17 |
|
29 | 18 | uint256 public listingCount; |
30 | 19 | mapping(uint256 => ListingPointer) public listings; |
31 | 20 |
|
32 | | - event ListingCreated(uint256 indexed id, address indexed creator, address indexed listingType, uint256 listingId); |
33 | | - event ListingSold(uint256 indexed id, address indexed buyer); |
34 | | - event ListingClosed(uint256 indexed id, address indexed caller); |
35 | | - event ListingPreBuy(uint256 indexed id, address indexed buyer); |
36 | | - |
37 | | - modifier onlyListing(uint256 id) { |
38 | | - if (listings[id].listingType == address(0)) revert ListingNotFound(); |
39 | | - _; |
40 | | - } |
41 | | - |
42 | | - function createListing(address listingType, bytes calldata data) external returns (uint256 id) { |
43 | | - if (listingType == address(0)) revert ListingTypeZeroAddress(); |
44 | | - |
45 | | - // lifecycle: beforeCreate -> onCreate -> afterCreate |
46 | | - if (!IListingType(listingType).beforeCreate(data)) revert BeforeCreateFailed(); |
47 | | - uint256 innerId = IListingType(listingType).onCreate(msg.sender, data); |
48 | | - if (innerId == 0) revert InnerIdZero(); |
| 21 | + event ListingCreated(uint256 indexed id, address indexed creator, address indexed listingType, uint256 listingId, bytes32 contenthash); |
| 22 | + event ListingAction(uint256 indexed id, address indexed caller, bytes32 action); |
| 23 | + event ListingActivationChanged(uint256 indexed listingId, bool active); |
49 | 24 |
|
| 25 | + function createListing( |
| 26 | + address listingType, |
| 27 | + bytes32 contenthash, |
| 28 | + bytes calldata data |
| 29 | + ) external returns (uint256 id) { |
50 | 30 | id = ++listingCount; |
51 | | - listings[id] = ListingPointer({ creator: msg.sender, listingType: listingType, listingId: innerId }); |
52 | | - |
53 | | - if (!IListingType(listingType).afterCreate(innerId, data)) revert AfterCreateFailed(); |
54 | | - emit ListingCreated(id, msg.sender, listingType, innerId); |
| 31 | + bool success = IListingType(listingType).create(msg.sender, id, data); |
| 32 | + if (!success) revert ListingCreationFailed(); |
| 33 | + listings[id] = ListingPointer(msg.sender, listingType, contenthash, true); |
| 34 | + emit ListingCreated(id, msg.sender, listingType, id, contenthash); |
55 | 35 | } |
56 | 36 |
|
57 | | - function preBuyAction(uint256 id, bytes calldata data) external payable onlyListing(id) { |
| 37 | + function callAction( |
| 38 | + uint256 id, |
| 39 | + bytes32 action, |
| 40 | + bytes calldata data |
| 41 | + ) external payable { |
| 42 | + if (id > listingCount) revert ListingNotFound(); |
58 | 43 | ListingPointer memory ptr = listings[id]; |
59 | | - |
60 | | - if (!IListingType(ptr.listingType).beforePreBuy(ptr.listingId, msg.sender, data)) revert BeforePreBuyFailed(); |
61 | | - if (!IListingType(ptr.listingType).onPreBuy{ value: msg.value }(ptr.listingId, msg.sender, data)) |
62 | | - revert OnPreBuyFailed(); |
63 | | - if (!IListingType(ptr.listingType).afterPreBuy(ptr.listingId, msg.sender, data)) revert AfterPreBuyFailed(); |
64 | | - |
65 | | - emit ListingPreBuy(id, msg.sender); |
| 44 | + IListingType(ptr.listingType).handleAction{value: msg.value}(id, ptr.creator, ptr.active, msg.sender, action, data); |
| 45 | + emit ListingAction(id, msg.sender, action); |
66 | 46 | } |
67 | 47 |
|
68 | | - function buyListing(uint256 id, bytes calldata data) external payable onlyListing(id) { |
69 | | - ListingPointer memory ptr = listings[id]; |
70 | | - |
71 | | - // lifecycle: beforeSale -> onSale -> afterSale |
72 | | - if (!IListingType(ptr.listingType).beforeSale(ptr.listingId, msg.sender, data)) revert BeforeSaleFailed(); |
73 | | - if (!IListingType(ptr.listingType).onSale{ value: msg.value }(ptr.listingId, msg.sender, data)) |
74 | | - revert OnSaleFailed(); |
75 | | - if (!IListingType(ptr.listingType).afterSale(ptr.listingId, msg.sender, data)) revert AfterSaleFailed(); |
76 | | - |
77 | | - emit ListingSold(id, msg.sender); |
| 48 | + function setActive(uint256 listingId, bool active) external { |
| 49 | + ListingPointer storage record = listings[listingId]; |
| 50 | + if (msg.sender != record.listingType) revert OnlyListingTypeCanModify(); |
| 51 | + record.active = active; |
| 52 | + emit ListingActivationChanged(listingId, active); |
78 | 53 | } |
79 | 54 |
|
80 | | - function closeListing(uint256 id, bytes calldata data) external onlyListing(id) { |
| 55 | + function getListing(uint256 id) external view returns ( |
| 56 | + address creator, |
| 57 | + address listingType, |
| 58 | + bytes32 contenthash, |
| 59 | + bool active, |
| 60 | + bytes memory listingData |
| 61 | + ) { |
81 | 62 | ListingPointer memory ptr = listings[id]; |
82 | | - if (ptr.creator != msg.sender) revert NotCreator(); |
83 | | - |
84 | | - if (!IListingType(ptr.listingType).beforeClose(ptr.listingId, msg.sender, data)) revert BeforeCloseFailed(); |
85 | | - if (!IListingType(ptr.listingType).onClose(ptr.listingId, msg.sender, data)) revert OnCloseFailed(); |
86 | | - if (!IListingType(ptr.listingType).afterClose(ptr.listingId, msg.sender, data)) revert AfterCloseFailed(); |
87 | | - emit ListingClosed(id, msg.sender); |
88 | | - } |
89 | | - |
90 | | - function getListing( |
91 | | - uint256 id |
92 | | - ) external view onlyListing(id) returns (ListingPointer memory pointer, bytes memory data) { |
93 | | - pointer = listings[id]; |
94 | | - data = IListingType(pointer.listingType).getListing(pointer.listingId); |
| 63 | + creator = ptr.creator; |
| 64 | + listingType = ptr.listingType; |
| 65 | + contenthash = ptr.contenthash; |
| 66 | + active = ptr.active; |
| 67 | + listingData = IListingType(ptr.listingType).getListing(id); |
95 | 68 | } |
96 | 69 | } |
0 commit comments