Skip to content
Open
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
21 changes: 21 additions & 0 deletions contracts/marketplace/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "rebaz_marketplace"
version = "1.0.0"
authors = []

[addresses]
rebaz = "0xa"

[dev-addresses]

[dependencies.SupraFramework]
git = "https://github.com/Entropy-Foundation/aptos-core.git"
rev = "dev"
subdir = "aptos-move/framework/supra-framework"

[dependencies.AptosTokenObjects]
git = "https://github.com/Entropy-Foundation/aptos-core.git"
rev = "dev"
subdir = "aptos-move/framework/aptos-token-objects"

[dev-dependencies]
102 changes: 102 additions & 0 deletions contracts/marketplace/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Marketplace Smart Contract - Supra Move

## Overview

Deployed Contract (check wallet modules) [Testnet](https://testnet.suprascan.io/tx/0x128f338869fc2d0094f4dd7d5ec1bf9b065f846b2a690acfa45e2e19969f504d/f)

The Marketplace smart contract is built using **Move** on the **Supra Network**. It provides a decentralized marketplace where users can:

- **List** Impact products for sale.
- **Buy** listed products using SupraCoin ($SUPRA).
- **Unlist** products before they are sold.
- **Transfer ownership** of the marketplace to a new admin.
- **Withdraw fees** collected from transactions.
- **Pause/unpause** the marketplace for maintenance.

## Features

### 1. **Marketplace Creation**

- The marketplace is initialized by an **admin** using the `init_marketplace_and_get_address` function.
- It requires a **name** and a **fee percentage** (e.g., 2% of sales as platform fees).

### 2. **Listing a Product**

- Sellers can list NFT-based products using `list_product_internal`.
- Requires:
- **Product Name**
- **NFT Object**
- **Price in SupraCoin ($SUPRA)**
- **Marketplace Address**

### 3. **Buying a Product**

- Users can purchase products using the `buy_product` function.
- The contract:
- Transfers **funds** from the buyer to the seller (minus fees).
- Transfers **NFT ownership** to the buyer.
- Ensures a product **cannot be sold twice**.

### 4. **Unlisting a Product**

- Only the **seller** can remove a listed product before it is sold using `unlist_product`.
- After a product is unlisted, the NFT is **returned to the seller**.

### 5. **Marketplace Fees**

- A percentage of each sale is **collected as fees**.
- The admin can withdraw accumulated fees using `withdraw_fees`.

### 6. **Marketplace Ownership Transfer**

- The admin can **transfer ownership** using `transfer_ownership`.
- The new owner must **claim ownership** using `claim_ownership`.
- Admin transfers can be **canceled** before being claimed.
- The admin can **permanently disable** ownership by setting it to `0x0`.

### 7. **Marketplace Management**

- The admin can **pause/unpause** the marketplace using `update_pause`.
- When paused, **new transactions (buys & listings) are disabled**.

## Installation & Setup

### **1. Install Supra CLI with Docker**

Follow the official installation guide:
[Install Supra CLI](https://docs.supra.com/move/getting-started/supra-cli-with-docker)

### **2. Compile the Marketplace Contract**

```sh
supra move tool compile --package-dir /supra/configs/move_workspace/<PROJECT_NAME>
```

### **3. Run Tests**

To ensure the contract works correctly, run the unit tests:

```sh
supra move tool test --package-dir /supra/configs/move_workspace/<PROJECT_NAME>
```

### **4. Deploy the Contract**

Deployment requires specifying a named address within the `move.toml` file.

```sh
supra move tool publish --package-dir /supra/configs/move_workspace/<PROJECT_NAME> --profile <YOUR_PROFILE> --url <RPC_URL>
```

For the latest RPC URL, check the **Supra Network Information** page.

## Smart Contract Tests

This contract includes extensive unit tests covering:

- **Listing and unlisting products**
- **Purchasing with correct funds**
- **Handling insufficient balance purchases**
- **Ensuring only sellers can unlist**
- **Ownership transfer and claim validation**
- **Marketplace pausing and fee withdrawals**
273 changes: 273 additions & 0 deletions contracts/marketplace/sources/events.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
module rebaz::events {
use std::option::{Self, Option};
use std::string::String;

use supra_framework::event;
use supra_framework::object::{Object};

use aptos_token_objects::collection;
use aptos_token_objects::token;

friend rebaz::marketplace;

struct TokenMetadata has drop, store {
creator_address: address,
collection_name: String,
collection: Option<Object<collection::Collection>>,
token_name: String,
token: Option<Object<token::Token>>,
property_version: Option<u64>,
}

public fun token_metadata(token: Object<token::Token>): TokenMetadata {
TokenMetadata {
creator_address: token::creator(token),
collection_name: token::collection_name(token),
collection: option::some(token::collection_object(token)),
token_name: token::name(token),
token: option::some(token),
property_version: option::none(),
}
}

#[event]
struct InitEvent has drop, store {
marketplace: address,
name: String,
fee_percentage: u64,
admin: address,
}

public(friend) fun emit_init_event(
marketplace: address,
name: String,
fee_percentage: u64,
admin: address
) {
event::emit(InitEvent {
marketplace,
name,
fee_percentage,
admin,
});
}

#[event]
struct ListEvent has drop, store {
marketplace: address,
product_id: u64,
product_name: String,
creator: address,
price: u64,
token_metadata: TokenMetadata
}

public(friend) fun emit_list_event(
marketplace: address,
product_id: u64,
product_name: String,
creator: address,
price: u64,
token_metadata: TokenMetadata
) {
event::emit(ListEvent {
marketplace,
product_id,
product_name,
creator,
price,
token_metadata
});
}

#[event]
struct UnlistEvent has drop, store {
marketplace: address,
product_id: u64,
creator: address,
price: u64,
token_metadata: TokenMetadata
}

public(friend) fun emit_unlist_event(
marketplace: address,
product_id: u64,
creator: address,
price: u64,
token_metadata: TokenMetadata
) {
event::emit(UnlistEvent {
marketplace,
product_id,
creator,
price,
token_metadata
});
}

#[event]
struct BuyEvent has drop, store {
marketplace: address,
product_id: u64,
seller: address,
buyer: address,
price: u64,
fees: u64,
token_metadata: TokenMetadata
}

public(friend) fun emit_buy_event(
marketplace: address,
product_id: u64,
seller: address,
buyer: address,
price: u64,
fees: u64,
token_metadata: TokenMetadata
) {
event::emit(BuyEvent {
marketplace,
product_id,
seller,
buyer,
price,
fees,
token_metadata
});
}


#[event]
struct OwnershipTransferEvent has drop, store {
marketplace: address,
admin: address,
new_admin: address,
}

public(friend) fun emit_ownership_transfer_event(
marketplace: address,
admin: address,
new_admin: address,
) {
event::emit(OwnershipTransferEvent {
marketplace,
admin,
new_admin,
});
}

#[event]
struct CancelTransferEvent has drop, store {
marketplace: address,
admin: address,
}

public(friend) fun emit_cancel_ownership_transfer_event(
marketplace: address,
admin: address,
) {
event::emit(CancelTransferEvent {
marketplace,
admin,
});
}

#[event]
struct ClaimOwnershipEvent has drop, store {
marketplace: address,
new_admin: address,
old_admin: address,
}

public(friend) fun emit_claim_ownership_event(
marketplace: address,
new_admin: address,
old_admin: address,
) {
event::emit(ClaimOwnershipEvent {
marketplace,
new_admin,
old_admin
});
}

#[event]
struct DisableOwnershipEvent has drop, store {
marketplace: address,
new_admin: address,
old_admin: address,
}

public(friend) fun emit_disable_ownership_event(
marketplace: address,
new_admin: address,
old_admin: address,
) {
event::emit(DisableOwnershipEvent {
marketplace,
new_admin,
old_admin
});
}

#[event]
struct FeesUpdateEvent has drop, store {
marketplace: address,
admin: address,
old_fee_percentage: u64,
new_fee_percentage: u64,
}

public(friend) fun emit_fees_update_event(
marketplace: address,
admin: address,
old_fee_percentage: u64,
new_fee_percentage: u64,
) {
event::emit(FeesUpdateEvent {
marketplace,
admin,
old_fee_percentage,
new_fee_percentage,
});
}

#[event]
struct PauseEvent has drop, store {
marketplace: address,
admin: address,
pause: bool
}

public(friend) fun emit_pause_event(
marketplace: address,
admin: address,
pause: bool
) {
event::emit(PauseEvent {
marketplace,
admin,
pause
});
}

#[event]
struct WitdrawFeesEvent has drop, store {
marketplace: address,
admin: address,
amount: u64
}

public(friend) fun emit_withdraw_fees_event(
marketplace: address,
admin: address,
amount: u64
) {
event::emit(WitdrawFeesEvent {
marketplace,
admin,
amount
});
}

}
Loading