threefoldtech / tfchain

Threefold Chain.
Apache License 2.0
15 stars 11 forks source link

allow third party services to charge the user #445

Closed xmonader closed 1 year ago

xmonader commented 2 years ago

according to the erc20 interface

function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)

these functions support third party billing, where

LeeSmet commented 2 years ago

I'm not a fan of this. Erc20 is specifically meant for general purpose assets on top of ethereum, while TFT is already a native currency on tfchain. Furthermore, in this context, we use a contract to govern the payment between 2 parties. To this extend, I prefer the design and implementation of a GenericContract, which handles billing. This gives more control than the erc20 interface, and fits better in the current architecture.

Specifically, I'm thinking off something like this:

The above follows the trend of using contracts, which means after creation a user does not need to care anymore. Furthermore you can track easily per contract how much you pay over time, how much you can pay maximum, and you don't have to continuously increase your allowance for some 3rd party.

sameh-farouk commented 2 years ago

@xmonader @LeeSmet Here is another approach to be considered. Zos deployments work in a similar fashion I believe.

We can have a contract with pin method which takes a content hash and TFT amounts. pinning service would listen for that contract on-chain events, pins the hashes, and unpinned it when received another event that states TFT amount consumed.

This approach won't expose public pinning API. pinning and unpinning will mainly be done by listening to chain events.

We could also have a hybrid approach to make the API follow the specs of IPFS pinning service. like after sending the content hash to the pin contract we could return a unique token, which can be used by a pinning client to pin the same hash. the service will validate the token and the hash from the chain and then pin the content. the pinning period will depend on the content size and the amount of TFT deposited.

sasha-astiadi commented 2 years ago

@xmonader please put an assignee if already on 'accepted '

xmonader commented 2 years ago

@LeeSmet please prepare the specs for this and have consensus with @DylanVerstraete to move forward

LeeSmet commented 2 years ago

Since we don't want to do work on the chain for every possible 3rd party service, we will keep this as generic as possible. While custom implementations for services might offer small advantages in the flow, the extra effort to develop and most importantly maintain these implementations is not worth it compared to a proper generic flow which would technically also be reusable.

Contract structure

A contract will work simple client - server principle (i.e. the "buyer" and the "seller", a "consumer" of a service and one who "offers" the service). Both parties are identified by a twin id to fit in the current flow (we could use a generic address as well here). Contract is laid out as such

Additionally, we also keep track of some metadata, which will be:

Billing

Once a contract is accepted by both the consumer and the service, the chain can start accepting "bill reports" from the service for the contract. Only the twin of the service can send these, as specified in the contract. The bill contains the following:

Chain calls

Callable by anyone

Callable by consumer or service

Callable by service

Callable by user

Flow

We start of by creating a contract. This can technically be done by anyone, but in practice will likely end up being done by either the service or the consumer (depending on what the service expects). This will be followed by the service or consumer setting the metadata (again depending on how the service expects things to be), and the service setting a base fee + variable fee. Note that part of the communication can and should be off chain, the contract is only the finalized agreement. When the fees and metadata are set, both the consumer and service need to explicitly approve the contract, setting the appropriate flag on the contract. Note that as soon as either party accepted (i.e. either flag is set), the fees and metadata cannot be changed anymore. It is technically possible for consumers to accept a contract as soon as it is created, thereby not giving the service a chance to set the fees. Though this basically means the contract is invalid and the service should just outright reject it.

Once the contract is accepted by both the consumer and the service, it can be billed (i.e. bills send before both flags are set must be rejected). Because a service should not charge the user if it doesn't work, we will require that bills be send every hour, by limiting the window size to 3600. Anything with a bigger window is rejected. This way if the service is down (for some longer period), it for sure can't bill for the time it was down. When the bill is received, the chain calculates contract.base_fee * bill.window / 3600 + variable fee (keeping in mind the constraint for variable fee as outlined above), and this amount is transferred from the consumer twin account to the service twin account.

We will not implement a grace period for this right now, as the service should define on an individual basis how this is handled. If needed in the future this can of course change.

DylanVerstraete commented 1 year ago

Progress on tfchain: https://github.com/threefoldtech/tfchain/pull/495

Things left to do here:

xmonader commented 1 year ago

Need a status update here, as this was rebased on the work of the power mgmt and the capacity planning? @renauter @DylanVerstraete ?

renauter commented 1 year ago

Need a status update here, as this was rebased on the work of the power mgmt and the capacity planning? @renauter @DylanVerstraete ?

Power mgmt and the capacity planning was reverted 3rd party service contract is now independent from it and has been already merged and tagged https://github.com/threefoldtech/tfchain/releases/tag/2.2.0-rc7 Substrate go client is also already synchronized Tomorrow we handle graphql And will be able to deploy on devnet

renauter commented 1 year ago

First version of 3rd party service contracts is deployed on Devnet! See https://github.com/threefoldtech/tf_operations/issues/1340

@xmonader, all related issues are tagged in Verification for 3.8.0

zaelgohary commented 1 year ago

Verified.

serviceContractCreate

image

serviceContractSetMetadata (by service)

image

serviceContractsSetFees (by service)

image

serviceContractApprove (by service)

image

serviceContractReject (by service)

image

serviceContractApprove (by user)

image

serviceContractReject (by user)

image