Blueberry Bank Contract
aboutBlueberryBank.sol
is a smart contract that implements a bank in which users can borrow and lend different tokens, as well as keep track of their positions. The contract includes the following functionalities:
Allowing borrowing, lending, and repaying different tokens
Tracking the state of each position and storing position data
Implement a borrowing limit for each user's position
Use an oracle to determine token prices
Implement a fee system for borrowing, lending, and deployment inside of the protocol
Functions
initialize
This function initializes the bank smart contract by setting the Oracle smart contract, the Protocol config address, and the Fee manager address. It also initializes some internal state variables. The function can only be called by the contract owner.
Parameters:
Name | Type | Description |
---|---|---|
| address | The oracle smart contract address |
| address | The Protocol config smart contract adress |
EXECUTOR
This function returns the current executor of the smart contract, which is the owner of the current position. If there is no position under execution, it reverts with an error.
Parameters:
address
- the address of the current position owner
setAllowContractCalls
This function sets the allowContractCalls
flag to allow or disallow contract calls. If allowContractCalls
is set to true
, then only externally-owned accounts (EOAs) can call the contract. This function can only be called by the contract owner.
Parameters
ok
- The status to setallowContractCalls
to. Iffalse
, only EOA can call the contract.
whitelistContract
This function sets the status of the given contracts in the whitelist. The function can only be called by the contract owner.
Parameters:
Name | Type | Description |
---|---|---|
| Array | An array of contract addresses to change the status of. |
| Array | An array of boolean values to change the status of the corresponding contract address in |
whitelistSpells
This function sets the status of the given spells in the whitelist. The function can only be called by the contract owner.
Parameters:
Name | Type | Description |
---|---|---|
| Array | An array of contract addresses to change the status of. |
| Array | An array of boolean values to change the status of the corresponding contract address in |
whitelistTokens
This function sets the status of the given tokens in the whitelist. It also checks whether the given tokens are supported by the Oracle smart contract. The function can only be called by the contract owner.
Parameters:
Name | Type | Description |
---|---|---|
| Array | An array of contract addresses to change the status of. |
| Array | An array of boolean values to change the status of the corresponding contract address in |
whitelistERC1155
This function sets the status of the given ERC1155(wrapped tokens) in the whitelist. The function can only be called by the contract owner.
Parameters:
Name | Type | Description |
---|---|---|
| Array | An array of contract addresses to change the status of. |
| bool | The status of the corresponding whitelisted wrapped tokens in |
addBank
This function adds a new bank to the ecosystem. It creates a new Bank
struct and sets its properties, such as the underlying token for the bank and the address of the soft and hard vaults. It also checks whether the bToken
for the soft vault has already been added to any other bank. If the bToken
has already been added to a bank, it reverts with an error. The function can only be called by the contract owner.
Parameters:
Name | Type | Description |
---|---|---|
| Address | The address of the underlying token for the bank |
| Address | The address of the soft vault for the bank |
| Address | The address of the hard vault for the bank |
| uint256 | The numerical value for liquidation threshold for the bank |
setBankStatus
This function is used to set the bank status to a new value. Only callable by the owner
Parameters:
Name | Type | Description |
---|---|---|
| uint256 | The new bank status value to set |
Modifiers
onlyOwner
: Only the contract owner can call this function
Return
None
isBorrowerAllowed
This function is used to check whether borrowing is allowed for the bank or not
Parameters:
None
Modifiers:
None
Return:
bool: Returns true if borrowing is allowed, false otherwise.
isRepayAllowed
This function is used to check whether repaying is allowed for the bank or not
Parameters:
None
Modifiers:
None
Return:
bool: Returns true if repaying is allowed, false otherwise.
isLendAllowed
This function is used to check whether lending is allowed for the bank or not
Parameters:
None
Modifiers:
None
Return:
bool: Returns true if lending is allowed, false otherwise.
isWithdrawLendAllowed
This function is used to check whether withdrawing lending is allowed for the bank or not
Parameters:
None
Modifiers:
None
Return:
bool: Returns true if withdrawing lend is allowed, false otherwise.
accrue
This function is used to trigger interest accrual for the given bank.
Parameters:
Name | Type | Description |
---|---|---|
| address | The underlying token for which interest accrual needs to be triggered |
accrueAll
This function is used to trigger interest accrual for a list of banks.
Parameters:
Name | Type | Description |
---|---|---|
| array | The list of underlying tokens for which interest accrual needs to be triggered. |
Modifiers:
None
Return:
None
_borrowBalanceStored
This internal function is used to get the stored borrow balance for the given token
Parameters:
Name | Type | Description |
---|---|---|
| address | The underlying token for which the stored borrow balance needs to be retrieved |
Modifiers:
None
Return:
uint256: The stored borrow balance for the given token.
currentPositionDebt
This function returns the debt of a given position considering the debt interest stored.
Parameters:
Name | Type | Description |
---|---|---|
| uint256 | The ID of the position to query for the debt balance |
Return:
debt
uint256: The current debt balance of the specified position.
getPositionDebt
This function returns the debt of the specified position considering the debt interest stored. The function should be called after calling the accrue
function to get the current debt.
Parameters:
Name | Type | Description |
---|---|---|
| uint256 | The ID of the position to query for the debt balance |
Modifiers:
None
Returns:
debt
(uint256): The debt balance of the specified position.
getBankInfo
This function returns the bank information for the specified token.
Parameters:
Name | Type | Description |
---|---|---|
| address | The token address to find the specific bank information |
Modifiers:
None
Returns:
isListed
(bool): True if the specified token is listed in the banks, otherwise falsebToken
(address): The address of the associated bToken contract for the specified tokentotalShare
(uin256): The total share of the specified token in the bank
getPositionInfo
This function returns the information of the specified position.
Parameters:
Name | Type | Description |
---|---|---|
| uint256 | The position ID to query for position information |
Modifiers:
None
Returns:
Position
(struct): The information about the specified position
getCurrentPositionInfo
This function returns the information about the current position
Returns:
Position
(struct): The information about the current position
Modifiers:
if (POSITION_ID == _NO_ID)
: MODIFIES THE FUNCTION TO CHECK IFPOSITION_ID
is not equal to_NO_ID
before executing the function.
getPositionValue
This function returns the USD value of the total collateral of the specified position considering yields generated from the collaterals.
Parameters
Name | Type | Description |
---|---|---|
| uint256 | The position ID to query for position value information |
Return:
positionValue
(uin256): The USD value of the total collateral of the specified position.
getDebtValue
This function should be called to get the current USD value of a position's debt. This function should be called after calling accrue()
to get the current debt balance.
Parameters:
Name | Type | Description |
---|---|---|
| uint256 | The position ID to query for position debt value information |
Return:
debtValue
(uint256): The USD value of the position's debt
getIsolatedCollateralValue
This function returns the USD value of the isolated collateral of a given position. It takes into consideration the stored lending interest in the position. This function should be called after calling accrue()
to get the current debt.
Parameters:
Name | Type | Description |
---|---|---|
| uint256 | The position ID to query for position's isolated collateral value information |
Return:
icollValue
(uint256): The USD value of the position's collateral.
getPositionRisk
This function calculates the risk ratio of a given position, which represents the degree of risk associated with the position. The higher the risk ratio, the higher the risk. By taking into consideration the following factors:
pv
(uint256): The position valueov
(uint256): The debt valuecv
(uint256): The isolated collateral value
If the position is closed or overcollateralized, the risk is set to 0. If there is no isolated collateral or there is an error with the isolated underlying token, the risk is set to the maximum value of Constants.DENOMINATOR
. Otherwise, the risk is calculated as (ov - pv) * Constants.DENOMINATOR / cv
Parameters:
Name | Type | Description |
---|---|---|
| uint256 | The position ID to query for the position's risk |
Returns:
risk
(uint256): The calculated risk ratio
isLiquidatable
This function checks whether a given position can be liquidated by first calculating its risk ratio using the getPositionRisk
function. It then compares the risk ratio to the liquidation threshold defined in the oracle for the underlying token of the position. If the risk ratio is higher than or equal to the liquidation threshold, the position is considered liquidatable and the function returns true
. Otherwise, the function returns false
.
Parameters:
Name | Type | Description |
---|---|---|
| uint256 | The position ID to query for the position's liquidation status. |
Returns:
bool: A boolean value indicating whether the position is liquidatable or not.
liquidate
This function liquidates a position, paying off its debt for the original owner and taking the collateral of the position.
Parameters:
Name | Type | Description |
---|---|---|
| uint256 | The ID of the position to liquidate |
| address | The debt token to repay |
| uint256 | The amount ot repay when doing |
Details:
Check if the repay operation is allowed
Check if the
amountCall
parameter is non-zeroCheck if the position is liquidatable using the
isLiquidatable
functionRetrieve the position and bank information
Calculate the amount paid and the share of the debt to repay using the
_repay
functionCalculate the liquidation size and the share of the underlying vault using the
oldShare
value, thecollateralSize
, and theunderlyingValueShare
fields of this positionUpdate the
collateralSize
andunderlyingVaultShare
fields of the positionTransfer the position (wrapped LP tokens) to the liquidator using the
safeTransferFrom
function of the ERC1155 tokenTransfer the underlying collateral (vault share tokens) to the liquidator using the
safeTransfer
function of the ERC20 token for a soft vault or thesafeTransferFrom
function of the ERC1155 token for a hard vault.Emit the
positionId
of the position liquidated,msg.sender
the address of the liquidator,debtToken
The token address that got repaid,amountPaid
How much did the liquidator pay to the bank,share
the share of the vault tokens,liqSize
how large the liquidation was, anduVaultShare
the underlying vault token share.
execute
This function allows the called to execute a spell with supplied data. The spell must be whitelisted before execution. If the positionID is zero, a new position will be created. If it is not zero, the function will check if the position exists, and is owned by the caller, and if not, it will revert. The function will set the global variables POSITION_ID
and SPELL
to the supplied positionID
and spell
, respectively. It will then execute the spell with the supplied data and handle any errors that may occur. Finally, it will check if the position is liquidatable and emit an event.
Modifiers
onlyEOAEx
: The function can only be called by an externally-owned account that is executing a spell
Parameters
Name | Type | Description |
---|---|---|
| uint256 | The position ID to execute the action, or zero for new position |
| address | The target spell to invoke the execution |
| bytes memory | Extra data to pass to the target for the execution |
Return:
(uint256): The position ID that was executed and created.
lend
This function allows the called to lend tokens to the bank as isolated collateral. The function must be called while under execution. The token must be whitelisted before lending.
Modifiers:
inExec
: The function can only be called while under executionpoke(token)
: The function will poke the token before execution to ensure its balance and allowance is up-to-dateonlyWhitelistedToken(token)
: The function can only be called with a whitelisted token
Parameters
Name | Type | Description |
---|---|---|
| address | The token to be deposited in the bank as isolated collateral |
| uint256 | The amount of tokens to be lent |
withdrawLend
This function withdraws isolated collateral tokens that were lent to the bank. It first checks if the withdrawLend function is allowed to execute. It then retrieves the Position storage and Bank memory objects from their respective mappings. If the token address does not match the underlying token address in the Position storage, the function throws an INVALID_UTOKEN
error.
If shareAmount
is equal to type(uint256).max
, the function sets shareAmount
to the underlyingVaultShare stored in the Position storage.
The function then calculates the amount to withdraw using either the softVault or hardVault. If _isSoftVault(token)
returns true, the function calls the approve
and withdraw
functions of the ISoftVault
interface. If it returns false, the function calls the withdraw
function of the IHardVault
interface.
After the tokens are withdrawn, the underlyingVaultShare stored in the Position storage is updated, the tokens are approved for transfer to the feeManager
contract, and the withdrawal fee is taken by calling the doCutWithdrawFee
function of the feeManager
contract. Finally, the tokens are transferred to the caller.
Modifiers:
inExec
: This modifier checks if the function is being called from the spell contract while under executionpoke
: This modifier updates the state of the contract by calling the poke method with the given token address
Parameters:
Name | Type | Description |
---|---|---|
| address | The token address of the isolated collateral token to be withdrawn |
| uint256 | The number of share tokens to be withdrawn |
borrow
This function allows the caller to borrow tokens from the bank. It first checks if the borrow function is allowed to execute. It then retrieves the Bank storage and Position storage objects from their respective mappings. If the Position storage has no debt token set, it sets the token. This function can only be called from the spell contract while under execution
Modifiers:
inExec
: This modifier checks if the function is being called from the spell contract while under executionpoke
: This modifier updates the state of the contract by calling the poke method with the given token addressonlyWhitelistedToken
: This modifier checks if the given token address is whitelisted
Parameters:
Name | Type | Description |
---|---|---|
| address | The token to borrow from the bank |
| uint256 | The number of tokens to borrow |
Return:
borrowedAmount
(uint256): The number of tokens borrowed.
repay
This function allows a user to repay a specific token to the bank. It should only be called during execution. Before executing the function, it checks whether the repay is allowed. If the repay is not allowed, it will revert with an error message.
The function then calls the internal function _repay()
with the position ID, token, and amountCall as parameters. _repay()
calculates the amount to be repaid and the corresponding debt share reduced. The function then emits a Repay
event with the relevant parameters.
Modifiers:
inExec
: This modifier checks if the function is being called from the spell contract while under executionpoke
: This modifier updates the state of the contract by calling the poke method with the given token addressonlyWhitelistedToken
: This modifier checks if the given token address is whitelisted
Parameters:
Name | Type | Description |
---|---|---|
| address | The token to be repaid to the bank |
| uint256 | The number of tokens to be repaid via |
_repay
This function is used to perform a repayment action on a given position ID, using the specified token. It returns the amount actually taken and the debt share reduced. The debt token of the position must match the specified token, otherwise, the function will revert. The amount to repay must not exceed the old debt, otherwise, the function will revert. The function must be called while under execution.
Parameters:
Name | Type | Description |
---|---|---|
| uint256 | The position ID to query for repayment of debt |
| address | The token to be repaid to the bank |
| uint256 | The number of tokens to be repaid via |
Returns:
Name | Type | Description |
---|---|---|
| uint | The amount actually taken from the user |
| uint | The debt share reduced from the position after repayment. |
putCollateral
This function allows users to put more collateral into their position. The function first checks if the collateral token being used is the same as the one already specified in the position. If not, it checks if the oracle supports the wrapped token of the LP address. If the collateral size of the position is greater than zero, it reverts. If both checks pass, the collateral token and ID are updated in the position.
The function then calls the internal _doERC1155TransferIn() function to transfer the ERC1155 tokens from the user's wallet to the contract. The amount of tokens transferred is added to the position's collateral size. An event PutCollateral() is then emitted to signify that collateral has been added to the position.
Modifiers:
inExec
Can only be called during execution
Parameters:
Name | Type | Description |
---|---|---|
| address | The address of the token that will be used as collateral |
| uint256 | The token ID that corresponds to the specific ERC1155 toke being used as collateral. |
| uint256 | The amount of ERC1155 tokens to be put as collateral by calling |
takeCollateral
This function allows users to take some of their collateral back. It must only be called during execution. The function first retrieves the position from the positions mapping. If the amount to be taken back is set to the maximum uint256 value, it sets the amount to the full collateral size of the position. Then, it reduces the collateral size of the position by the amount being taken back.
The function then calls the safeTransferFrom() function of the IERC1155Upgradeable interface to transfer the ERC1155 tokens from the contract back to the user's wallet. An event TakeCollateral() is emitted to signify that collateral has been taken back from the position. The amount of tokens taken back is returned.
Modifiers:
inExec
Can only be called during execution
Parameters:
amount
(uint256): The amount of ERC1155 tokens to be taken back by transfer
_doBorrow
This function is used to perform a borrow from a bank and returns the amount borrowed.
Parameters:
Name | Type | Description |
---|---|---|
| address | The token address to perform borrow action |
| uint256 | The amount ot use in the |
Returns:
borrowAmount
(uint256): The amount actually borrowed from the bank
_doRepay
This function is used to perform a repay to the bank and returns the amount actually repaid.
Parameters:
Name | Type | Description |
---|---|---|
| address | The token address to perform repay action |
| uint256 | The amount ot use in the |
Returns:
repaidAmount
(uint256): The amount actually repaid to the bank
_doERC20TransferIn
This function is used to perform an ERC20 transfer-in and return the amount actually received.
Parameters:
Name | Type | Description |
---|---|---|
| address | The token address to perform transfer action |
| uint256 | The amount ot use in the |
Returns:
(uint256): The amount actually received from the transfer
_doERC1155TransferIn
This function is used to perform an ERC1155 transfer-in and return the amount actually received.
Parameters:
Name | Type | Description |
---|---|---|
| address | The token address to perform transfer action |
| uint256 | The id to perform the transfer action for |
| uint256 | The amount ot use in the |
Returns:
(uint256): The amount actually received from the transfer
_isSoftVault
This function checks whether the given token
address corresponds to a soft vault or hard vault. The function accesses the banks
mapping to retrieve the softVault
address for the given token
. It then calls the uToken()
function of the ISoftVault
interface to get the underlying token address of the soft vault. If the retrieved underlying token address is equal to the given token
, then the vault is a soft vault and the function returns true
. Otherwise, it returns false
.
Parameters:
token
(address): The token address to check
Returns:
bool
:true
if the vault is a soft vault,false
if it is a hard vault
_ensureApprove
This function is used to reset the approval for spender
to zero and set it again to amount
. The function calls the approve
function of the IERC20Upgradeable
interface to reset the approval to zero and then calls it again to set the approval to amount
Parameters:
Name | Type | Description |
---|---|---|
| address | the token adress to approve |
| address | the address of the spender to approve |
| uint256 | the amount to approve |
Last updated