Arcadia Finance
Search
K
Comment on page

Vault

Users can use this vault to deposit a combination of assets (ERC20, ERC721, ERC1155, etc). The vault will denominate all the pooled assets into one baseCurrency (one unit of account). An increase in value of one asset will offset a decrease in value of another asset. Users can take out a credit line against the single denominated value.
A vault is a smart contract that will contain multiple assets. Using getValue(), the vault returns the combined total value of all (whitelisted) assets the vault contains. Integrating this vault as means of collateral management for your own protocol that requires collateral is encouraged. Arcadia's vault functions will guarantee you a certain value of the vault. For whitelists or liquidation strategies specific to your protocol, contact: dev at arcadia.finance

Contract Spec

State Variables

_IMPLEMENTATION_SLOTstorage slot with the address of the current implementation. This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

isTrustedProtocolSet

bool public isTrustedProtocolSet;

vaultVersion

uint16 public vaultVersion;

life

uint256 public life;

baseCurrency

address public baseCurrency;

owner

address public owner;

liquidator

address public liquidator;

registry

address public registry;

trustedProtocol

address public trustedProtocol;

erc20Stored

address[] public erc20Stored;

erc721Stored

address[] public erc721Stored;

erc1155Stored

address[] public erc1155Stored;

erc721TokenIds

uint256[] public erc721TokenIds;

erc1155TokenIds

uint256[] public erc1155TokenIds;

allowed

mapping(address => bool) public allowed;

Functions

onlyFactorythrows if called by any account other than the factory address.
modifier onlyFactory();
onlyAuthorized throws if called by any account other than an authorised adress.
modifier onlyAuthorized();
onlyOwnerthrows if called by any account other than the owner.
modifier onlyOwner();
constructor
constructor();

Initialize

function initialize(address owner_, address registry_, uint16 vaultVersion_) external;
  • Initiates the variables of the vault
  • A proxy will be used to interact with the vault logic. Therefore everything is initialised through an init function. This function will only be called (once) in the same transaction as the proxy vault creation through the factory.
Parameters
Name
Type
Description
owner_
address
The tx.origin: the sender of the 'createVault' on the factory
registry_
address
The 'beacon' contract to which should be looked at for external logic.
vaultVersion_
uint16
The version of the vault logic.

upgradeVault

Stores a new address in the EIP1967 implementation slot & updates the vault version.
function upgradeVault(address newImplementation, uint16 newVersion) external onlyFactory;

_getAddressSlot

Returns an AddressSlot with member value located at slot.
function _getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r);

transferOwnership

Transfers ownership of the contract to a new account (newOwner). Can only be called by the current owner via the factory. A transfer of ownership of this vault by a transfer of ownership of the accompanying ERC721 Vault NFT issued by the factory. Owner of Vault NFT = owner of vault
function transferOwnership(address newOwner) public onlyFactory;

_transferOwnership

Transfers ownership of the contract to a new account (newOwner). Internal function without access restriction.
function _transferOwnership(address newOwner) internal virtual;

setBaseCurrency

Sets the baseCurrency of a vault.
function setBaseCurrency(address baseCurrency_) public onlyAuthorized;
Parameters
Name
Type
Description
baseCurrency_
address
the new baseCurrency for the vault.

_setBaseCurrency

Internal function: sets baseCurrency.
First checks if there is no locked value. If there is no value locked then the baseCurrency gets changed to the param
function _setBaseCurrency(address baseCurrency_) private;
Parameters
Name
Type
Description
baseCurrency_
address
the new baseCurrency for the vault.

openTrustedMarginAccount

Initiates a margin account on the vault for one trusted application..
The open position is fetched at a contract of the application -> only allow trusted audited protocols!!!
Currently only one trusted protocol can be set.
Only open margin accounts for protocols you trust! The protocol has significant authorisation: use margin (-> trigger liquidation)
function openTrustedMarginAccount(address protocol) public onlyOwner;
Parameters
Name
Type
Description
protocol
address
The contract address of the trusted application.

closeTrustedMarginAccount

