# Providing on-chain payment based access

Loop's smart contracts can be used to gate access to end-products. When relevant, Loop stores customer external reference IDs and/or email addresses in an off-chain database. Reference IDs and email addresses are **only** ever shared with the end company. Reference IDs and email addresses are helpful in granting access based on webhooks.&#x20;

Companies can use webhooks or sign on with Ethereum to verify that a customer has an active subscription.

## **With webhooks**&#x20;

Loop can send notifications to your app using webhooks. Webhooks are especially important for subscriptions where most activity occurs asynchronously.

Events are triggered every time a subscription is created or changed. Some events are sent immediately when a subscription is created, while others recur on regular billing intervals.

Make sure that your integration properly handles the events. For example, you may want to email a customer if a payment fails or revoke a customer’s access when a subscription is canceled.

When a wallet doesn't have enough funds, the keeper network will skip over the wallet because the keeper knows the transaction will fail (it can see the wallet's level of funds), and a failed transaction costs the keeper gas with no reward.&#x20;

When someone subscribes, the webhook will push the event to the end company, including the subscription date and payment frequency. Companies can store this information and use it to extrapolate when the next payment date is.

{% hint style="info" %}
Companies can always check who has a payment due but has not yet paid on the [Company Dashboard](https://admin.loopcrypto.xyz/login). &#x20;
{% endhint %}

## **With sign on with Ethereum**&#x20;

Loop smart contracts create an on-chain record of an active subscription. Thus, sign on with Ethereum tooling can reference the smart contract to verify if a subscription is active or not.&#x20;

Subscription contract gating offers additional benefits to NFT gating and may be the better choice for some situations. Unlike NFT gating, subscriptions are tied to a specific wallet and are thus non-transferable, ensuring only the payer receives community benefits. Additionally, subscriptions can be paid for with a community’s native ERC-20, giving communities a clear consumptive use of their tokens. For example, a community could provide access to all ERC-20 or NFT holders and then gate “premium” feature access to subscribers who pay in a specific ERC-20 token. Subscription based gating is ideal for communities such as newsletters/blogs, DAOs that pair “ownership” with “cash flows” (i.e. you must own a specific NFT/token and pay a due - similar to a country club), SaaS companies, and more.

## Requirements  <a href="#requirements" id="requirements"></a>

### Providing access based on customer’s on-chain subscribing <a href="#providing-access-based-on-customers-on-chain-subscribing" id="providing-access-based-on-customers-on-chain-subscribing"></a>

Communities/companies can monitor their Loop contract for the `subscribed` event and provide access to the wallet address found in the `subscriber` variable.&#x20;

**Conditional logic**

Communities can configure their gating based on any variable contained in the subscribe event. For example, communities can gate based on subscribing to a certain plan (`tierName`), subscription start date (startDate), or paying with a particular token (`paymentToken`).&#x20;

**How to get the data**

If you are monitoring for events without an ABI, the best way is to monitor `Topic0 = 0x8c0d98b5d6c402ce661653d871595a45094a16d4b4c415aafd9b17e337f0ae37`If you are using an ABI, then you can simply listen for the “subscribed” event detailed below.

**Relevant function**

`event Subscribed( address indexed subscriber, string tierName, uint256 usdAmount, uint256 usdStakeAmount, uint256 startDate, uint256 frequency, uint256 stakedAmount, address indexed paymentToken, string paymentTokenSymbol, uint256 createdAt)`;

| Data Type         | Variable           | Description                                                                                                                      |
| ----------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| address (indexed) | subscriber         | Wallet address of the subscriber                                                                                                 |
| string            | tierName           | Name of the subscription plan                                                                                                    |
| uint256           | usdAmount          | USD price of the subscription                                                                                                    |
| uint256           | startDate          | date the subscription starts                                                                                                     |
| uint256           | frequency          | how often the subscription is paid in seconds                                                                                    |
| address (indexed) | paymentToken       | the token address of the ERC-20 the token the dollar subscription is paid in (converted at time of payment)                      |
| string            | paymentTokenSymbol | <p>the symbol of the token the dollar subscription is paid in</p><h3 id="providing-access-based-on-continued-payments"><br></h3> |

### Providing access based on continued payments <a href="#providing-access-based-on-continued-payments" id="providing-access-based-on-continued-payments"></a>

Communities that want to gate based on continued payments can monitor the ProcessPaymentSuccess event.

**Conditional logic**

Communities can decide to revoke access based on missed payments.Such configuration can allow for a grace period whereby a customer’s access isn’t revoked unless a buffer period has passed. For example, a company could say “allow access for up to 3 days after the payment is due and then exclude them.”To solve for this, find the "last payment date" + "frequency" + "buffer" = "revoke access date" and compare this date to "today". If the date is greater than today, the access can be revoked.

**How to get the data**

The "last payment date" can be found by monitoring the `ProcessPaymentSuccess` event which has `topic0 = 0xf33573f0c63990d7089884152ed4dcf37f8b8fb616604884960df63734dbbda5` and using the processedForDate as the last payment date.The "frequency" can be found by monitoring the `Subscribed` event `topic0 = 0x8c0d98b5d6c402ce661653d871595a45094a16d4b4c415aafd9b17e337f0ae37` and using the frequency variable. The frequency is in seconds.The "buffer" is inputted by the user and should be converted to the correct unit.If you’re using an ABI, get the `processedForDate` from the the `ProcessPaymentSuccess` event, and the frequency from the Subscribed event to calculate the the revoke access date.

**Relevant function**

`event ProcessPaymentSuccess( address indexed processor, address indexed accountProcessed, uint256 processedForDate, uint256 grossAmount, uint256 feeAmount, uint256 netAmount, address indexed paymentToken, address receivingAddress, uint256 date );`&#x20;

| Data Type | Variable         | Description                                                                                 |
| --------- | ---------------- | ------------------------------------------------------------------------------------------- |
| uint256   | processedForDate | Date the subscription was due                                                               |
| uint256   | date             | <p>Date the payment was received</p><h3 id="revoke-access-based-on-cancellations"><br></h3> |

### Revoke access based on cancellations  <a href="#revoke-access-based-on-cancellations" id="revoke-access-based-on-cancellations"></a>

Some communities may wish to revoke access when an end-user has canceled their subscription.

**Conditional logic**

A community may decide to revoke access once a subscription has been canceled and the current payment period has ended `endDate` or immediately when the subscription is canceled `createdAt`.

**How to get the data**

Monitoring for `Topic0: 0xd3338f38a74459c95edaa4e94e38c21b1db9d68af67266300a9396def9a9f7a1`If you’re using an ABI, get the `endDate` or `createdAt` from the `Unsubscribed` event to determine when to revoke access.

**Relevant function**

`event Unsubscribed( address indexed subscriber, string tierName, uint256 usdAmount, uint256 startDate, uint256 endDate, uint256 stakedAmount, address indexed paymentToken, string paymentTokenSymbol, uint256 createdAt )`

<table><thead><tr><th>Data Type</th><th width="103">Variable</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>subscriber</td><td>The wallet address that is unsubscribing</td></tr><tr><td>uint256</td><td>endDate</td><td>The last day of the subscription</td></tr><tr><td>uint256</td><td>createdAt</td><td>The cancellation date</td></tr></tbody></table>
