Skip to content

DecentraLabsCom/Smart-Contract-Specifications

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

description
A description of the smart contracts that rule the DecentraLabs ecosystem

Smart Contract Specification

This repository details the specification of a lab booking, access and sharing decentralized solution using Solidity smart contracts that includes role-based access control using OpenZeppelin libraries.


🧩 Diamond Structure

The proposed architecture leverages a diamond proxy (EIP-2535), behind which various smart contracts are deployed. This approach is chosen for two key reasons:

  1. To enable seamless updates and enhancements to the contracts without disrupting client functionality.
  2. To maintain a degree of control during the initial phases of development.

Once the diamond proxy is deployed, the account responsible for the deployment gains the ability to add other accounts, referred to as “providers”. Providers are empowered to list or register online laboratories, which can later be modified, deleted, or transferred to a different provider.

Users, on the other hand, are able to reserve laboratories listed by the providers, as well as cancel any of their existing reservations. Additionally, users can access laboratories they have previously reserved, as long as the reservation remains valid. This functionality is achieved through the implementation of a new proposal: reservable token, which allows for the reservation of the use of an ERC721 token over a time interval, improving upon existing standards.

The implementation of a dedicated payable token, $LAB, through ERC-20, is not covered within the scope of this document. This token is deployed separately from the diamond proxy and a basic specificacion can be found here LabERC20.sol.

The system is divided into multiple facets, each handling specific responsibilities:

  • ProviderFacet: Handles admin and provider roles.
  • LabFacet: Manages the lab entities.
  • ReservationFacet: Manages reservations/bookings.

👤 Roles & Actors

  • Contract Owner – Holds DEFAULT_ADMIN_ROLE. Deploys the diamond proxy and initialises facets. Only the owner can grant or revoke provider roles and perform administrative functions.
  • Provider – Holds PROVIDER_ROLE. Providers can mint new lab NFTs, update or delete their labs, list/unlist them for reservation, and claim funds from completed bookings. Providers are assigned by the owner using ProviderFacet.
  • User – Any address that can browse listed labs, request reservations and cancel their own pending bookings. Renters pay the reservation price in $LAB at the time of request.

📦 Data Models

Provider

Field Type Description
account address Wallet address
base.name string Provider name
base.email string Email address
base.country string Country

Lab (Cyber Physical System implemented as an NFT)

Field Type Description
labId uint Unique ID
base.uri string Off-chain metadata URI
base.price uint96 Price in $LAB tokens
base.auth string Authentication service URI
base.accessURI string Lab services acess URI
base.accessKey string Key or ID used for routing/access

Reservation (Booking presented as a new reservable token)

Field Type Description
reservationKey bytes32 Unique key associated with the reservation
labId uint Associated lab ID
renter address Renter address
price uint96 Rental price
start uint32 Start time (Unix epoch)
end uint32 End time (Unix epoch)
status status State of the reservation: 0 = PENDING, 1 = BOOKED, 2 = USED, 3 = COLLECTED, 4 = CANCELLED

⚙️ Functional Requirements

Below, each implemented function is listed.

ProviderFacet:

  • initialize: Sets up the initial contract state and assigns admin roles
  • addProvider: Grants PROVIDER_ROLE to a specified account and mints $LAB tokens.
  • removeProvider: Removes the caller’s PROVIDER_ROLE if conditions are met.
  • updateProvider: Updates the caller's provider information (name, email, country).
  • isLabProvider: Checks if a given account holds the PROVIDER_ROLE.
  • getLabProviders: Retrieves a list of all lab providers.

Since ProviderFacet extends OpenZeppelin’s OpenZeppelin’s AccessControlUpgradeable.sol contract, it inherits all role-based access control functionalities provided by the OpenZeppelin library.

