This task is for the smart contract implementation of Service Registry - Phase 1.
Smart contract requirements
The following smart contract requirements have been scoped based on the user stories in Phase 1.
Architecture overview

Methods:
registerService(did: string, serviceType: ServiceType, endpointUri: string, country: string, maxAccounts: integer, pricePerDayPerAccount: decimal, proof: string, consentBlock: integer)
Enable a Verida Infrastructure Operator to register a service.
proof is a signed message in the form:
${did} consents to registering a ${serviceType} at ${endpointUri}
Constraints:
- The
Verida Infrastructure Operator must bond VDA tokens equal to (maxUsers * vdaPer<InfrastructureType>Account), where InfrastructureType can be determined by looking up serviceType from ServiceType lookup. These bonded tokens are removed from the account's credit and placed in a separate bonded tokens pool of VDA tokens within the smart contract. These bonded tokens will be paid to the Verida Infrastructure Operator every day via the distribute() function.
- Generates a unique
serviceId that represents the service equal to hash(did+serviceType)
proof must be signed by did and match the parameters supplied when calling the method. How to prevent replay attacks? Use block number range?
updateService(did: string, serviceId: string, maxAccounts: integer, pricePerAccount: decimal)`
Update details about the service. Note: Changing the country or endpoint URI is not permitted. Instead a new service type should be created and the current one deregistered.
Updating maxAccounts will take effect immediately.
Updating pricePerAccount will take effect after 30 days (priceChangeDelayDays) for existing accounts (to give sufficient notice of any changes) if the price increases. The price change will take effect immediately for all new accounts.
Constraints:
- This method will fail if
maxAccounts is being set to a value lower than the current number of connected accounts
deregisterService(did: string, serviceId: string)`
Enable a Verida Infrastructure Operator to deregister a service. There will be a 30 day delay (see deregisterDelayDays) before the service is removed entirely. The service will immediately stop accepting new connections. The service will be flagged as pending removal.
addCredit(did: string)
Allow a Verida Account to deposit VDA tokens as credit to their account. Credit is stored against a given DID. This can be used by both Verida Account users and Verida Infrastructure Operator users.
removeCredit(did: string)
Allow a Verida Account to withdraw VDA tokens that are currently sitting as credit in their account. Tokens will be withdrawn to the account that called this method.
The smart contract will reject the request if, after removing the tokens, the did will have insufficient credit to meet 30 days (minimumDaysCreditPerService) for all connected services.
connectService(did: string, serviceId: string)
Enable a Verida Account to connect and make use of a service provided by a Verida Infrastructure Operator. The Verida Account must deposit sufficient tokens for 30 days (minimumDaysCreditPerService) of utilising the service, calculated based on the pricePerDayPerAccount.
The smart contract will reject the connection if:
- The service is pending de-registration
- The service is has hit its maximum number of connected accounts
- The account didn't deposit sufficient tokens for 30 days of access
disconnectService(did: string, serviceId: string)
Enable a Verida Account to disconnect a service provided by a Verida Infrastructure Operator. The Verida Account will free up tokens previously deposited for utilising the service that can then be removed via removeCredit().
discoverServices(infraType: string (required), serviceType: string, country: string, maxPricePerDay)
Enable easy searching of the available services so users can discover the services they want to select.
distribute()
Distribute credit between all the registered did's based on the connected services.
For each Verida Account Connection credit VDA tokens to the Verida Infrastructure Operator and debit tokens from the Verida Account base on the service pricePerDayPerAccount.
If the Verida Account has insufficient credit the services they have registered are automatically de-registered. There is no guarantee to the order that services are de-registered.
Credit can be added or removed (effectively claiming) via the addCredit() and removeCredit() methods.
Does this method need to be called externally or could it be automatically called every day?
Constraints:
- Ensure this method is only run once per day
DID v blockchain address
Most smart contracts allocate tokens to a blockchain address. In our instance, we need to allocate tokens to a specific DID and only allow those tokens to be withdrawn by that DID.
Data Structures:
InfrastructureType (enum):
[
"database",
"storage",
"messaging",
"notification"
]
ServiceType (lookup):
[
"VeridaDatabase": {"type": "database"},
"VeridaStorage": {"type": "storage"},
"VeridaMessaging": {"type": "messaging"},
"VeridaNotification": {"type": "notification"}"
"TextileDatabase": {"type": "database"},
]
ServiceTypeConfig:
The configuration will depend on the ServiceType.
Config Variables:
These variables can be changed by the contract owner.
vdaPerDatabaseAccount: How many VDA tokens must be bonded by the Verida Infrastructure Operator to register a database node
vdaPerMessagingAccount: How many VDA tokens must be bonded by the Verida Infrastructure Operator to register a messaging node
vdaPerStorageAccount: How many VDA tokens must be bonded by the Verida Infrastructure Operator to register a storage node
vdaPerNotificationAccount: How many VDA tokens must be bonded by the Verida Infrastructure Operator to register a notification node
deregisterDelayDays: How many days to delay a service from requesting de-registration to actually being de-registered?
minimumDaysCreditPerService: How many days credit must a Verida Account maintain for each Verida Account Connection?
priceChangeDelayDays: How many days to delay price changes for services
Deliverables
Future considerations
- Allow infrastructure operators to register multiple services of the same type under the same DID?
- Use a common add / remove credit registry, instead of building into this smart contract?
This task is for the smart contract implementation of Service Registry - Phase 1.
Smart contract requirements
The following smart contract requirements have been scoped based on the user stories in Phase 1.
Architecture overview
Methods:
registerService(did: string, serviceType: ServiceType, endpointUri: string, country: string, maxAccounts: integer, pricePerDayPerAccount: decimal, proof: string, consentBlock: integer)
Enable a
Verida Infrastructure Operatorto register a service.proofis a signed message in the form:Constraints:
Verida Infrastructure Operatormust bond VDA tokens equal to (maxUsers*vdaPer<InfrastructureType>Account), whereInfrastructureTypecan be determined by looking upserviceTypefromServiceTypelookup. These bonded tokens are removed from the account's credit and placed in a separatebonded tokenspool of VDA tokens within the smart contract. These bonded tokens will be paid to theVerida Infrastructure Operatorevery day via thedistribute()function.serviceIdthat represents the service equal tohash(did+serviceType)proofmust be signed bydidand match the parameters supplied when calling the method. How to prevent replay attacks? Use block number range?updateService(did: string, serviceId: string, maxAccounts: integer, pricePerAccount: decimal)`
Update details about the service. Note: Changing the country or endpoint URI is not permitted. Instead a new service type should be created and the current one deregistered.
Updating
maxAccountswill take effect immediately.Updating
pricePerAccountwill take effect after 30 days (priceChangeDelayDays) for existing accounts (to give sufficient notice of any changes) if the price increases. The price change will take effect immediately for all new accounts.Constraints:
maxAccountsis being set to a value lower than the current number of connected accountsderegisterService(did: string, serviceId: string)`
Enable a
Verida Infrastructure Operatorto deregister a service. There will be a 30 day delay (seederegisterDelayDays) before the service is removed entirely. The service will immediately stop accepting new connections. The service will be flagged as pending removal.addCredit(did: string)
Allow a
Verida Accountto deposit VDA tokens as credit to their account. Credit is stored against a given DID. This can be used by bothVerida Accountusers andVerida Infrastructure Operatorusers.removeCredit(did: string)
Allow a
Verida Accountto withdraw VDA tokens that are currently sitting as credit in their account. Tokens will be withdrawn to the account that called this method.The smart contract will reject the request if, after removing the tokens, the
didwill have insufficient credit to meet 30 days (minimumDaysCreditPerService) for all connected services.connectService(did: string, serviceId: string)
Enable a
Verida Accountto connect and make use of a service provided by aVerida Infrastructure Operator. TheVerida Accountmust deposit sufficient tokens for 30 days (minimumDaysCreditPerService) of utilising the service, calculated based on thepricePerDayPerAccount.The smart contract will reject the connection if:
disconnectService(did: string, serviceId: string)
Enable a
Verida Accountto disconnect a service provided by aVerida Infrastructure Operator. TheVerida Accountwill free up tokens previously deposited for utilising the service that can then be removed viaremoveCredit().discoverServices(infraType: string (required), serviceType: string, country: string, maxPricePerDay)
Enable easy searching of the available services so users can discover the services they want to select.
distribute()
Distribute credit between all the registered
did's based on the connected services.For each
Verida Account Connectioncredit VDA tokens to theVerida Infrastructure Operatorand debit tokens from theVerida Accountbase on the servicepricePerDayPerAccount.If the
Verida Accounthas insufficient credit the services they have registered are automatically de-registered. There is no guarantee to the order that services are de-registered.Credit can be added or removed (effectively
claiming) via theaddCredit()andremoveCredit()methods.Does this method need to be called externally or could it be automatically called every day?
Constraints:
DID v blockchain address
Most smart contracts allocate tokens to a blockchain address. In our instance, we need to allocate tokens to a specific DID and only allow those tokens to be withdrawn by that DID.
Data Structures:
InfrastructureType (enum):
ServiceType (lookup):
ServiceTypeConfig:
The configuration will depend on the
ServiceType.Config Variables:
These variables can be changed by the contract owner.
vdaPerDatabaseAccount: How many VDA tokens must be bonded by theVerida Infrastructure Operatorto register a database nodevdaPerMessagingAccount: How many VDA tokens must be bonded by theVerida Infrastructure Operatorto register a messaging nodevdaPerStorageAccount: How many VDA tokens must be bonded by theVerida Infrastructure Operatorto register a storage nodevdaPerNotificationAccount: How many VDA tokens must be bonded by theVerida Infrastructure Operatorto register a notification nodederegisterDelayDays: How many days to delay a service from requesting de-registration to actually being de-registered?minimumDaysCreditPerService: How many days credit must aVerida Accountmaintain for eachVerida Account Connection?priceChangeDelayDays: How many days to delay price changes for servicesDeliverables
Future considerations