manual developer section update
@@ -1,94 +0,0 @@
|
||||
<h1> Farming Policies </h1>
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Farming Policy Fields](#farming-policy-fields)
|
||||
- [Limits on linked policy](#limits-on-linked-policy)
|
||||
- [Creating a Policy](#creating-a-policy)
|
||||
- [Linking a policy to a Farm](#linking-a-policy-to-a-farm)
|
||||
|
||||
***
|
||||
|
||||
## Introduction
|
||||
|
||||
A farming policy defines how farming rewards are handed out for nodes. Every node has a farming policy attached. A farming policy is either linked to a farm, in which case new nodes are given the farming policy of the farm they are in once they register themselves. Alternatively a farming policy can be a "default". These are not attached to a farm, but instead they are used for nodes registered in farms which don't have a farming policy. Multiple defaults can exist at the same time, and the most fitting should be chosen.
|
||||
|
||||
## Farming Policy Fields
|
||||
|
||||
A farming policy has the following fields:
|
||||
|
||||
- id (used to link policies)
|
||||
- name
|
||||
- Default. This indicates if the policy can be used by any new node (if the parent farm does not have a dedicated attached policy). Essentially, a `Default` policy serves as a base which can be overriden per farm by linking a non default policy to said farm.
|
||||
- Reward tft per CU, SU and NU, IPV4
|
||||
- Minimal uptime needed in integer format (example 995)
|
||||
- Policy end (After this block number the policy can not be linked to new farms any more)
|
||||
- If this policy is immutable or not. Immutable policies can never be changed again
|
||||
|
||||
Additionally, we also use the following fields, though those are only useful for `Default` farming policies:
|
||||
|
||||
- Node needs to be certified
|
||||
- Farm needs to be certified (with certification level, which will be changed to an enum).
|
||||
|
||||
In case a farming policy is not attached to a farm, new nodes will pick the most appropriate farming policy from the default ones. To decide which one to pick, they should be considered in order with most restrictive first until one matches. That means:
|
||||
|
||||
- First check for the policy with highest farming certification (in the current case gold) and certified nodes
|
||||
- Then check for a policy with highest farming certification (in the current case gold) and non certified nodes
|
||||
- Check for policy without farming certification but certified nodes
|
||||
- Last check for a policy without any kind of certification
|
||||
|
||||
Important here is that certification of a node only happens after it comes live for the first time. As such, when a node gets certified, farming certification needs to be re evaluated, but only if the currently attached farming policy on the node is a `Default` policy (as specifically linked policies have priority over default ones). When evaluating again, we first consider if we are eligible for the farming policy linked to the farm, if any.
|
||||
|
||||
## Limits on linked policy
|
||||
|
||||
When a council member attaches a policy to a farm, limits can be set. These limits define how much a policy can be used for nodes, before it becomes unusable and gets removed. The limits currently are:
|
||||
|
||||
- Farming Policy ID: the ID of the farming policy which we want to limit to a farm.
|
||||
- CU. Every time a node is added in the farm, it's CU is calculated and deducted from this amount. If the amount drops below 0, the maximum amount of CU that can be attached to this policy is reached.
|
||||
- SU. Every time a node is added in the farm, it's SU is calculated and deducted from this amount. If the amount drops below 0, the maximum amount of SU that can be attached to this policy is reached.
|
||||
- End date. After this date the policy is not effective anymore and can't be used. It is removed from the farm and a default policy is used.
|
||||
- Certification. If set, only certified nodes can get this policy. Non certified nodes get a default policy.
|
||||
|
||||
Once a limit is reached, the farming policy is removed from the farm, so new nodes will get one of the default policies until a new policy is attached to the farm.
|
||||
|
||||
## Creating a Policy
|
||||
|
||||
A council member can create a Farming Policy (DAO) in the following way:
|
||||
|
||||
1: Open [PolkadotJS](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Ftfchain.grid.tf#/extrinsics) apps on the corresponding network and go to `Extrinsics`
|
||||
2: Now select the account to propose from (should be an account that's a council member).
|
||||
3: Select as action `dao` -> `propose`
|
||||
5: Set a `threshold` (amount of farmers to vote)
|
||||
6: Select an actions `tfgridModule` -> `createFarmingPolicy` and fill in all the fields.
|
||||
7: Create a forum post with the details of the farming policy and fill in the link of that post in the `link` field
|
||||
8: Give it some good `description`.
|
||||
9: Duration is optional (by default it's 7 days). A proposal cannot be closed before the duration is "expired". If you wish to set a duration, the duration should be expressed in number of blocks from `now`. For example, 2 hours is equal to 1200 blocks (blocktime is 6 seconds) in this case, the duration should be filled in as `1200`.
|
||||
10: If all the fields are filled in, click `Propose`, now Farmers can vote. A proposal can be closed manually once there are enough votes AND the proposal is expired. To close go to extrinsics -> `dao` -> `close` -> fill in proposal hash and index (both can be found in chainstate).
|
||||
|
||||
All (su, cu, nu, ipv4) values should be expressed in units USD. Minimal uptime should be expressed as integer that represents an percentage (example: `95`).
|
||||
|
||||
Policy end is optional (0 or some block number in the future). This is used for expiration.
|
||||
|
||||
For reference:
|
||||
|
||||

|
||||
|
||||
## Linking a policy to a Farm
|
||||
|
||||
First identify the policy ID to link to a farm. You can check for farming policies in [chainstate](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Ftfchain.grid.tf#/chainstate) -> `tfgridModule` -> `farmingPolciesMap`, start with ID 1 and increment with 1 until you find the farming policy which was created when the proposal was expired and closed.
|
||||
|
||||
1: Open [PolkadotJS](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Ftfchain.grid.tf#/extrinsics) apps on the corresponding network and go to `Extrinsics`
|
||||
2: Now select the account to propose from (should be an account that's a council member).
|
||||
3: Select as proposal `dao` -> `propose`
|
||||
4: Set a `threshold` (amount of farmers to vote)
|
||||
5: Select an actions `tfgridModule` -> `attachPolicyToFarm` and fill in all the fields (FarmID and Limits).
|
||||
6: Limits contains a `farming_policy_id` (Required) and cu, su, end, node count (which are all optional). It also contains `node_certification`, if this is set to true only certified nodes can have this policy.
|
||||
7: Create a forum post with the details of why we want to link that farm to that policy and fill in the link of that post in the `link` field
|
||||
8: Give it some good `description`.
|
||||
9: Duration is optional (by default it's 7 days). A proposal cannot be closed before the duration is "expired". If you wish to set a duration, the duration should be expressed in number of blocks from `now`. For example, 2 hours is equal to 1200 blocks (blocktime is 6 seconds) in this case, the duration should be filled in as `1200`.
|
||||
10: If all the fields are filled in, click `Propose`, now Farmers can vote. A proposal can be closed manually once there are enough votes AND the proposal is expired. To close go to extrinsics -> `dao` -> `close` -> fill in proposal hash and index (both can be found in chainstate).
|
||||
|
||||
For reference:
|
||||
|
||||

|
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 200 KiB |
Before Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 198 KiB |
Before Width: | Height: | Size: 169 KiB |
Before Width: | Height: | Size: 280 KiB |
Before Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 185 KiB |
Before Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 128 KiB |
@@ -1,57 +0,0 @@
|
||||
<h1>ThreeFold Chain</h1>
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Deployed instances](#deployed-instances)
|
||||
- [Create a TFChain twin](#create-a-tfchain-twin)
|
||||
- [Get your twin ID](#get-your-twin-id)
|
||||
|
||||
***
|
||||
|
||||
## Introduction
|
||||
|
||||
ThreeFold blockchain (aka TFChain) serves as a registry for Nodes, Farms, Digital Twins and Smart Contracts.
|
||||
It is the backbone of [ZOS](https://github.com/threefoldtech/zos) and other components.
|
||||
|
||||
## Deployed instances
|
||||
|
||||
- Development network (Devnet):
|
||||
|
||||
- Polkadot UI: [https://polkadot.js.org/apps/?rpc=wss%3A%2F%2F/tfchain.dev.grid.tf#/explorer](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2F/tfchain.dev.grid.tf#/explorer)
|
||||
- Websocket url: `wss://tfchain.dev.grid.tf`
|
||||
- GraphQL UI: [https://graphql.dev.grid.tf/graphql](https://graphql.dev.grid.tf/graphql)
|
||||
|
||||
- QA testing network (QAnet):
|
||||
|
||||
- Polkadot UI: [https://polkadot.js.org/apps/?rpc=wss%3A%2F%2F/tfchain.qa.grid.tf#/explorer](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2F/tfchain.qa.grid.tf#/explorer)
|
||||
- Websocket url: `wss://tfchain.qa.grid.tf`
|
||||
- GraphQL UI: [https://graphql.qa.grid.tf/graphql](https://graphql.qa.grid.tf/graphql)
|
||||
|
||||
- Test network (Testnet):
|
||||
|
||||
- Polkadot UI: [https://polkadot.js.org/apps/?rpc=wss%3A%2F%2F/tfchain.test.grid.tf#/explorer](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2F/tfchain.test.grid.tf#/explorer)
|
||||
- Websocket url: `wss://tfchain.test.grid.tf`
|
||||
- GraphQL UI: [https://graphql.test.grid.tf/graphql](https://graphql.test.grid.tf/graphql)
|
||||
|
||||
- Production network (Mainnet):
|
||||
|
||||
- Polkadot UI: [https://polkadot.js.org/apps/?rpc=wss%3A%2F%2F/tfchain.grid.tf#/explorer](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2F/tfchain.grid.tf#/explorer)
|
||||
- Websocket url: `wss://tfchain.grid.tf`
|
||||
- GraphQL UI: [https://graphql.grid.tf/graphql](https://graphql.grid.tf/graphql)
|
||||
|
||||
## Create a TFChain twin
|
||||
|
||||
A twin is a unique identifier linked to a specific account on a given TFChain network.
|
||||
Actually there are 2 ways to create a twin:
|
||||
|
||||
- With the [Dashboard](../../dashboard/wallet_connector.md)
|
||||
- a twin is automatically generated while creating a TFChain account
|
||||
- With the TFConnect app
|
||||
- a twin is automatically generated while creating a farm (in this case the twin will be created on mainnet)
|
||||
|
||||
## Get your twin ID
|
||||
|
||||
One can retrieve the twin ID associated to his account going to `Developer` -> `Chain state` -> `tfgridModule` -> `twinIdByAccountID()`.
|
||||
|
||||

|
@@ -1,95 +0,0 @@
|
||||
<h1> ThreeFold Chain <h1>
|
||||
|
||||
<h2> Table of Contents </h2>
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Twins](#twins)
|
||||
- [Farms](#farms)
|
||||
- [Nodes](#nodes)
|
||||
- [Node Contract](#node-contract)
|
||||
- [Rent Contract](#rent-contract)
|
||||
- [Name Contract](#name-contract)
|
||||
- [Contract billing](#contract-billing)
|
||||
- [Contract locking](#contract-locking)
|
||||
- [Contract grace period](#contract-grace-period)
|
||||
- [DAO](#dao)
|
||||
- [Farming Policies](#farming-policies)
|
||||
- [Node Connection price](#node-connection-price)
|
||||
- [Node Certifiers](#node-certifiers)
|
||||
|
||||
***
|
||||
|
||||
## Introduction
|
||||
|
||||
ThreeFold Chain (TFChain) is the base layer for everything that interacts with the grid. Nodes, farms, users are registered on the chain. It plays the central role in achieving decentralised consensus between a user and Node to deploy a certain workload. A contract can be created on the chain that is essentially an agreement between a node and user.
|
||||
|
||||
## Twins
|
||||
|
||||
A twin is the central Identity object that is used for every entity that lives on the grid. A twin optionally has an IPV6 planetary network address which can be used for communication between twins no matter of the location they are in. A twin is coupled to a private/public keypair on chain. This keypair can hold TFT on TF Chain.
|
||||
|
||||
## Farms
|
||||
|
||||
A farm must be created before a Node can be booted. Every farms needs to have an unique name and is linked to the Twin that creates the farm. Once a farm is created, a unique ID is generated. This ID can be used to provide to the boot image of a Node.
|
||||
|
||||
## Nodes
|
||||
|
||||
When a node is booted for the first time, it registers itself on the chain and a unique identity is generated for this Node.
|
||||
|
||||
## Node Contract
|
||||
|
||||
A node contract is a contract between a user and a Node to deploy a certain workload. The contract is specified as following:
|
||||
|
||||
```
|
||||
{
|
||||
"contract_id": auto generated,
|
||||
"node_id": unique id of the node,
|
||||
"deployment_data": some additional deployment data
|
||||
"deployment_hash": hash of the deployment definition signed by the user
|
||||
"public_ips": number of public ips to attach to the deployment contract
|
||||
}
|
||||
```
|
||||
|
||||
We don't save the raw workload definition on the chain but only a hash of the definition. After the contract is created, the user must send the raw deployment to the specified node in the contract. He can find where to send this data by looking up the Node's twin and contacting that twin over the planetary network.
|
||||
|
||||
## Rent Contract
|
||||
|
||||
A rent contract is also a contract between a user and a Node, but instead of being able to reserve a part of the node's capacity, the full capacity is rented. Once a rent contract is created on a Node by a user, only this user can deploy node contracts on this specific node. A discount of 50% is given if a the user wishes to rent the full capacity of a node by creating a rent contract. All node contracts deployed on a node where a user has a rent contract are free of use expect for the public ip's which can be added on a node contract.
|
||||
|
||||
## Name Contract
|
||||
|
||||
A name contract is a contract that specifies a unique name to be used on the grid's webgateways. Once a name contract is created, this name can be used as and entrypoint for an application on the grid.
|
||||
|
||||
## Contract billing
|
||||
|
||||
Every contract is billed every 1 hour on the chain, the amount that is due is deducted from the user's wallet every 24 hours or when the user cancels his contract. The total amount acrued in those 24 hours gets send to following destinations:
|
||||
|
||||
- 10% goes to the threefold foundation
|
||||
- 5% goes to staking pool wallet (to be implemented in a later phase)
|
||||
- 50% goes to certified sales channel
|
||||
- 35% TFT gets burned
|
||||
|
||||
See [pricing](../../../knowledge_base/cloud/pricing/pricing.md) for more information on how the cost for a contract is calculated.
|
||||
|
||||
## Contract locking
|
||||
|
||||
To not overload the chain with transfer events and others we choose to lock the amount due for a contract every hour and after 24 hours unlock the amount and deduct it in one go. This lock is saved on a user's account, if the user has multiple contracts the locked amount will be stacked.
|
||||
|
||||
## Contract grace period
|
||||
|
||||
When the owner of a contract runs out funds on his wallet to pay for his deployment, the contract goes in to a Grace Period state. The deployment, whatever that might be, will be unaccessible during this period to the user. When the wallet is funded with TFT again, the contract goes back to a normal operating state. If the grace period runs out (by default 2 weeks) the user's deployment and data will be deleted from the node.
|
||||
|
||||
## DAO
|
||||
|
||||
See [DAO](../../dashboard/tfchain/tf_dao.md) for more information on the DAO on TF Chain.
|
||||
|
||||
## Farming Policies
|
||||
|
||||
See [farming_policies](farming_policies.md) for more information on the farming policies on TF Chain.
|
||||
|
||||
## Node Connection price
|
||||
|
||||
A connection price is set to every new Node that boots on the Grid. This connection price influences the amount of TFT farmed in a period. The connection price set on a node is permanent. The DAO can propose the increase / decrease of the connection price. At the time of writing the connection price is set to $ 0.08. When the DAO proposes a connection price and the vote is passed, new nodes will attach to the new connection price.
|
||||
|
||||
## Node Certifiers
|
||||
|
||||
Node certifiers are entities who are allowed to set a node's certification level to `Certified`. The DAO can propose to add / remove entities that can certify nodes. This is usefull for allowing approved resellers of Threefold nodes to mark nodes as Certified. A certified node farms 25% more tokens than `Diy` a node.
|
@@ -1,142 +0,0 @@
|
||||
<h1>External Service Contract: How to set and execute</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Step 1: Create the contract and get its unique ID](#step-1-create-contract--get-unique-id)
|
||||
- [Step 2: Fill contract](#step-2-fill-contract)
|
||||
- [Step 3: Both parties approve contract](#step-3-both-parties-approve-contract)
|
||||
- [Step 4: Bill for the service](#step-4-bill-for-the-service)
|
||||
- [Step 5: Cancel the contract](#step-5-cancel-the-contract)
|
||||
|
||||
***
|
||||
|
||||
|
||||
# Introduction
|
||||
|
||||
It is now possible to create a generic contract between two TFChain users (without restriction of account type) for some external service and bill for it.
|
||||
|
||||
The initial scenario is when two parties, a service provider and a consumer of the service, want to use TFChain to automatically handle the billing/payment process for an agreement (in TFT) they want to make for a service which is external from the grid.
|
||||
This is actually a more direct and generic feature if we compare to the initial rewarding model where a service provider (or solution provider) is receiving TFT from a rewards distribution process, linked to a node contract and based on a cloud capacity consumption, which follows specific billing rules.
|
||||
|
||||
The initial requirements are:
|
||||
- Both service and consumer need to have their respective twin created on TFChain (if not, see [here](tfchain.md#create-a-tfchain-twin) how to do it)
|
||||
- Consumer account needs to be funded (lack of funds will simply result in the contract cancelation while billed)
|
||||
|
||||
In the following steps we detail the sequence of extrinsics that need to be called in TFChain Polkadot portal for setting up and executing such contract.
|
||||
<!-- We also show how to check if everything is going the right way via the TFChain GraphQL interface. -->
|
||||
Make sure to use right [links](tfchain.md#deployed-instances) depending on the targeted network.
|
||||
|
||||
|
||||
# Step 1: Create contract / Get unique ID
|
||||
|
||||
## Create service contract
|
||||
|
||||
The contract creation can be initiated by both service or consumer.
|
||||
In TFChain Polkadot portal, the one who iniciates the contract should go to `Developer` -> `Extrinsics` -> `smartContractModule` -> `serviceContractCreate()`, using the account he pretends to use in the contract, and select the corresponding service and consumer accounts before submiting the transaction.
|
||||
|
||||

|
||||
|
||||
Once executed the service contract is `Created` between the two parties and a unique ID is generated.
|
||||
|
||||
## Last service contract ID
|
||||
|
||||
To get the last generated service contract ID go to `Developer` -> `Chain state` -> `smartContractModule` -> `serviceContractID()`.
|
||||
|
||||

|
||||
|
||||
## Parse service contract
|
||||
|
||||
To get the corresponding contract details, go to `Developer` -> `Chain state` -> `smartContractModule` -> `serviceContracts()` and provide the contract ID.
|
||||
You should see the following details:
|
||||
|
||||

|
||||
|
||||
Check if the contract fields are correct, especially the twin ID of both service and consumer, to be sure you get the right contract ID, referenced as `serviceContractId`.
|
||||
|
||||
## Wrong contract ID ?
|
||||
|
||||
If twin IDs are wrong ([how to get my twin ID?](tfchain.md#get-your-twin-id)) on service contract fields it means the contract does not correspond to the last created contract.
|
||||
In this case parse the last contracts on stack by decreasing `serviceContractId` and try to identify the right one; or the contract was simply not created so you should repeat the creation process and evaluate the error log.
|
||||
|
||||
|
||||
# Step 2: Fill contract
|
||||
|
||||
Once created, the service contract must be filled with its relative `per hour` fees:
|
||||
- `baseFee` is the constant "per hour" price (in TFT) for the service.
|
||||
- `variableFee` is the maximum "per hour" amount (in TFT) that can be billed extra.
|
||||
|
||||
To provide these values (only service can set fees), go to `Developer` -> `Extrinsics` -> `smartContractModule` -> `serviceContractSetFees()` specifying `serviceContractId`.
|
||||
|
||||

|
||||
|
||||
Some metadata (the description of the service for example) must be filled in a similar way (`Developer` -> `Extrinsics` -> `smartContractModule` -> `serviceContractSetMetadata()`).
|
||||
In this case service or consumer can set metadata.
|
||||
|
||||

|
||||
|
||||
The agreement will be automatically considered `Ready` when both metadata and fees are set (`metadata` not empty and `baseFee` greater than zero).
|
||||
Note that whenever this condition is not reached both extrinsics can still be called to modify agreement.
|
||||
You can check the contract status at each step of flow by parsing it as shown [here](#parse-service-contract).
|
||||
|
||||
|
||||
# Step 3: Both parties approve contract
|
||||
|
||||
Now having the agreement ready the contract can be submited for approval.
|
||||
To approve the agreement, go to `Developer` -> `Extrinsics` -> `smartContractModule` -> `serviceContractApprove()` specifying `serviceContractId`.
|
||||
|
||||

|
||||
|
||||
To reject the agreement, go to `Developer` -> `Extrinsics` -> `smartContractModule` -> `serviceContractReject()` specifying `serviceContractId`.
|
||||
|
||||

|
||||
|
||||
The contract needs to be explicitly `Approved` by both service and consumer to be ready for billing.
|
||||
Before reaching this state, if one of the parties decides to call the rejection extrinsic, it will instantly lead to the cancelation of the contract (and its permanent removal).
|
||||
|
||||
|
||||
# Step 4: Bill for the service
|
||||
|
||||
Once the contract is accepted by both it can be billed.
|
||||
|
||||
## Send bill to consumer
|
||||
|
||||
Only the service can bill the consumer going to `Developer` -> `Extrinsics` -> `smartContractModule` -> `serviceContractBill()` specifying `serviceContractId` and billing informations such as `variableAmount` and some `metadata`.
|
||||
|
||||

|
||||
|
||||
## Billing frequency
|
||||
|
||||
⚠️ Important: because a service should not charge the user if it doesn't work, it is required that bills be send in less than 1 hour intervals.
|
||||
Any bigger interval will result in a bounded 1 hour bill (in other words, extra time will not be billed).
|
||||
It is the service responsability to bill on right frequency!
|
||||
|
||||
## Amount due calculation
|
||||
|
||||
When the bill is received, the chain calculates the bill amount based on the agreement values as follows:
|
||||
|
||||
~~~
|
||||
amount = baseFee * T / 3600 + variableAmount
|
||||
~~~
|
||||
|
||||
where `T` is the elapsed time, in seconds and bounded by 3600 (see [above](#billing-frequency)), since last effective billing operation occured.
|
||||
|
||||
## Protection against draining
|
||||
|
||||
Note that if `variableAmount` is too high (i.e `variableAmount > variableFee * T / 3600`) the billing extrinsic will fail.
|
||||
The `variableFee` value in the contract is interpreted as being "per hour" and acts as a protection mechanism to avoid consumer draining.
|
||||
Indeed, as it is technically possible for the service to send a bill every second, there would be no gain for that (unless overloading the chain uselessly).
|
||||
So it is also the service responsability to set a suitable `variableAmount` according to the billing frequency!
|
||||
|
||||
## Billing considerations
|
||||
|
||||
Then, if all goes well and no error is dispatched after submitting the transaction, the consumer pays for the due amount calculated from the bill (see calculation detail [above](#amount-due-calculation)).
|
||||
In practice the amount is transferred from the consumer twin account to the service twin account.
|
||||
Be aware that if the consumer is out of funds the billing will fail AND the contract will automatically be canceled.
|
||||
|
||||
|
||||
# Step 5: Cancel the contract
|
||||
|
||||
At every moment of the flow since the contract is created it can be canceled (and definitively removed).
|
||||
Only the service or the consumer can do it going to `Developer` -> `Extrinsics` -> `smartContractModule` -> `serviceContractCancel()` specifying `serviceContractId`.
|
||||
|
||||

|
@@ -1,81 +0,0 @@
|
||||
<h1>Solution Provider</h1>
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Changes to Contract Creation](#changes-to-contract-creation)
|
||||
- [Creating a Provider](#creating-a-provider)
|
||||
- [Council needs to approve a provider before it can be used](#council-needs-to-approve-a-provider-before-it-can-be-used)
|
||||
|
||||
***
|
||||
|
||||
## Introduction
|
||||
|
||||
> Note: While the solution provider program is still active, the plan is to discontinue the program in the near future. We will update the manual as we get more information. We currently do not accept new solution providers.
|
||||
|
||||
A "solution" is something running on the grid, created by a community member. This can be brought forward to the council, who can vote on it to recognize it as a solution. On contract creation, a recognized solution can be referenced, in which case part of the payment goes toward the address coupled to the solution. On chain a solution looks as follows:
|
||||
|
||||
- Description (should be some text, limited in length. Limit should be rather low, if a longer one is desired a link can be inserted. 160 characters should be enough imo).
|
||||
- Up to 5 payout addresses, each with a payout percentage. This is the percentage of the payout received by the associated address. The amount is deducted from the payout to the treasury and specified as percentage of the total contract cost. As such, the sum of these percentages can never exceed 50%. If this value is not 50%, the remainder is payed to the treasure. Example: 10% payout percentage to addr 1, 5% payout to addr 2. This means 15% goes to the 2 listed addresses combined and 35% goes to the treasury (instead of usual 50). Rest remains as is. If the cost would be 10TFT, 1TFT goes to the address1, 0.5TFT goes to address 2, 3.5TFT goes to the treasury, instead of the default 5TFT to the treasury
|
||||
- A unique code. This code is used to link a solution to the contract (numeric ID).
|
||||
|
||||
This means contracts need to carry an optional solution code. If the code is not specified (default), the 50% goes entirely to the treasury (as is always the case today).
|
||||
|
||||
A solution can be created by calling the extrinsic `smartContractModule` -> `createSolutionProvider` with parameters:
|
||||
|
||||
- description
|
||||
- link (to website)
|
||||
- list of providers
|
||||
|
||||
Provider:
|
||||
|
||||
- who (account id)
|
||||
- take (amount of take this account should get) specified as an integer of max 50. example: 25
|
||||
|
||||
A forum post should be created with the details of the created solution provider, the dao can vote to approve this or not. If the solution provider get's approved, it can be referenced on contract creation.
|
||||
|
||||
Note that a solution can be deleted. In this case, existing contracts should fall back to the default behavior (i.e. if code not found -> default).
|
||||
|
||||
## Changes to Contract Creation
|
||||
|
||||
When creating a contract, a `solution_provider_id` can be passed. An error will be returned if an invalid or non-approved solution provider id is passed.
|
||||
|
||||
## Creating a Provider
|
||||
|
||||
Creating a provider is as easy as going to the [polkadotJS UI](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Ftfchain.dev.grid.tf#/extrinsics) (Currently only on devnet)
|
||||
|
||||
Select module `SmartContractModule` -> `createSolutionProvider(..)`
|
||||
|
||||
Fill in all the details, you can specify up to 5 target accounts which can have a take of the TFT generated from being a provider. Up to a total maximum of 50%. `Take` should be specified as a integer, example (`25`).
|
||||
|
||||
Once this object is created, a forum post should be created here: <https://forum.threefold.io/>
|
||||
|
||||

|
||||
|
||||
## Council needs to approve a provider before it can be used
|
||||
|
||||
First propose the solution to be approved:
|
||||
|
||||

|
||||
|
||||
After submission it should like like this:
|
||||
|
||||

|
||||
|
||||
Now another member of the council needs to vote:
|
||||
|
||||

|
||||
|
||||
After enough votes are reached, it can be closed:
|
||||
|
||||

|
||||
|
||||
If the close was executed without error the solution should be approved and ready to be used
|
||||
|
||||
Query the solution: `chainstate` -> `SmartContractModule` -> `solutionProviders`
|
||||
|
||||

|
||||
|
||||
Now the solution provider can be referenced on contract creation:
|
||||
|
||||

|