LabFacet:

  • initialize: Sets up the ERC721 token with the provided name and symbol. Initializes the labId to 0.
  • addLab: Allows the lab provider to create and register a new lab with metadata securely stored on-chain.
  • setTokenURI: Allows the lab provider to set or update the URI for the file containing the off-chain metadata of a specific lab token ID.
  • tokenURI: Returns the URI for the off-chain metadata of a given lab/token ID. Used for compliance with ERC721 standards.
  • updateLab: Allows the lab provider to update metadata stored on-chain, including the token URI, which links to the metadata stored off-chain.
  • deleteLab: Allows the lab provider to delete an existing lab.
  • getLab: Retrieves the information about the lab structure (on-chain metadata) corresponding to the provided lab ID.
  • getLabsPaginated: Returns a paginated list of lab IDs and the total supply. Limit input must be between 1 and 100.

Since LabFacet extends OpenZeppelin’s OpenZeppelin’s ERC721EnumerableUpgradeable.sol contract, it inherits all the standard ERC-721 enumerable functionalities, including token enumeration and indexing capabilities.

ReservationFacet:

  • reservationRequest: Allows a user to request a booking for a lab.
  • confirmReservationRequest: The lab provider or authorized account confirms a pending reservation request for a lab.
  • denyReservationRequest: Denies a pending reservation request and refunds the payment if necessary.
  • cancelReservationRequest: Allows a user to cancel a previously requested reservation and refunds the payment if necessary.
  • cancelBooking: Allows a user or the lab provider to cancel an existing confirmed booking.
  • requestFunds: Allows lab providers to claim funds from used or expired reservations.
  • getLabTokenAddress: Returns the address of the $LAB token contract, set at ProviderFacet initialization.
  • getSafeBalance: Retrieves the total balance of $LAB funds held in the contract.

Since ReservationFacet implements the enumerable extension of the newly proposed Reservable Token, as defined in ReservableTokenEnumerable.sol, it also inherits all its functions.

Use case Specification Detailed information on how each specific use case is executed is provided below:

💎 ProviderFacet:

Description
Use case INITIALIZE
Definition function initialize(string memory _name, string memory _email, string memory _country, address _labERC20) public initializer
Actors Contract owner
Purpose Initializes the smart contract setting, the initial admin role and the ERC20 token external contract.
Summary Only the contract owner can initialize the contract
Preconditions Have a WALLET and sufficient funds. Can only be executed once.
Postconditions The contract becomes initialized
Events Emits a {RoleGranted} event if the role is successfully granted.
Description
Use case ADD PROVIDER
Definition function addProvider(string memory _name, address _account, string memory _email, string memory _country) external defaultAdminRole
Actors Contract owner
Purpose Adds a new provider by granting the PROVIDER_ROLE and minting tokens for the specified account.
Summary Only the contract owner can add a new provider.
Preconditions The account must not already have the PROVIDER_ROLE.
Postconditions The account receives the PROVIDER_ROLE and 1000 $LAB ERC20 tokens are minted for them.
Events Emits an {ProviderAdded} event if the provider is successfully added.
Description
Use case REMOVE SPECIFIC PROVIDER
Definition function removeProvider(address _provider) external defaultAdminRole
Actors Contract owner
Purpose Removes a specified provider from the provider list if they do not have any lab.
Summary Only the contract owner can remove a provider from the list.
Preconditions The provider must not own any lab.
Postconditions The specified provider's role is revoked if conditions are met.
Events Emits an {ProviderRemoved} event if the provider is successfully removed.
Description
Use case UPDATE PROVIDER
Definition function updateProvider(string memory _name, string memory _email, string memory _country) external onlyRole(PROVIDER_ROLE)
Actors Provider
Purpose Updates the provider information for the caller, modifying their name, email, and country details.
Summary Only a provider can update their own information.
Preconditions The caller must be an existing provider.
Postconditions The provider's information is updated with the new details provided.
Events Emits an {ProviderUpdated} event if the provider is successfully updated.

🔍 View Functions

The functions listed below are queries that do not modify the state of the variables:

Function Name Definition Purpose Return Type
isLabProvider function isLabProvider(address _account) external view returns (bool) Checks if the given account is a lab provider. bool
getLabProviders function getLabProviders() external view returns (Provider[] memory) Retrieves the list of all lab providers. Provider array

📢 Events