Closes the margin account on the vault of the trusted application..
The open position is fetched at a contract of the application -> only allow trusted audited protocols!!!
Currently only one trusted protocol can be set.
function closeTrustedMarginAccount() public onlyOwner;

increaseMarginPosition

Can be called by authorised applications to increase a margin position.
function increaseMarginPosition(address baseCurrency_, uint256 amount)
public
view
onlyAuthorized
returns (bool success);
Parameters
Name
Type
Description
baseCurrency_
address
The Base-currency in which the margin position is denominated
amount
uint256
The amount the position is increased.
Returns
Name
Type
Description
success
bool
Boolean indicating if there is sufficient free margin to increase the margin position

getVaultValue

Returns the total value of the vault in a specific baseCurrency
Fetches all stored assets with their amounts on the proxy vault. Using a specified baseCurrency, fetches the value of all assets on the proxy vault in said baseCurrency.
function getVaultValue(address baseCurrency_) public view returns (uint256 vaultValue);
Parameters
Name
Type
Description
baseCurrency_
address
The asset to return the value in.
Returns
Name
Type
Description
vaultValue
uint256
Total value stored on the vault, expressed in baseCurrency.

getCollateralValue

Calculates the total collateral value of the vault.
Returns the value denominated in the baseCurrency in which the proxy vault is initialised.
The collateral value of the vault is equal to the spot value of the underlying assets, discounted by a haircut (the collateral factor). Since the value of collateralised assets can fluctuate, the haircut guarantees that the vault remains over-collateralised with a high confidence level (99,9%+). The size of the haircut depends on the underlying risk of the assets in the vault, the bigger the volatility or the smaller the on-chain liquidity, the bigger the haircut will be.
function getCollateralValue() public view returns (uint256 collateralValue);
Returns
Name
Type
Description
collateralValue
uint256
The collateral value, returned in the decimals of the base currency.

getLiquidationValue

Calculates the total liquidation value of the vault.
Returns the value denominated in the baseCurrency in which the proxy vault is initialised.
The liquidation value of the vault is equal to the spot value of the underlying assets, discounted by a haircut (the liquidation factor). The liquidation value takes into account that not the full value of the assets can go towards repaying the debt, but only a fraction of it, the remaining value is lost due to: slippage while liquidating the assets, fees for the auction initiator, gas fees and a penalty to the protocol.
function getLiquidationValue() public view returns (uint256 liquidationValue);
Returns
Name
Type
Description
liquidationValue
uint256
The liquidation value, returned in the decimals of the base currency.

getUsedMargin

Returns the used margin of the proxy vault.
The used margin is denominated in the baseCurrency of the proxy vault.
Currently only one trusted application (Arcadia Lending) can open a margin account. The open position is fetched at a contract of the application -> only allow trusted audited protocols!!!
function getUsedMargin() public view returns (uint256 usedMargin);
Returns
Name
Type
Description
usedMargin
uint256
The used amount of margin a user has taken

getFreeMargin

Calculates the remaining margin the owner of the proxy vault can use.
The free margin is denominated in the baseCurrency of the proxy vault, with an equal number of decimals as the base currency.
function getFreeMargin() public view returns (uint256 freeMargin);
Returns
Name
Type
Description
freeMargin
uint256
The remaining amount of margin a user can take.

liquidateVault

Function called to start a vault liquidation.
Requires an unhealthy vault (value / debt < liqThres). Starts the vault auction on the liquidator contract. Increases the life of the vault to indicate a liquidation has happened. Transfers ownership of the proxy vault to the liquidator!
function liquidateVault(address liquidationKeeper) public onlyFactory returns (bool success, address liquidator_);
Parameters
Name
Type
Description
liquidationKeeper
address
Address of the keeper who initiated the liquidation process.
Returns
Name
Type
Description
success
bool
Boolean returning if the liquidation process is successfully started.
liquidator_
address

deposit

