Skip to content
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
59 changes: 34 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,57 @@

# BCA Service Token
# BCA Market for Tokenized Services

### Version: 2024-10-02
### Copyright: 2024 Alexander Diemand
### [License](./LICENSE): GPLv3 - GNU GENERAL PUBLIC LICENSE Version 3
#### Version: 2024-11-23
#### Copyright: 2024 Alexander Diemand
#### [License](./LICENSE): GPLv3 - GNU GENERAL PUBLIC LICENSE Version 3

## Documentation

[see documentation](./doc/README.md)


## Overview

This project is an evaluation of how to use ERC20 tokens on a blockchain to charge users for their usage of our services in micro-payments without incurring massive transaction fees.
Such a setup shows large flexibility in creating new services and shows great potential for revenue streams from micro-payments.
Users benefit from keeping control over their budget of service usage costs and only expose a minimal stake at any time.
Charging for services is done transparently on-chain.
The user with a positive token balance has access to an agent that helps funding service usage: by time, using fixed budget, ...
We are developing the tokenization of services and have them managed on a blockchain with smart contracts.

The contracts' behaviour is defined by a fixed set of parameters.

### Why call the internal token GEEZ?
Our services can be compared to mice which need some cheese from time to time to make them happy.
We might call that GEEZ (GEZ), similar to Ethereum's GAS.
Our product creates a market for tokenized services and brings users and service providers together.

![Overview](./doc/img/service_contract.png)

## Principles & Ideas

- there is an on-chain service token (probably named "BCA") and an internal token (named "GEEZ") for micropayments
- users aquire the service token using a fiat on-ramp service
- we mint new tokens to the user on payment in fiat. Later: they might also pay in crypto to some smart contract
- users own the service tokens and can see them in their wallets
- before using a service, users transfer a small amount of service tokens to the service's address
- A GEEZ record of the user's tokens is kept in our database linked to the sender. Proof is the on-chain transaction
- service usage by the user will be deducte from the user's GEEZ account
- (this part could be solved in our own L2 network, one day)
- users can see their GEEZ balance and transactions in a dashboard
- users can optionally add monitoring to their GEEZ budget: as soon as it drops below a certain level, then an email is sent to them asking for refunding
- micropayments in a stable-coin (EUR, USD)
- alternative: ERC20 token pegged to a currency, on/off-ramp from/to fiat
- users keep their funds in their wallets, and only commit a small amount in deposits to the service contract
- optionally, users can subscribe to a bot that deposits every 24 hours the required funds to keep services running
- at any time either the user or the provider can call stop() and the contract halts
- at any time both the user and the provider can withdraw funds from the service contract: up to the calculated balance at the current block time
- the contracts store the necessary information and thus no party relies on a centralized backend for operations

## Micropayments and balance calculation

The service contract is created with a set of parameters which are fixed for the lifetime of the contract.

The calculation of the user's and provider's balances depend on the contracts start time and the current time, taken from the latest block.

Once the user makes her first deposit, the contract starts. Multiple deposits can be made by the user. And, both parties can withdraw up to their calculated balance.

![User and provider balance in the contract](./doc/img/service_micropayment.png)

## Solidity contract and testing
## Solidity contracts and testing

see [README](./bca-token-solidity/README.md) in directory [./bca-token-solidity](./bca-token-solidity/)

## Frontend to interact with service contracts

Both users and providers connect to this user interface to interact with the service contracts.

see [README](./bca-token-market/README.md) in directory [./bca-token-market](./bca-token-market/)


## Frontend for minting/burning of tokens

see [README](./bca-token-app/README.md) in directory [./bca-token-app](./bca-token-app/)
Developping and testing is done using our own ERC20 token that mimics a stable-coin.

see [README](./bca-token-app/README.md) in directory [./bca-token-app](./bca-token-app/)
2 changes: 1 addition & 1 deletion bca-token-solidity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ in one terminal start a node:
```sh
npx hardhat node
```
in the other deploy the contract
in the other deploy the contracts
```sh
npx hardhat ignition deploy ignition/modules/BCA_Token.ts --network localhost
npx hardhat ignition deploy ignition/modules/BCA_ServiceManager.ts --network localhost
Expand Down
185 changes: 185 additions & 0 deletions doc/Contracts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Smart contracts

## Contract: BCAServiceToken

This contract implements an ERC20 token following the definitions from OpenZeppelin:

Source file: [BCA_ERC20_nf.sol](../bca-token-solidity/contracts/BCA_ERC20_nf.sol)

Implements interfaces:
- `import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"`
- the `constructor(string memory setName, string memory setSymbol, address setMinter, address setBurner)`

