Blueberry Bank Contract
Last updated
Last updated
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
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:
oracle
address
The oracle smart contract address
config_
address
The Protocol config smart contract adress
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
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 set allowContractCalls
to. If false
, only EOA can call the contract.
This function sets the status of the given contracts in the whitelist. The function can only be called by the contract owner.
Parameters:
contracts
Array
An array of contract addresses to change the status of.
statuses
Array
An array of boolean values to change the status of the corresponding contract address in contracts
.
This function sets the status of the given spells in the whitelist. The function can only be called by the contract owner.
Parameters:
spells
Array
An array of contract addresses to change the status of.
statuses
Array
An array of boolean values to change the status of the corresponding contract address in spells
.
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:
tokens
Array
An array of contract addresses to change the status of.
statuses
Array
An array of boolean values to change the status of the corresponding contract address in tokens
.
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:
tokens
Array
An array of contract addresses to change the status of.
ok
bool
The status of the corresponding whitelisted wrapped tokens in tokens
.
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:
token
Address
The address of the underlying token for the bank
softvault
Address
The address of the soft vault for the bank
hardvault
Address
The address of the hard vault for the bank
liqThreshold
uint256
The numerical value for liquidation threshold for the bank
This function is used to set the bank status to a new value. Only callable by the owner
Parameters:
_bankStatus
uint256
The new bank status value to set
Modifiers
onlyOwner
: Only the contract owner can call this function
Return
None
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.
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.
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.
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.
This function is used to trigger interest accrual for the given bank.
Parameters:
token
address
The underlying token for which interest accrual needs to be triggered
This function is used to trigger interest accrual for a list of banks.
Parameters:
tokens
array
The list of underlying tokens for which interest accrual needs to be triggered.
Modifiers:
None
Return:
None
This internal function is used to get the stored borrow balance for the given token
Parameters:
token
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.
This function returns the debt of a given position considering the debt interest stored.
Parameters:
positionId
uint256
The ID of the position to query for the debt balance
Return:
debt
uint256: The current debt balance of the specified position.
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:
positionId
uint256
The ID of the position to query for the debt balance
Modifiers:
None
Returns:
debt
(uint256): The debt balance of the specified position.
This function returns the bank information for the specified token.
Parameters:
token
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 false
bToken
(address): The address of the associated bToken contract for the specified token
totalShare
(uin256): The total share of the specified token in the bank
This function returns the information of the specified position.
Parameters:
positionId
uint256
The position ID to query for position information
Modifiers:
None
Returns:
Position
(struct): The information about the specified position
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 IF POSITION_ID
is not equal to _NO_ID
before executing the function.
This function returns the USD value of the total collateral of the specified position considering yields generated from the collaterals.
Parameters
positionId
uint256
The position ID to query for position value information
Return:
positionValue
(uin256): The USD value of the total collateral of the specified position.
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:
positionId
uint256
The position ID to query for position debt value information
Return:
debtValue
(uint256): The USD value of the position's debt
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:
positionId
uint256
The position ID to query for position's isolated collateral value information
Return:
icollValue
(uint256): The USD value of the position's collateral.
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 value
ov
(uint256): The debt value
cv
(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:
positionId
uint256
The position ID to query for the position's risk
Returns:
risk
(uint256): The calculated risk ratio
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:
positionId
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.
This function liquidates a position, paying off its debt for the original owner and taking the collateral of the position.
Parameters:
positionId
uint256
The ID of the position to liquidate
debtToken
address
The debt token to repay
amountCall
uint256
The amount ot repay when doing transferFrom
call
Details:
Check if the repay operation is allowed
Check if the amountCall
parameter is non-zero
Check if the position is liquidatable using the isLiquidatable
function
Retrieve the position and bank information
Calculate the amount paid and the share of the debt to repay using the _repay
function
Calculate the liquidation size and the share of the underlying vault using the oldShare
value, the collateralSize
, and the underlyingValueShare
fields of this position
Update the collateralSize
and underlyingVaultShare
fields of the position
Transfer the position (wrapped LP tokens) to the liquidator using the safeTransferFrom
function of the ERC1155 token
Transfer the underlying collateral (vault share tokens) to the liquidator using the safeTransfer
function of the ERC20 token for a soft vault or the safeTransferFrom
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, and uVaultShare
the underlying vault token share.
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
positionId
uint256
The position ID to execute the action, or zero for new position
spell
address
The target spell to invoke the execution
data
bytes memory
Extra data to pass to the target for the execution
Return:
(uint256): The position ID that was executed and created.
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 execution
poke(token)
: The function will poke the token before execution to ensure its balance and allowance is up-to-date
onlyWhitelistedToken(token)
: The function can only be called with a whitelisted token
Parameters
token
address
The token to be deposited in the bank as isolated collateral
amount
uint256
The amount of tokens to be lent
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 execution
poke
: This modifier updates the state of the contract by calling the poke method with the given token address
Parameters:
token
address
The token address of the isolated collateral token to be withdrawn
shareAmount
uint256
The number of share tokens to be withdrawn
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 execution
poke
: This modifier updates the state of the contract by calling the poke method with the given token address
onlyWhitelistedToken
: This modifier checks if the given token address is whitelisted
Parameters:
token
address
The token to borrow from the bank
amount
uint256
The number of tokens to borrow
Return:
borrowedAmount
(uint256): The number of tokens borrowed.
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 execution
poke
: This modifier updates the state of the contract by calling the poke method with the given token address
onlyWhitelistedToken
: This modifier checks if the given token address is whitelisted
Parameters:
token
address
The token to be repaid to the bank
amountCall
uint256
The number of tokens to be repaid via transferFrom
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:
positionId
uint256
The position ID to query for repayment of debt
token
address
The token to be repaid to the bank
amountCall
uint256
The number of tokens to be repaid via transferFrom
Returns:
paid
uint
The amount actually taken from the user
lessShare
uint
The debt share reduced from the position after repayment.
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:
collToken
address
The address of the token that will be used as collateral
collId
uint256
The token ID that corresponds to the specific ERC1155 toke being used as collateral.
amountCall
uint256
The amount of ERC1155 tokens to be put as collateral by calling transferFrom
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
This function is used to perform a borrow from a bank and returns the amount borrowed.
Parameters:
token
address
The token address to perform borrow action
amountCall
uint256
The amount ot use in the transferFrom
call
Returns:
borrowAmount
(uint256): The amount actually borrowed from the bank
This function is used to perform a repay to the bank and returns the amount actually repaid.
Parameters:
token
address
The token address to perform repay action
amountCall
uint256
The amount ot use in the repayBorrow
call
Returns:
repaidAmount
(uint256): The amount actually repaid to the bank
This function is used to perform an ERC20 transfer-in and return the amount actually received.
Parameters:
token
address
The token address to perform transfer action
amountCall
uint256
The amount ot use in the transferFrom
call
Returns:
(uint256): The amount actually received from the transfer
This function is used to perform an ERC1155 transfer-in and return the amount actually received.
Parameters:
token
address
The token address to perform transfer action
id
uint256
The id to perform the transfer action for
amountCall
uint256
The amount ot use in the transferFrom
call
Returns:
(uint256): The amount actually received from the transfer
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
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:
token
address
the token adress to approve
spender
address
the address of the spender to approve
amount
uint256
the amount to approve