The following table lists the events emitted by ProviderFacet.

Event Description Parameters
ProviderAdded Emitted when a new provider is added to the system.

(address _account) Address of the provider
(string _name) Name of the provider
(string _email) Email address
(string _country) Country

ProviderAddedWithoutTokens Emitted when a provider is added but the initial token mint fails (e.g., supply cap reached)

(address _account) Address of the provider
(string _reason) Reason why the lab provider didn't received tokens

ProviderRemoved Emitted when a provider is removed. (address _account) Address of the provider
ProviderUpdated Emitted when a provider's information is updated.

(address _account) Address of the provider
(string _name) Name of the provider
(string _email) Email address
(string _country) Country

💎 LabFacet:

Description
Use case INITIALIZE
Definition function initialize(string memory _name, string memory _symbol) public initializer
Actors Contract owner
Purpose Sets up the ERC721 token with the provided name and symbol, and initializes the labId to 0.
Summary Only the contract owner can initialize the contract
Preconditions Have a WALLET and sufficient funds. Can only be executed once
Postconditions The ERC721 token associated with de labs is initializes
Description
Use case ADD LAB
Definition function addLab(string memory _uri, uint96 _price, string memory _auth, string memory _accessURI, string memory _accessKey) external isLabProvider
Actors Providers
Purpose Allows the contract provider to add a new lab with the on-chain stored metadata
Summary Only a provider can add a new lab
Preconditions Caller must be the lab provider
Postconditions A new lab is registered with the given metadata
Events Emits a {LabAdded} event if successful
Description
Use case SET TOKEN URI
Definition function setTokenURI(uint256 _labId, string memory _tokenURI) external
Actors Providers
Purpose Allows the lab provider to set or update the URI for a specific lab ID
Summary Only the lab provider can modify the lab URI
Preconditions Caller must be the lab provider; the lab ID must exist
Postconditions The specified lab's URI is updated
Events Emits a {LabURISet} event if successful
Description
Use case UPDATE LAB
Definition function updateLab(uint _labId, string memory _uri, uint96 _price, string memory _auth, string memory _accessURI, string memory _accessKey) external onlyLabProvider(_labId)
Actors Provider
Purpose Allows the lab provider to update the on-chain stored metadata of an existing lab
Summary Only the lab provider can modify lab details
Preconditions Caller must be the lab provider; lab ID must exist
Postconditions The specified lab's metadata are updated
Events Emits a {LabUpdated} event if successful
Description
Use case DELETE LAB
Definition function deleteLab(uint _labId) external onlyLabProvider(_labId)
Actors Providers
Purpose Allows the lab provider to delete an existing lab
Summary Only the lab provider can remove a lab
Preconditions Caller must be the lab provider; lab ID must exist and be removable
Postconditions The specified lab is removed from the system
Events Emits a {LabDeleted} event if successful

🔍 View Functions

The functions listed below are queries that do not modify the state of the variables:

Function Name Definition Purpose Return Type
getLab function getLab(uint _labId) public view returns (Lab memory) Retrieves the lab associated with the given lab ID. Lab
getAllLabs function getAllLabs() public view returns (uint256[] memory) Retrieves the list of the all labs ID. ID (uint256) array
tokenURI function tokenURI(uint256 _labId) public view returns (string memory) Retrieves the URI associated with a specific lab ID. URI string

📢 Events

The following table lists the events emitted by the LabFacet.

Event Description Parameters
LabAdded Emitted when a new lab is added to the system.

(uint256 _labId) Lab identifier
(address _provider) Provider address
(string _uri) Metadata URI
(uint96 _price) Lab price
(string _auth) Authorization details
(string _accessURI) Access URI
(string _accessKey) Access key

LabUpdated Emitted when a lab is updated.

(uint256 _labId) Lab identifier
(string _uri) Updated URI
(uint96 _price) Updated price
(string _auth) Updated auth
(string _accessURI) Updated access URI
(string _accessKey) Updated access key

LabDeleted Emitted when a lab is deleted.

(uint256 _labId) Lab identifier

