Loop's default model for handling payments automations is to auto-generate invoices and sign transfer requests for customers. Customers also have the option of managing invoices and sending transfer requests to Loop via APIs to process on-chain. As noted in the trust assumptions, these transfer requests may reflect terms agreed to off-chain via a company’s website or on-chain via a smart contract.

Sending bills to Loop

The Loop smart contracts process transactions that are sent to Loop’s backend API. We provide API keys to companies that deploy a Loop smart contract. These keys can be provisioned and subsequently rotated as necessary from the company dashboard. Our backend uses these API keys to authenticate the transfer request and all other API interactions. Different API keys can be configured based on the operation being performed. For example, sending a transfer request can use 1 API key while adding and removing subscription plans can use another. This allows for finer grain control and lessens the impact if one of the API keys is compromised.

As a second line of security, a wallet address that the company controls is saved on-chain in the contract. When a transaction is sent to be processed on-chain, the Loop smart contract verifies each individual transfer order’s transfer parameters and validates that the address that signed and produced the signature matches the signer address stored in the contract. If the address values don't match, the transfer order fails. Thus, the transfer request is validated again, but this time on-chain.

By requiring each transfer to be signed like this, it ensures that none of the payment parameters can be changed at any point during the time the request is sent to Loop and then submitted to be processed on chain. This architecture ensures not even Loop can make a change to the parameters.

To / from address

Companies can choose to save "to" and "from" wallet addresses in the smart contract (in fact, we recommend this where possible). When this step is taken, the smart contract validates that the transfer request includes the appropriate "to" or "from" address, and if not, the transaction will fail.

Smart contract owner

Each company controls its own Loop smart contract, ideally owned by a multi-sig wallet. The contract owner is a privileged account within the contract that is allowed to call a few administrative functions.

  • setOperatorAddress(): to set the inbound / outbound treasury and signer addresses

  • addTokens(): Adds tokens to the accepted tokens list

  • removeTokens(): Removes tokens from the accepted tokens list

  • transferOwnership(): Transfers ownership to another wallet

What could go wrong?

Someone takes over the contract

Taking over the contract means compromising the wallet address that owns the contract in order to call “owner only” privileged functions. Using a multi-sig provides additional security as it would require multiple keys to be compromised. However, if the multi-sig did get compromised, there are a few things to note and some defensive mechanisms we put in place to limit any exposure to end users:

The owner address cannot change any code within the existing contract. If a new contract were to be deployed by a malicious actor, it would be outside of the Loop ecosystem and would be deployed at a new address. A new address means that any allowance that had been set by a user using our checkout or modal would be nullified and transfers attempted from that contract would fail. Thus, the attacker would not be able to steal any funds from existing users in this way.

However, the owner of the contract can update the wallet address that can sign billing requests. Thus, that owner should be a multi-sig for security purposes. Which takes us to….

The signing wallet is compromised

Since API keys are used to authorize all API requests, even if the signer wallet is compromised, a Company's API key would be needed to submit a malicious transfer order. Additionally, if you elect to save the "to" address in the smart contract, then even if someone stole the API keys and the signer wallet, they still would only be able to direct funds to the "to" wallet.

Lastly, the processing function in the contract can only be called by whitelisted keeper addresses. Thus, a malicious actor would need to separately hack Loop's factory contract to change the whitelist, in order to call the payment processing function in the contract.

There’s a bug in the contract

This is a universal fear in crypto. To mitigate this, we have implemented the following:

  • Have our smart contracts audited by reputable auditing firms, and where not formally audited, thoroughly reviewed by smart contract experts

  • Have the ability to pause transfer execution in the contract in the event that any malicious activity is detected

  • Implemented the well-documented upgradable smart contracts pattern to be able to rectify any bug that is found

A short note on fraud

We’ve written about trusting the company, but what about trusting the end consumer? Since it is a wallet that permissions the contract, that transaction requires having the private key. If someone steals the key to a wallet, it's unlikely they will sign up for an automated payment - they’d likely just take the wallet’s funds (e.g. equivalent to stealing banking information). With this in mind, companies can be less concerned about fraudulent charges from their end users in web3 payments.

Last updated