Deposits assets into the proxy vault by the proxy vault owner.
All arrays should be of same length, each index in each array corresponding to the same asset that will get deposited. If multiple asset IDs of the same contract address are deposited, the assetAddress must be repeated in assetAddresses. The ERC20 gets deposited by transferFrom. ERC721 & ERC1155 using safeTransferFrom. Can only be called by the proxy vault owner to avoid attacks where malicous actors can deposit 1 wei assets, increasing gas costs upon credit issuance and withrawals. Example inputs: [wETH, DAI, Bayc, Interleave], [0, 0, 15, 2], [1018, 1018, 1, 100], [0, 0, 1, 2] [Interleave, Interleave, Bayc, Bayc, wETH], [3, 5, 16, 17, 0], [123, 456, 1, 1, 10**18], [2, 2, 1, 1, 0]
function deposit(
address[] calldata assetAddresses,
uint256[] calldata assetIds,
uint256[] calldata assetAmounts,
uint256[] calldata assetTypes
) external onlyOwner;
Parameters
Name
Type
Description
assetAddresses
address[]
The contract addresses of the asset. For each asset to be deposited one address, even if multiple assets of the same contract address are deposited.
assetIds
uint256[]
The asset IDs that will be deposited for ERC721 & ERC1155. When depositing an ERC20, this will be disregarded, HOWEVER a value (eg. 0) must be filled!
assetAmounts
uint256[]
The amounts of the assets to be deposited.
assetTypes
uint256[]
The types of the assets to be deposited. 0 = ERC20 1 = ERC721 2 = ERC1155 Any other number = failed tx

_deposit

Deposits assets into the proxy vault.
Each index in each array corresponding to the same asset that will get deposited. If multiple asset IDs of the same contract address are deposited, the assetAddress must be repeated in assetAddresses. The ERC20 gets deposited by transferFrom. ERC721 & ERC1155 using safeTransferFrom. Example inputs: [wETH, DAI, Bayc, Interleave], [0, 0, 15, 2], [1018, 1018, 1, 100], [0, 0, 1, 2] [Interleave, Interleave, Bayc, Bayc, wETH], [3, 5, 16, 17, 0], [123, 456, 1, 1, 10**18], [2, 2, 1, 1, 0]
function _deposit(
address[] memory assetAddresses,
uint256[] memory assetIds,
uint256[] memory assetAmounts,
uint256[] memory assetTypes,
address from
) internal;
Parameters
Name
Type
Description
assetAddresses
address[]
The contract addresses of the asset. For each asset to be deposited one address, even if multiple assets of the same contract address are deposited.
assetIds
uint256[]
The asset IDs that will be deposited for ERC721 & ERC1155. When depositing an ERC20, this will be disregarded, HOWEVER a value (eg. 0) must be filled!
assetAmounts
uint256[]
The amounts of the assets to be deposited.
assetTypes
uint256[]
The types of the assets to be deposited. 0 = ERC20 1 = ERC721 2 = ERC1155 Any other number = failed tx
from
address
The address to deposit from.

withdraw

Processes withdrawals of assets by and to the owner of the proxy vault.
All arrays should be of same length, each index in each array corresponding to the same asset that will get withdrawn. If multiple asset IDs of the same contract address are to be withdrawn, the assetAddress must be repeated in assetAddresses. The ERC20 get withdrawn by transfers. ERC721 & ERC1155 using safeTransferFrom. Can only be called by the proxy vault owner. Will fail if balance on proxy vault is not sufficient for one of the withdrawals. Will fail if "the value after withdrawal / open debt (including unrealised debt) > collateral threshold". If no debt is taken yet on this proxy vault, users are free to withraw any asset at any time. Example inputs: [wETH, DAI, Bayc, Interleave], [0, 0, 15, 2], [1018, 1018, 1, 100], [0, 0, 1, 2] [Interleave, Interleave, Bayc, Bayc, wETH], [3, 5, 16, 17, 0], [123, 456, 1, 1, 10**18], [2, 2, 1, 1, 0]
function withdraw(
address[] calldata assetAddresses,
uint256[] calldata assetIds,
uint256[] calldata assetAmounts,
uint256[] calldata assetTypes
) external onlyOwner;
Parameters
Name
Type
Description
assetAddresses
address[]
The contract addresses of the asset. For each asset to be withdrawn one address, even if multiple assets of the same contract address are withdrawn.
assetIds
uint256[]
The asset IDs that will be withdrawn for ERC721 & ERC1155. When withdrawing an ERC20, this will be disregarded, HOWEVER a value (eg. 0) must be filled!
assetAmounts
uint256[]
The amounts of the assets to be withdrawn.
assetTypes
uint256[]
The types of the assets to be withdrawn. 0 = ERC20 1 = ERC721 2 = ERC1155 Any other number = failed tx