LabURISet Emitted when the URI of a lab is set.

(uint256 _labId) Lab identifier
(string _uri) URI of the lab

💎 ReservationFacet:

Description
Use case RESERVATION REQUEST
Definition function reservationRequest(uint256 _labId, uint32 _start, uint32 _end) external exists(_labId) override
Actors Users
Purpose Initiates a new reservation request
Summary Creates a reservation request with specified details
Preconditions The lab must exists
Postconditions Reservation state is updated to PENDING
Events {ReservationRequested}
Description
Use case CONFIM RESERVATION REQUEST
Definition function confimReservationRequest(bytes32 _reservationKey) external defaultAdminRole reservationPending(_reservationKey) override
Actors Providers or authorized account
Purpose Confirm and book the reservation
Summary Creates a reservation request with specified details
Preconditions Caller must be the lab provider (for now, the DEFAULT_ADMIN_ROLE)
Postconditions State is updated to BOOKED
Events Emits a {ReservationConfirmed} event if successful
Description
Use case DENY RESERVATION REQUEST
Definition function denyReservationRequest(bytes32 _reservationKey) external defaultAdminRole reservationPending(_reservationKey) override
Actors Providers or authorized account
Purpose Denies a pending reservation request
Summary Reservation request is marked as denied
Preconditions Caller must be the lab provider (for now, the DEFAULT_ADMIN_ROLE)
Postconditions State is updated to CANCELLED
Events Emits a {ReservationRequestDenied} event if successful
Description
Use case CANCEL RESERVATION REQUEST
Definition function cancelReservationRequest(bytes32 _reservationKey) external override
Actors Users
Purpose Allows cancellation of an existing reservation
Summary Cancels an active reservation
Preconditions Caller must be the renter
Postconditions State is updated to CANCELLED
Events Emits a {ReservationRequestCanceled} event if successful
Description
Use case CANCEL BOOKING
Definition function cancelBooking(bytes32 _reservationKey) external override
Actors Users, providers
Purpose Allows cancellation of an existing booking
Summary Cancels an active booking
Preconditions Caller must be the renter or the lab provider
Postconditions State is updated to CANCELLED
Events Emits a {BookingCanceled} event if successful
Description
Use case REQUEST FUNDS
Definition function requestFunds() external isLabProvider
Actors Providers
Purpose Allows lab providers to claim funds from used or expired reservations
Summary Creates a reservation request with specified details
Preconditions Caller must be a registered lab provider
Postconditions Transfers the total amount of $LAB tokens from all eligible reservations to the provider
Events None

🔍 View Functions

The functions listed below are queries that do not modify the state of the variables:

Function Name Definition Purpose Return Type
getLabTokenAddress function getLabTokenAddress() external view returns (address) Returns the address of the $LAB ERC20 token
getSafeBalance function getSafeBalance() public view returns (uint256) Returns the current balance of Lab tokens held by this contract uint256

📢 Events

The following table lists the events emitted by the ProviderFacet.

Event Description Parameters
ReservationRequested Emitted when a user submits a new reservation request.

(address) renter

(uint256) tokenId
(uint256) start
(uint256) end
(bytes32) reservationKey

ReservationConfirmed Emitted when a reservation request is confirmed.

(bytes32) reservationKey

(uint256) tokenId

ReservationRequestDenied Emitted when a reservation request is denied.

(bytes32) reservationKey

(uint256) tokenId

ReservationRequestCanceled Emitted when a reservation request is canceled by the user.

(bytes32) reservationKey

(uint256) tokenId

BookingCanceled Emitted when a confirmed booking is canceled.

(bytes32) reservationKey

(uint256) tokenId

LabListed Emitted when a lab is listed

(uint256) tokenId

(address) owner

LabUnlisted Emitted when a lab is unlisted

(uint256) tokenId

(address) owner

💳 Token Integration

The project uses a dedicated ERC-20 token: $LAB for all transactions. The token is deployed outside the diamond proxy.

About

Specification for the smart contracts used in DecentraLabs

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Contributors 2

  •  
  •