Audits

Sharpe Vault

Automated smart contracts for vast investment strategies.

Smart Contract Name: Sharpe
Token Name: Sharpe
Prepared by: Sage Osoro | Senior Solidity Developer at Sharpe

Amounts of dormant token1 held in the vaultSharpe's functions

Code
_baseLowerSharpeAI.sol
Some of the functions you will find inherit from uniswap interfaces.
  1. 1.
    Internal Functions
1.1 _poke(int24 tickLower, int24 tickUpper) internal
This does zero-burns to poke a position on Uniswap so vault’s earned fees are updated.
Name
Type
Description
tickLower
int24
The lower tick of the vault’s position range
tickUpper
int24
The upper tick of the vault’s position range
1.2 _calcSharesAndAmounts(uint256 amount0Desired, uint256 amount1Desired) internal view returns (uint256 shares,uint256 amount0,uint256 amount1)
Returns the largest possible amounts of token0 and token1(the token pairs) to store from the recipient address such that they are in the same proportion as the total amount of tokens the vault already holds but not greater than the desired amounts the recipient wants for deposit. It also calculates the shares the recipient address would receive for the tokens about to be stored.
Name
Type
Description
amount0Desired
uint256
The amount of token0 wanted for deposit by recipient or vault
amount1Desired
uint256
The amount of token1 wanted for deposit by recipient or vault
shares
uint256
The amount of SharpeAI tokens recipient’s address would receive
amount0
uint256
The amount of token0 the vault can store proportional to total amounts
amount1
uint256
The amount of token1 the vault can store proportional to total amounts
1.3 _burnLiquidityShare(int24 tickLower,int24 tickUpper,uint256 shares,uint256 totalSupply ) internal returns (uint256 amount0, uint256 amount1)
Takes out liquidity from uniswap position proportional to the amount of shares recipient burned at the point of withdrawal.
Name
Type
Description
tickLower
int24
The lower tick of the vault’s position range
tickUpper
int24
The upper tick of the vault’s position range
shares
uint256
The amount of SharpeAI tokens burned from recipient’s address
totalSupply
uint256
The total supply of SharpeAI tokens in circulation
amount0
uint256
Amounts of token0 taken out of vault’s liquidity position
amount1
uint256
Amounts of token1 taken out of vault’s liquidity position
1.4 _checkRange(int24 tickLower, int24 tickUpper) internal view
Ensures that range of tickLower and tickUpper are within the specified ranges before allowing a rebalance.
tickLower
int24
The lower tick of the vault’s position range
tickUpper
int24
The upper tick of the vault’s position range
1.5 _burnAndCollect(int24 tickLower,int24 tickUpper,uint128 liquidity) internal returns (uint256 burned0,uint256 burned1,uint256 feesToVault0,uint256 feesToVault1)
Burns uniswap liquidity in a range and collects all fees in the process.
Name
Type
Description
tickLower
int24
The lower tick of the vault’s position range
tickUpper
int24
The upper tick of the vault’s position range
liquidity
uint128
Liquidity amount to burn out of vault’s position on uniswap
burned0
uint256
The amount of token0 the vault recieves from its uniswap position
burned1
uint256
The amount of token1 the vault recieves from its uniswap position
feesToVault0
uint256
The amount of token0 fees collected from the vault’s uniswap position
feesToVault1
uint256
The amount of token1 fees collected from the vault’s uniswap position
1.6 _mintLiquidity(int24 tickLower,int24 tickUpper,uint128 liquidity) internal
Deposits liquidity in a range on the Uniswap pool.
Name
Type
Description
tickLower
int24
The lower tick of the vault’s position range
tickUpper
int24
The upper tick of the vault’s position range
liquidity
uint128
Liquidity amount to mint into vault’s uniswap position
1.7 _position(int24 tickLower, int24 tickUpper) internal view returns (uint128,uint256,uint256,uint128,uint128)
This is the wrapper around `IUniswapV3Pool.positions()`. The vault smart contract uses this function to view its liquidity and owed tokens. The smart contract fetches only the three int128 return values(liquidity, token0 owed and token1 owed) from the bytes 32 array.
Name
Type
Description
tickLower
int24
The lower tick of the vault’s position range
tickUpper
int24
The upper tick of the vault’s position range
uint128
Liquidity
uint128
Amount of token0 owed
uint128
Amount of token1 owed
1.8 amountsForLiquidity(int24 tickLower,int24 tickUpper,uint128 liquidity ) internal view returns (uint256, uint256)
This is the wrapper around `LiquidityAmounts.getAmountsForLiquidity()`.The vault smart contract uses this function to view the amounts of tokens excluding tokens owed in its uniswap position.
Name
Type
Description
tickLower
int24
The lower tick of the vault’s position range
tickUpper
int24
The upper tick of the vault’s position range
liquidity
uint128
Liquidity
uint256
Amounts of token0 in vault’s uniswap position
uint256
Amounts of token1 in vault’s uniswap position
1.9 _liquidityForAmounts(int24 tickLower,int24 tickUpper,uint256 amount0,uint256 amount1 ) internal view returns (uint128)
This is the wrapper around
`LiquidityAmounts.getLiquidityForAmounts()`. The vault smart contract uses this function to view the maximum amount of liquidity it can receive for a given amount0 and amount1 (amount of tokens)
Name
Type
Description
tickLower
int24
The lower tick of the vault’s position range
tickUpper
int24
The upper tick of the vault’s position range
amount0
uint256
The amount of token0 being sent
amount1
uint256
The amount of token1 being sent
uint128
Maximum amount of liquidity to receive
1.10 _toUint128(uint256 x) internal pure returns (uint128)
Casts uint256 to uint128 with overflow check.
Name
Type
Description
x
uint256
Amount to convert
uint128
Conversion return value
2. External Functions (Read-Only and Write)
2.1 Read-Only
2.1.1 getTotalAmounts() public view override returns (uint256 total0, uint256 total1)
Calculates the vault's total holdings of token0 and token1 i.e how much of each token the vault would hold if it withdrew all its liquidity from Uniswap.
Name
Type
Description
totalo
uint256
Total amount of token1 in the vault and in vault’s uniswap position
total1
uint256
Total amount of token1 in the vault and in vault’s uniswap position
2.1.2 getPositionAmounts(int24 tickLower, int24 tickUpper) public view returns (uint256 amount0, uint256 amount1)
Calculates the amounts of token0 and token1 held in vault's position. Includes owed fees but excludes the proportion of fees that will be paid to the protocol. Doesn't include fees gathered since last poke.
Name
Type
Descritpion
tickLower
int24
The lower tick of the vault’s position range
tickUpper
int24
The upper tick of the vault’s position range
amount0
uint256
Amounts of token0 currently in the vault’s uniswap position
amount1
uint256
Amounts of token1 currently in the vault’s uniswap position
2.1.3 getBalance0() public view returns (uint256)
This gets the balance of token0 in held the vault but not used in any uniswap position
Type
Descritpion
uint256
Amounts of dormant token0 held in the vault
2.1.4 getBalance1() public view returns (uint256)
This gets the balance of token1 in held the vault but not used in any uniswap position
Type
Description
uint256
Amounts of dormant token1 held in the vault
2.2 Write
2.2.1 deposit(uint256 amount0Desired,uint256 amount1Desired,uint256 amount0Min,uint256 amount1Min,uint256 swapMin, address to) external override nonReentrant returns (uint256 shares,uint256 amount0,uint256 amount1)
At the point of deposit the smart contract first tries to calculate the amount0 and amount1 to transfer from the recipient’s address. If amount 0 and amount1 are already provided (i.e both tokens > 0) the contract mints out shares(SharpeAI) to the recipient address. If the recipient has only one of the vault’s token pairs, the contract takes in the single token and splits it in half in order to perform a swap with the difference and get the second token. The two token amounts are then calculated again after the swap and the recipient’s equivalent shares are minted. Any dust left after the swap is also sent back to the recipient. This swapping process is called Zapp.
Name
Type
Description
amount0Desired
uint256
Amount of token0 recipient wants to deposit
amount1Desired
uint256
Amount of token1 recipient wants to deposit
amount0Min
uint256
Minimum amount of token0 recipient deposits
amount1Min
uint256
Minimum of amount token1 recipient deposits
swapMin
uint256address
Minimum amount of either token0 or token1 the vault receives after a swap is made
to
address
Address of recipient
shares
uint256
Amount of SharpeAI tokens minted to recipient address
amount0
uint256
Actual amount of token0 stored in the vault after deposit
amount1
uint256
Actual amount of token1 stored in the vault after deposit
2.2.2 withdraw(uint256 shares,uint256 amount0Min,uint256 amount1Min,address to ) external override nonReentrant returns (uint256 amount0, uint256 amount1)
At the point of withdrawal, the shares (SharpeAI tokens) of the recipient are burned and the proportional liquidity amount of recipient tokens and fees are redeemed from uniswap to the recipient address. Unused token amounts (i.e dormant tokens) in the vault proportional to the SharpeAI tokens burned are also added to the tokens redeemed from uniswap. If the recipient had deposited a single token via Zapp swap, the recipient would receive both tokens of the vault’s pairs.
Name
Type
Description
shares
uint256
Amount of SharpeAI tokens burned from recipient address
amount0Min
uint256
Minimum amount of token0 recipient receives
amount1Min
uint256
Minimum amount of token1 recipient receives
amount1Min
uint256
Minimum of amount token1 recipient wants to deposit
to
address
Address of recipient
amount0
uint256
Actual amount of token0 recipient receives
amount1
uint256
Actual amount of token1 recipient receives
2.2.3 rebalance(int256 swapAmount,uint160 sqrtPriceLimitX96,int24 _baseLower,int24 _baseUpper, int24 _bidLower,int24 _bidUpper,int24 _askLower,int24 _askUpper ) external nonReentrant
This updates the vault’s uniswap position by placing the bid orders. Two orders are placed - a base order and a limit order. The base order is placed first with as much liquidity as possible. This order uses up all of one token, leaving only the other. The excess amount is then placed as a single-sided bid or ask order. The parameters for the transaction are set by the SharpeKeeper(strategy) during every rebalance call.
Name
Type
Description
swapAmount
int256
Amount of tokens to swap in the vault’s uniswap position
sqrtPriceLimitX96
uint160
The price limit of the pool that cannot be exceeded by the swap
_baseLower
int24
The lower tick value of the new position range for the most used token
_baseUpper
int24
The upper tick value of the new position range for the most used token
_bidLower
int24
The lower tick value of the new position range if token left is token0
_bidUpper
int24
The upper tick value of the new position range if token left is token0
_askLower
int24
The lower tick value of the new position range if token left is token1
_askUpper
int24
The upper tick value of the new position range if token left is token1
2.2.4 uniswapV3MintCallback(uint256 amount0, uint256 amount1, bytes calldata data) external override
Mint callback for uniswap V3 pool. Accessible by only the uniswap pool address.
Name
Type
Description
amount0
uint256
The amount of token0 due to the pool for the minted liquidity
amount1
uint256
The amount of token1 due to the pool for the minted liquidity
data
bytes
Any data passed through by the caller via the IUniswapV3PoolActions#mintcall
2.2.5 uniswapV3SwapCallback(int256 amount0Delta,int256 amount1Delta,bytes calldata data) external override
Swap callback for uniswap V3 pool. Accessible by only the uniswap pool address.
Name
Type
Description
amount0Delta
int256
The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool
amount1Delta
int256
The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool
data
bytes
Any data passed through by the caller via the IUniswapV3PoolActions#swapcallback
2.2.6 sweep(IERC20 token,uint256 amount,address to) external onlyGovernance
This removes any foreign token accidentally sent to the vault out. For example, if LINK tokens were sent to the USDC/USDT vault address the LINK tokens can be removed by Governance address. Please note that the Governance address has no access to any of the vault token pairs i.e USDC or USDT since the smart contract requires only that the token to sweep be neither token0 nor token1:
Name
Type
Description
token
IERC20
Contract address of token to sweep
amount
uint256
Amount of foreign token to sweep
to
address
Address to receive foreign tokens
2.2.7 setSharpeKeeper(address _SharpeKeeper) external onlyGovernance
The strategy smart contract is set by this function. It is set only by the Governance address. @Dev deploys the strategy smart contract and then the Governance address sets the SharpeKeeper to the strategy smart contract @Dev deployed. Governance can always change the strategy the vault uses for rebalancing on uniswap.
Name
Type
Description
_SharpeKeeper
address
Address of the vault’s rebalance strategy
2.2.8 setProtocolFee(uint256 _protocolFee) external onlyGovernance
Changes the protocol fee charged on pool fees earned from Uniswap, expressed as multiple of 1e-6. Set by only the Governance address.
Name
Type
Description
_protocolFeeuint256
uint256
Amount the vault charges from earned feesuint256
2.2.9 collectProtocol(uint256 amount0, uint256 amount1, address to) external onlyGovernance
Collects fees charged by the vault. Accessible by only the Governance address.
Name
Type
Description
amount0
uint256
Amount of token0 fees to transfer from vault
amount1
uint256
Amount of token1 fees to transfer from the vault
to
address
Address to receive the fees
2.2.10 emergencyBurn(int24 tickLower,int24 tickUpper,uint128 liquidity) external onlyGovernance
Removes all liquidity of token0 and token1 in the case of an emergency from uniswap. Function accessible only by the Governance Address
Name
Type
Description
tickLower
int24
The lower tick of the vault’s position range
tickUpper
int24
The upper tick of the vault’s position range
liquidity
uint128
Liquidity amount to burn from vault’s uniswap position
2.2.11 setGovernance(address _governance) external onlyGovernance
Sets the new address for governance. Governance address is not updated until the new governance address has called `acceptGovernance()` to accept this responsibility.
Name
Type
Description
_governance
address
Address to accept Govenance
2.2.12 acceptGovernance() external
`setGovernance()` should be called by the existing governance address prior to calling this function.
Furthermore, onlyGovernance is a modifier in the smart contract which when seen on any function means that only the Governance address can access that function:
Copy link
Outline
Sharpe Vault
Amounts of dormant token1 held in the vaultSharpe's functions