_withdraw

Processes withdrawals of assets
Each index in each array corresponding to the same asset that will get withdrawn. If multiple asset IDs of the same contract address are to be withdrawn, the assetAddress must be repeated in assetAddresses. The ERC20 get withdrawn by transfers. ERC721 & ERC1155 using safeTransferFrom. Will fail if balance on proxy vault is not sufficient for one of the withdrawals. Example inputs: [wETH, DAI, Bayc, Interleave], [0, 0, 15, 2], [1018, 1018, 1, 100], [0, 0, 1, 2] [Interleave, Interleave, Bayc, Bayc, wETH], [3, 5, 16, 17, 0], [123, 456, 1, 1, 10**18], [2, 2, 1, 1, 0]
function _withdraw(
address[] memory assetAddresses,
uint256[] memory assetIds,
uint256[] memory assetAmounts,
uint256[] memory assetTypes,
address to
) internal;
Parameters
Name
Type
Description
assetAddresses
address[]
The contract addresses of the asset. For each asset to be withdrawn one address, even if multiple assets of the same contract address are withdrawn.
assetIds
uint256[]
The asset IDs that will be withdrawn for ERC721 & ERC1155. When withdrawing an ERC20, this will be disregarded, HOWEVER a value (eg. 0) must be filled!
assetAmounts
uint256[]
The amounts of the assets to be withdrawn.
assetTypes
uint256[]
The types of the assets to be withdrawn. 0 = ERC20 1 = ERC721 2 = ERC1155 Any other number = failed tx
to
address
The address to withdraw to.

_depositERC20

Internal function used to deposit ERC20 tokens.
Used for all tokens types = 0. Note the transferFrom, not the safeTransferFrom to allow legacy ERC20s. After successful transfer, the function checks whether the same asset has been deposited. This check is done using a loop: writing it in a mapping vs extra loops is in favor of extra loops in this case. If the address has not yet been seen, the ERC20 token address is stored.
function _depositERC20(address from, address ERC20Address, uint256 amount) private;
Parameters
Name
Type
Description
from
address
Address the tokens should be taken from. This address must have pre-approved the proxy vault.
ERC20Address
address
The asset address that should be transferred.
amount
uint256
The amount of ERC20 tokens to be transferred.

_depositERC721

Internal function used to deposit ERC721 tokens.
Used for all tokens types = 1. Note the transferFrom. No amounts are given since ERC721 are one-off's. After successful transfer, the function pushes the ERC721 address to the stored token and stored ID array. This may cause duplicates in the ERC721 stored addresses array, but this is intended.
function _depositERC721(address from, address ERC721Address, uint256 id) private;
Parameters
Name
Type
Description
from
address
Address the tokens should be taken from. This address must have pre-approved the proxy vault.
ERC721Address
address
The asset address that should be transferred.
id
uint256
The ID of the token to be transferred.

_depositERC1155

Internal function used to deposit ERC1155 tokens.
Used for all tokens types = 2. Note the safeTransferFrom. After successful transfer, the function checks whether the combination of address & ID has already been stored. If not, the function pushes the new address and ID to the stored arrays. This may cause duplicates in the ERC1155 stored addresses array, but this is intended.
function _depositERC1155(address from, address ERC1155Address, uint256 id, uint256 amount) private;
Parameters
Name
Type
Description
from
address
The Address the tokens should be taken from. This address must have pre-approved the proxy vault.
ERC1155Address
address
The asset address that should be transferred.
id
uint256
The ID of the token to be transferred.
amount
uint256
The amount of ERC1155 tokens to be transferred.

_withdrawERC20

