This document describes how to work with the recurring billing smart contract factory and a recurring billing smart contract.
- Smart Contracts Addresses
- Recurring Billing Smart Contract Factory
- Using Recurring Billing Smart Contract
Mainnet:
- 0xDCc90D21186e9c1B60439FdBf88f0f14ad3A7355: Recurring Billing Smart Contract Factory
- 0x9dF38BdF603b36B8FE8040De760dFbB84cCeFa6d: Recurring Billing Smart Contract (for DREAM token)
Testnet (Ropsten):
Please create an issue/pull request regarding deploying recurring billing smart contract factories for any other networks.
Recurring billing smart contract factory allows to create recurring billing smart contracts for any ERC20-compatible tokens. Thus, you can enable recurring billing for your own tokens.
To create new recurring billing smart contract for your token, execute newRecurringBillingContract
function in recurring billing smart contract factory, providing a token address as an argument. You can make this transaction from any account: this account won't be provided with any special control over the new recurring billing smart contract.
Once mined, check the event logs of the transaction and find NewRecurringBillingContractCreated(address token, address recurringBillingContract)
event. This event has an address of the new recurring billing smart contract for your token (example for DREAM token: 9df38bdf603b36b8fe8040de760dfbb84ccefa6d
is the new recurring billing contract address). You don't need to create more than 1 recurring billing smart contract for your token. However, in case you really need this you can publish more transactions to newRecurringBillingContract
function, each one will create a new recurring billing smart contract.
You can use Etherscan or similar resources to find out event logs of past transactions and check whether recurring billing smart contract was created for your token.
Etherscan does not inherit verified smart contract code for newly created smart contracts yet, so you have to verify smart contract code manually. In order to verify the code of your newly created recurring billing smart contract, go to verify smart contract code on Etherscan and:
- Copy-paste the code from the smart contract factory. To make things more clear, you can delete
contract RecurringBillingContractFactory
definition from the code. - In the
Address
input, put the address of your newly created recurring billing smart contract. - In the
Contract Name
input, putTokenRecurringBilling
. - Select
0.5.2
as a compiler version. - Select
Yes
forOptimization Enabled
. Ensure thatRuns
says200
. - In "Constructor Arguments ABI-encoded", put the newly created smart contract address as it appears in the
NewRecurringBillingContractCreated
event log. E.g. for DREAM token we had to put0000000000000000000000009df38bdf603b36b8fe8040de760dfbb84ccefa6d
(0x9df38bdf603b36b8fe8040de760dfbb84ccefa6d). - Press
Verify and Publish
.
Once you've got the recurring billing smart contract address for your token, you can use it for your needs, it's permanent. Example: Recurring Billing for DREAM Token.
The recurring billing smart contract defines workflow between a merchant and a customer. Workflow:
- Merchant registers themselves in this smart contract using
registerNewMerchant
.- Merchant specifies
beneficiary
address, which receives tokens. - Merchant specifies
merchant
address, which is able to changemerchant
andbeneficiary
addresses. - Merchant specified an address that is authorized to call
charge
related to this merchant.- Later, merchant can (de)authorize another addresses to call
charge
usingchangeMerchantChargingAccount
.
- Later, merchant can (de)authorize another addresses to call
- As a result, merchant gets
merchantId
, which is used to initialize recurring billing by customers. - Merchant account can change their
beneficiary
,merchant
and authorized charging addresses by calling:- Function
changeMerchantAccount
, which changes account that can control this merchant (merchantId
). - Function
changeMerchantBeneficiaryAddress
, which changes merchant'sbeneficiary
. - Function
changeMerchantChargingAccount
, which (de)authorizes addresses to callcharge
on behalf of this merchant.
- Function
- Merchant specifies
- According to an off-chain agreement with merchant, customer calls
allowRecurringBilling
and:- Specifies
billingId
, which is given off-chain by merchant (merchant will listen blockchain Event on this ID). - Specifies
merchantId
, the merchant which will receive tokens. - Specifies
period
in seconds, during which only one charge can occur. - Specifies
value
, amount in tokens which can be charged eachperiod
.- If the customer doesn't have at least
value
tokens,allowRecurringBilling
errors. - If the customer haven't approved at least
value
tokens for a smart contract,allowRecurringBilling
errors.
- If the customer doesn't have at least
billingId
is then used by merchant to charge customer eachperiod
.
- Specifies
- Merchant use authorized accounts (1.iii) to call the
charge
function eachperiod
to charge agreed amount from a customer.- It is impossible to call
charge
if the date of the last charge is less thanperiod
. - Calling
charge
cancels billing when called after 2period
s from the last charge. - Thus, to successfully charge an account,
charge
must be strictly called within 1 and 2period
s after the last charge. - Calling
charge
errors if any of the following occur:- Customer canceled recurring billing with
cancelRecurringBilling
. - Customer's balance is lower than the chargeable amount.
- Customer's allowance to the smart contract is less than the chargeable amount.
- Specified
billingId
does not exists. - There's no
period
passed since the last charge.
- Customer canceled recurring billing with
- Next charge date increments strictly by
period
each charge, thus, there's no need to execcharge
strictly on time.
- It is impossible to call
- Customer can cancel further billing by calling
cancelRecurringBilling
and passingbillingId
. - TokenRecurringBilling smart contract implements
receiveApproval
function for allowing/cancelling billing within one call from the token smart contract. Parameterdata
is encoded as tightly-packed (uint256 metadata, uint256 billingId).metadata
is encoded usingencodeBillingMetadata
.- As for
receiveApproval
,lastChargeAt
inmetadata
is used as an action identifier. lastChargeAt=0
specifies that customer wants to allow new recurring billing.lastChargeAt=1
specifies that customer wants to cancel existing recurring billing.- Make sure that passed
bytes
parameter is exactly 64 bytes in length.
The common automated setup for the recurring billing smart contract can be arranged like this:
- (One-time action) Merchant (a business representative) register themselves in a smart contract, determining which address will receive tokens and which address will be authorized to charge customers on behalf of merchant account.
- (One-time action) Merchant develops back end for recurring charges from authorized charging account. In short, back end publishes charge Ethereum transaction from charging account each time it sees
BillingAllowed
event or when the time allows to do the next charge. Additionally, back end can listen forBillingCharged
event to strictly define the next charge date. - (One-time action) Merchant develops front end for end users, primarily allowing them to call
allowRecurringBilling
function. Note that billing parameters should arrive and get validated on the back end. If billing parameters don't match with ones generated on a back end, merchant should not perform any charges. - (Recurring) Each time there is a charge possible, back end charges customers using
charge
function.
More detailed description of how to work with these smart contracts is coming on the developer's Medium.