How To Use Vault Protection Smart Contracts

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 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

  2. Single Limit

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.

All our smart contracts can be found at:

The protection admin for a token can be set by using setProtectionAdmin function on LosslessGuardian smart contract.l

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.

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

  • Which address should have this whitelist applied to it (the protected address)

  • Whitelisted addresses (wallets that will be able to receive tokens from the protected address)

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

  • Which address should have its whitelist updated

  • A list of addresses that need to be removed or added from or to the whitelist

  • A flag that specifies if a provided list of addresses has to be removed or added to the whitelist. Setting the flag to true will add the provided list of addresses to the whitelist and setting the flag to false would remove it from the 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

  • The address which should have its whitelist removed

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

  • Using setLimitBatched 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

  • For which address this limit should be applied to

  • The limit period in seconds Limit amount Limit start time

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

  • Address for which transfers should be paused

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

  • A list of addresses that should have their limit removed from them

function removeLimits(address token, address[] calldata protectedAddresses) external onlyProtectionAdmin(token)

Last updated