Internal function used to withdraw ERC20 tokens.
Used for all tokens types = 0. Note the transferFrom, not the safeTransferFrom to allow legacy ERC20s. After successful transfer, the function checks whether the proxy vault has any leftover balance of said asset. If not, it will pop() the ERC20 asset address from the stored addresses array. Note: this shifts the order of erc20Stored! This check is done using a loop: writing it in a mapping vs extra loops is in favor of extra loops in this case.
function _withdrawERC20(address to, address ERC20Address, uint256 amount) private;
Parameters
Name
Type
Description
to
address
Address the tokens should be sent to. This will in any case be the proxy vault owner either being the original user or the liquidator!.
ERC20Address
address
The asset address that should be transferred.
amount
uint256
The amount of ERC20 tokens to be transferred.

_withdrawERC721

Internal function used to withdraw ERC721 tokens.
Used for all tokens types = 1. Note the safeTransferFrom. No amounts are given since ERC721 are one-off's. After successful transfer, the function checks whether any other ERC721 is deposited in the proxy vault. If not, it pops the stored addresses and stored IDs (pop() of two arrs is 180 gas cheaper than deleting). If there are, it loops through the stored arrays and searches the ID that's withdrawn, then replaces it with the last index, followed by a pop(). Sensitive to ReEntrance attacks! SafeTransferFrom therefore done at the end of the function.
function _withdrawERC721(address to, address ERC721Address, uint256 id) private;
Parameters
Name
Type
Description
to
address
Address the tokens should be taken from. This address must have pre-approved the proxy vault.
ERC721Address
address
The asset address that should be transferred.
id
uint256
The ID of the token to be transferred.

_withdrawERC1155

Internal function used to withdraw ERC1155 tokens.
Used for all tokens types = 2. Note the safeTransferFrom. After successful transfer, the function checks whether there is any balance left for that ERC1155. If there is, it simply transfers the tokens. If not, it checks whether it can pop() (used for gas savings vs delete) the stored arrays. If there are still other ERC1155's on the contract, it looks for the ID and token address to be withdrawn and then replaces it with the last index, followed by a pop(). Sensitive to ReEntrance attacks! SafeTransferFrom therefore done at the end of the function.
function _withdrawERC1155(address to, address ERC1155Address, uint256 id, uint256 amount) private;
Parameters
Name
Type
Description
to
address
Address the tokens should be taken from. This address must have pre-approved the proxy vault.
ERC1155Address
address
The asset address that should be transferred.
id
uint256
The ID of the token to be transferred.
amount
uint256
The amount of ERC1155 tokens to be transferred.

generateAssetData

Generates three arrays about the stored assets in the proxy vault in the format needed for vault valuation functions.
No balances are stored on the contract. Both for gas savings upon deposit and to allow for rebasing/... tokens. Loops through the stored asset addresses and fills the arrays. The vault valuation function fetches the asset type through the asset registries. There is no importance of the order in the arrays, but all indexes of the arrays correspond to the same asset.
function generateAssetData()
public
view
returns (address[] memory assetAddresses, uint256[] memory assetIds, uint256[] memory assetAmounts);
Returns
Name
Type
Description
assetAddresses
address[]
An array of asset addresses.
assetIds
uint256[]
An array of asset IDs. Will be '0' for ERC20's
assetAmounts
uint256[]
An array of the amounts/balances of the asset on the proxy vault. wil be '1' for ERC721's

vaultManagementAction

Calls external action handlers to execute and interact with external logic.
Similar to flash loans, this function optimistically calls external logic and checks for the vault state at the very end.
function vaultManagementAction(address actionHandler, bytes calldata actionData) public onlyOwner;
Parameters
Name
Type
Description
actionHandler
address
the address of the action handler to call
actionData
bytes
a bytes object containing two actionAssetData structs, an address array and a bytes array

onERC721Received

function onERC721Received(address, address, uint256, bytes calldata) public pure returns (bytes4);

onERC1155Received

function onERC1155Received(address, address, uint256, uint256, bytes calldata) public pure returns (bytes4);

fallback

fallback() external;

Events

Upgraded

event Upgraded(address indexed implementation);

OwnershipTransferred

event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

Structs

AddressSlot

struct AddressSlot {
address value;
}