How Vault Protection Works

In this article, we review Lossless Vault Protection smart contracts, discuss how to use the system directly, and comment on some gas saving implementation details of our system.

Lossless Vault Protection is a smart contracts system that allows setting up specific protection rules for an address. Vault Protection can only be used for tokens that have integrated with lossless protection smart contracts, see also https://lossless-cash.gitbook.io/lossless/technical-reference/lerc20. It can be used by token admins and allows setting up token scoped rules for token transfers execution. At the moment there are two types of rules that can be used:

  1. Whitelist

Before any of these rules can be turned on for a particular address in a particular token’s scope, the address and the token have to be verified by the lossless team. This permission is required to stop projects from abusing Vault Protection functionality and also to perform a gradual rollout of this feature to all of the lossless protected tokens.

Once a token is verified, its project team has to set a protection admin. The sole responsibility of the Protection admin is to control protection rules. The Protection admin can only be set by the token admin. You can read more about the token admin role on lossless protected tokens here:

​​https://lossless-cash.gitbook.io/lossless/technical-reference/lerc20#admin

The protection admin for a token can be set by using setProtectionAdmin function on LosslessGuardian smart contract. All our smart contracts can be found at https://github.com/Lossless-Cash/lossless-v2

function setProtectionAdmin(address token, address admin) external onlyVerifiedToken(token)

The address of LosslessGuardian smart contract and all the other contracts mentioned in this article can be found here:

https://lossless-cash.gitbook.io/lossless/technical-reference/vault-and-treasury-protection/deployments

The diagram below summarises steps that need to be executed for Vault Protection to be enabled.

Whitelist

Adding whitelist

Address that has a whitelist will be able to transfer tokens only to an address that’s in that whitelist. The whitelist can be set using the setProtectedAddress function on the TreasuryProtectionStrategy contract.

function setProtectedAddress(address token, address protectedAddress, address[] calldata whitelist) external onlyProtectionAdmin(token)

To call this function one needs to specify:

  • In which token’s scope this whitelist is going to be set

You can also see that this function can only be called by the protection admin.

Removing Whitelist

To remove some addresses from a whitelist or add some new ones, the setWhitelistState function on the TreasuryProtectionStrategy smart contract should be used.

function setWhitelistState(address token, address protectedAddress, address[] calldata addresses, bool state) public onlyProtectionAdmin(token)

To call this function you need to specify:

  • In which token’s scope you are going to set this whitelist

In order to remove the whitelist protection rule from a protected address completely, call the removeProtectedAddresses function on the LosslessGuardian smart contract with these arguments:

  • In which token’s scope this whitelist was set
function removeProtectedAddresses(address token, address protectedAddress) external

Single Limit

Setting up single limit protection for an address means that this particular address will be able to transfer not more than a given number of tokens in a set period of time. For example, an address has a limit of 100 000 tokens per hour. Token transfer transactions will start failing if that address transfers out more than 100 000 tokens in an hour. However, the limit gets reset every period. Therefore, even if transactions start failing or the amount transferred is close to the limit, this only lasts until a new period is entered. In the previous example, this would mean that once one hour passes, the protected address can once again transfer up to 100 000 tokens.

Setting a limit

Setting a limit for an address can be done in one of two ways:

  • Using setLimit function

Essentially, setLimitBatched works just like setLimit , except that it allows setting up the same limit for a bunch of addresses in a single transaction.

function setLimitBatched(
address token,
address[] calldata protectedAddresses,
uint256 periodInSeconds,
uint256 amountPerPeriod,
uint256 startTimestamp
) external onlyProtectionAdmin(token)

function setLimit(
address token,
address protectedAddress,
uint256 periodInSeconds,
uint256 amountPerPeriod,
uint256 startTimestamp
) external onlyProtectionAdmin(token)

Arguments for setLimit are as follows:

  • In which token’s scope this limit should be set

Please note that setting a limit in the future is not recommended as it will result in a limit that does not get reset until the start time is reached. In other words, the protection will not apply for a period of time. Therefore, the start time should either be set to the current timestamp or a timestamp in the past. Choosing a timestamp in the past allows the user to have better control over when the limit gets reset. For example, if the user wants to have a limit that resets every 24 hours, they might also want it to happen exactly at midnight (00:00). So when setting this limit the user could choose the start time to be a timestamp of the previous midnight and this would result in a limit that gets reset every 24 hours exactly at midnight.

Pausing Transfers

The single limit protection strategy has a feature that allows pausing all transfers from a protected address. This is a common feature that smart contracts implement in order to mitigate incidents. However, some smart contracts just don’t have it and cannot be upgraded to include such a function. Also, wallets (Externally Owned Accounts, EOAs) do not have any way of pausing transfers. Lossless Vault Protection fixes this and allows pausing transfers from any protected address. Essentially, the transfer pausing feature uses a single limit protection strategy with a limit that’s equal to zero.

Pausing can be done by calling the pause function on the LiquidityProtectionSingleLimitStrategy smart contract. This function takes two arguments:

  • Token for which these rules should be scoped
function pause(address token, address protectedAddress) external onlyProtectionAdmin(token)

Once the transfers need to be unpaused, all you need to do is set a new limit with a valid limit amount or remove the limit protection rule completely.

Removing Limits

Removing limits from a single address or from a bunch of addresses all at once can be done by calling the removeLimits function on the LiquidityProtectionSingleLimitStrategy smart contract. For it to work you need to provide the following two arguments:

  • Token for which limit was scoped
function removeLimits(address token, address[] calldata protectedAddresses) external onlyProtectionAdmin(token)

Trusted Setup Architecture

Because some of the smart contracts are setting state in some other smart contracts, a trusted setup between different smart contracts is required. This trusted setup is created by the lossless team by calling two different functions:

  • LosslessControllerV2.setGuardian

The setGuardian function saves the trusted guardian smart contract address in the lossless controller smart contract. The verifyStrategies function saves a list of protection strategies (smart contracts addresses) that can be trusted by the guardian smart contract.

This pattern enables keeping only a minimal part of the whole Vault Protection state on the lossless controller. The guardian smart contract acts as a proxy and gatekeeper between the strategies and the controller. After the protection rules are saved on the controller, guardian, and protection strategy contracts, the controller is able to execute direct calls to the protection strategies and thus reduce gas costs by not proxying calls through the guardian contract. In case a picture is worth type(uint256).max words, please see the diagram below.

We are constantly striving to improve our documentation, and we strongly appreciate feedback, both negative and positive — do reach out if you see concrete ways how this writeup can be improved.

About Lossless

Lossless is the world’s first DeFi hack mitigation tool for token creators. Apart from our known cyber security solutions and renowned professionals, the community also plays a role. With a tangible reward system, community members are also encouraged to explore new ways to detect hacks and fraudulent transactions.

Our protocol halts counterfeit transactions through various methods of fraud identification and automatically reverses any stolen tokens back to the original owner. Our solutions to the impending problems of cyber theft within the blockchain space are thorough and applicable within many protocols.

Twitter | Telegram | Website | Whitepaper

World’s first crypto hack mitigation tool for trusted and safe DeFi.