- `import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"`
- implements access control
- we restrict minting to the indicated minter address as given to the constructor of updated using `setMinterAddress()`
- we restrict burning to the indicated burner address as given to the constructor of updated using `setBurnerAddress()`

The contract has public fields:
- `address public serviceAddress`
- `address public minterAddress`
- `address public burnerAddress`

## Contract: BCAServiceManager

The service manager contract is at the top of the hierarchy of contracts and serves as an entry point. It is parameterized by the ERC20 or stable-coin address that is used throughout the dependent contracts. It stores the addresses of provider controller contracts.

Source file: [BCA_ServiceManager.sol](../bca-token-solidity/contracts/BCA_ServiceManager.sol)

Implements interfaces:
- [IServiceManager](../bca-token-solidity/contracts/Iface_ServiceManager.sol)
- [ReentrancyGuard](https://docs.openzeppelin.com/contracts/4.x/api/security#ReentrancyGuard)

The contract has public fields:
- `IERC20 public immutable tokToken`
* address of the ERC20 token as stable-coin
- `address[] public providerControllers`
* array of addresses of linked service controllers (see [BCA_ServiceController.sol](#bca_servicecontrollersol))
- `mapping (address => ControllerStruct) public deployedControllers`
* mapping of a provider's address to the setup controller
* ControllerStruct is:
```sol
struct ControllerStruct {
address addrContract;
bool isDeployed;
}
```

The contract has public methods:
- `constructor(address tokAddress)`
* only parameter is the common ERC20/stable-coin
- `function getControllerAddress(address providerAddress) public view returns(address addrController)`
* returns the controller address for a provider's address
- `function isDeployed(address providerAddress) public view returns(bool isdeployed)`
* returns true when the controller is deployed
- `function newController(address providerAddress) external nonReentrant`
* deploys a provider's controller
- `function countServiceControllers() public view returns (uint)`
* returns the number of known controllers by this service manager

## Contract: BCAServiceController

The service controller contract is deployed for every provider.
It keeps a list of addresses for the services that the provider offers.

Source file: [BCA_ServiceController.sol](../bca-token-solidity/contracts/BCA_ServiceController.sol)

Implements interfaces:
- [IServiceController](../bca-token-solidity/contracts/Iface_ServiceController.sol)
- [ReentrancyGuard](https://docs.openzeppelin.com/contracts/4.x/api/security#ReentrancyGuard)

The contract has public fields:
- `IERC20 public immutable tokToken`
* the common ERC20 or stable-coin
- `address public immutable providerAddress`
* the provider's address
- `address[] public deployedServices`
* an array of linked services

The contract has public methods:
- `constructor(address setProviderAddress, address tokAddress)`
- `function newService(uint16 maxInstances, uint256 dayPrice) external nonReentrant returns (address)`
* deploys a new service contract with the given parameterization
- `function countServiceContracts() public view returns (uint)`
* returns the number of services in the array, necessary to enumerate the array entries

## Contract: BCAService

A service references a provider and the common ERC20/stable-coin and is parameterized with the maximal number of instances and the price of the service per day.

Source file: [BCA_Service.sol](../bca-token-solidity/contracts/BCA_Service.sol)

Implements interfaces:
- [IService](../bca-token-solidity/contracts/Iface_Service.sol)
- [ReentrancyGuard](https://docs.openzeppelin.com/contracts/4.x/api/security#ReentrancyGuard)

The contract has public fields:
- `IERC20 public immutable tokToken`
- `uint256 public immutable dayPrice`
- `address public immutable providerAddress`
- `uint16 public immutable maxInstances`
- `address[] public deployedInstances`

The contract has public methods:
- `constructor(address setProviderAddress, address tokAddress,
uint16 setMaxInstances, uint256 setDayPrice)`
- `function newInstance(address userAddress) external nonReentrant returns (address)`
- `function countServiceInstances() public view returns (uint)`

## Contract: BCAServiceInstance

This contract is at the heart of the market and represents a service instance. A user subscribes to a service with a first deposit of funds. This sets the start time of the contract from which the balances are calculated.

Source file: [BCA_ServiceInstance.sol](../bca-token-solidity/contracts/BCA_ServiceInstance.sol)

Implements interfaces:
- [IServiceInstance](../bca-token-solidity/contracts/Iface_ServiceInstance.sol)
- [ReentrancyGuard](https://docs.openzeppelin.com/contracts/4.x/api/security#ReentrancyGuard)

The contract has public fields:
- `IERC20 public immutable tokToken`
* the common ERC20/stable-coin
- `uint256 public immutable dayPrice`
* the price of the service for 24 hours; minimizes rounding errors
- `address public immutable providerAddress`
* the address of the provider
- `address public immutable userAddress`
* the address of the user
- `uint256 public deposit`
* the amount of deposits made by the user
- `uint256 public retracted`
* the amount of withdrawals made by the provider
- `uint256 public startTime`
* when the contract has been started
- `uint256 public endTime`
* when it has been stopped

The contract has public methods:
- `constructor(address setProviderAddress, address tokAddress,
address setUserAddress,
uint256 setDayPrice)`
- `function makeDeposit(uint256 amount) external nonReentrant`
* deposits can only be made from the user's address
- `function stop() external nonReentrant`
* both parties may call stop() at any time
- `function balanceUser() public view returns (uint256)`
* calculates the user's balance
- `function balanceProvider() public view returns (uint256)`
* calculates the provider's balance
- `function withdrawUser(uint256 amount) external nonReentrant`
* the user may withdraw from his balance; this will affect the deposit
- `function withdrawProvider(uint256 amount) external nonReentrant`
* the provider may withdraw up to his calculated balance


## Contract: BCAServiceFunding24

This contract automates the funding of a service contract by transferring the required funds to run the service every 24 hours. The contract is guaranteed to only transfer the said amount at most every 24 hours. It requires an external transaction to `deposit()` which is sent from a bot.

Source file: [BCA_Funding24.sol](../bca-token-solidity/contracts/BCA_Funding24.sol)

Implements interfaces:
- [IFunding24](../bca-token-solidity/contracts/Iface_Funding24.sol)
- [Ownable](https://docs.openzeppelin.com/contracts/4.x/api/access#Ownable)

The contract has public fields:
- `address public immutable targetContract`
* the target contract
- `uint256 public immutable dailyAmount`
* the amount to deposit every 24 hours
- `IERC20 public immutable token`
* the common ERC20/stable-coin
- `uint256 public lastDepositTime`
* remembers the last time a deposit was made

The contract has public methods:
- `constructor(
address initialOwner,
address setTargetContract,
address setToken,
uint256 setDailyAmount`
* the parameterization of the contract is done in the constructor. The owner is set to the service user.
- `function deposit() external`
* this method triggers the transfer of funds and makes the deposit to the service contract
- `function canDeposit() external view returns (bool)`
* returns true if a deposit can be make
30 changes: 30 additions & 0 deletions doc/Deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Deployment

Depending on the target chain, we run for deployment of the contracts:

## Deploy to local node

First, run a node in another terminal:
```sh
cd bca-token-solidity
npx hardhat compile
npx hardhat node
```

* if this our first run of the node, then we can import the list of output accounts into MetaMask
* in other cases it might be necessary to "clear activity" in MetaMask for these accounts so it resyncs with the node and starts with the first block

Then, deploy the ERC20 contract along with the service manager contract:

```sh
npx hardhat ignition deploy ignition/modules/BCA_Token.ts --network localhost
npx hardhat ignition deploy ignition/modules/BCA_ServiceManager.ts --network localhost
```

## Deploy to Amoy testnet

- tbd

## Deploy to Polygon mainnet

- tbd
12 changes: 12 additions & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
[Service Tokenization](./Tokenization.md)


## The smart contracts

[Smart contracts](./Contracts.md)


## The transactions involved

[Transaction Flow](./Flow.md)
Expand All @@ -14,6 +19,13 @@

[Services](./Services.md)

## Testing and estimating Gas costs

[Testing](./Testing.md)

## Deployment

[Deployment](./Deployment.md)

## User authentication

Expand Down
Loading
Loading