Deposit process with the Liquidity Handler
Step 1: User calls deposit with 100 USDC and the funds are sent to the voteExecutor and IbAlluo calls the deposit function.
function deposit(address _token, uint256 _amount) external {
if (supportedTokens.contains(_token) == false) {
IERC20Upgradeable(_token).safeTransferFrom(_msgSender(), address(this), _amount);
(, address primaryToken) = ILiquidityHandler(liquidityHandler).getAdapterCoreTokensFromIbAlluo(address(this));
IERC20Upgradeable(_token).safeIncreaseAllowance(exchangeAddress, _amount);
_amount = IExchange(exchangeAddress).exchange(_token, primaryToken, _amount, 0);
_token = primaryToken;
//Funds are sent to the liquidity Handler
IERC20Upgradeable(primaryToken).safeTransfer(address(liquidityHandler), _amount);
} else {
//Funds are sent to the liquidity Handler
IERC20Upgradeable(_token).safeTransferFrom(_msgSender(),address(liquidityHandler),_amount);
}
updateRatio();
ILiquidityHandler(liquidityHandler).deposit(_token, _amount);
uint256 amountIn18 = _amount * 10**(18 - AlluoERC20Upgradable(_token).decimals());
uint256 adjustedAmount = (amountIn18 * multiplier) / growingRatio;
_mint(_msgSender(), adjustedAmount);
emit TransferAssetValue(address(0), _msgSender(), adjustedAmount, amountIn18, growingRatio);
emit Deposited(_msgSender(), _token, _amount);
}
- 1.If the expectedAdapterAmount (minimum buffer requirement) is not met, the 100 USDC is deposited into the adapter until the buffer is met and any surplus is sent to the treasury.
- 2.If the buffer requirement is already met, the funds are sent directly to the treasury.
LiquidityHandler.sol
1
/** @notice Called by ibAlluo, deposits tokens into the adapter.
2
* @dev Deposits funds, checks whether adapter is filled or insufficient, and then acts accordingly.
3
** @param _token Address of token (USDC, DAI, USDT...)
4
** @param _amount Amount of tokens in correct deimals (10**18 for DAI, 10**6 for USDT)
5
*/
6
function deposit(address _token, uint256 _amount)
7
external
8
whenNotPaused
9
onlyRole(DEFAULT_ADMIN_ROLE)
10
{
11
uint256 amount18 = _amount *
12
10**(18 - ERC20Upgradeable(_token).decimals());
13
14
uint256 inAdapter = getAdapterAmount(msg.sender);
15
uint256 expectedAdapterAmount = getExpectedAdapterAmount(
16
msg.sender,
17
amount18
18
);
19
20
uint256 adapterId = ibAlluoToAdapterId.get(msg.sender);
21
address adapter = adapterIdsToAdapterInfo[adapterId].adapterAddress;
22
23
IERC20Upgradeable(_token).safeTransfer(adapter, _amount);
24
if (inAdapter < expectedAdapterAmount) {
25
//
26
// Case 1
27
//
28
if (expectedAdapterAmount < inAdapter + amount18) {
29
uint256 toWallet = inAdapter + amount18 - expectedAdapterAmount;
30
uint256 leaveInPool = amount18 - toWallet;
31
IHandlerAdapter(adapter).deposit(_token, amount18, leaveInPool);
32
} else {
33
IHandlerAdapter(adapter).deposit(_token, amount18, amount18);
34
}
35
} else {
36
//
37
// Case 2
38
//
39
IHandlerAdapter(adapter).deposit(_token, amount18, 0);
40
}
41
42
WithdrawalSystem storage withdrawalSystem = ibAlluoToWithdrawalSystems[
43
msg.sender
44
];
45
46
if (
47
withdrawalSystem.totalWithdrawalAmount > 0 && !withdrawalSystem.resolverTrigger
48
) {
49
uint256 inAdapterAfterDeposit = getAdapterAmount(msg.sender);
50
uint256 firstInQueueAmount = withdrawalSystem
51
.withdrawals[withdrawalSystem.lastSatisfiedWithdrawal + 1].amount;
52
if (firstInQueueAmount <= inAdapterAfterDeposit) {
53
withdrawalSystem.resolverTrigger = true;
54
emit EnoughToSatisfy(
55
msg.sender,
56
inAdapterAfterDeposit,
57
withdrawalSystem.totalWithdrawalAmount
58
);
59
}
60
}
61
}
62
Here is the logic that occurs in the actual adapter. The funds are either kept in the contract as a buffer for withdrawals, or they are sent to the treasury.
USDCurveAdapter.sol
1
/// @notice When called by liquidity handler, moves some funds to the Gnosis multisig and others into a LP to be kept as a 'buffer'
2
/// @param _token Deposit token address (eg. USDC)
3
/// @param _fullAmount Full amount deposited in 10**18 called by liquidity handler
4
/// @param _leaveInPool Amount to be left in the LP rather than be sent to the Gnosis wallet (the "buffer" amount)
5
function deposit(address _token, uint256 _fullAmount, uint256 _leaveInPool) external onlyRole(DEFAULT_ADMIN_ROLE) {
6
uint256 toSend = _fullAmount - _leaveInPool;
7
address primaryToken = ICurvePoolUSD(curvePool).underlying_coins(primaryTokenIndex);
8
if(_token == primaryToken){
9
if (toSend != 0) {
10
IERC20(primaryToken).safeTransfer(wallet, toSend / 10**(18 - IERC20Metadata(primaryToken).decimals()));
11
}
12
if (_leaveInPool != 0) {
13
uint256[3] memory amounts;
14
amounts[primaryTokenIndex] = _leaveInPool / 10**(18 - IERC20Metadata(primaryToken).decimals());
15
ICurvePoolUSD(curvePool).add_liquidity(amounts, 0, true);
16
}
17
}
18
else{
19
uint256[3] memory amounts;
20
amounts[indexes[_token]] = _fullAmount / 10**(18 - IERC20Metadata(_token).decimals());
21
22
uint256 lpAmount = ICurvePoolUSD(curvePool).add_liquidity(amounts, 0, true);
23
delete amounts;
24
if (toSend != 0) {
25
toSend = toSend / 10**(18 - IERC20Metadata(primaryToken).decimals());
26
amounts[primaryTokenIndex] = toSend;
27
ICurvePoolUSD(curvePool).remove_liquidity_imbalance(
28
amounts,
29
lpAmount * (10000+slippage)/10000,
30
true);
31
IERC20(primaryToken).safeTransfer(wallet, toSend);
32
}
33
}
34
}
Here you can see this logic with the Curve 3pool. In other adapters, funds are just kept as native tokens (ETH, BTC... for IbAlluoBTC, IbAlluoETH) but here the funds are kept as LP tokens. Tokens are converted to a 'primaryToken' with the most liquidity to dissuade arbitrage opportunities upon withdrawals.
Inside the deposit function
1
WithdrawalSystem storage withdrawalSystem = ibAlluoToWithdrawalSystems[
2
msg.sender
3
];
4
5
if (
6
withdrawalSystem.totalWithdrawalAmount > 0 && !withdrawalSystem.resolverTrigger
7
) {
8
uint256 inAdapterAfterDeposit = getAdapterAmount(msg.sender);
9
uint256 firstInQueueAmount = withdrawalSystem
10
.withdrawals[withdrawalSystem.lastSatisfiedWithdrawal + 1].amount;
11
if (firstInQueueAmount <= inAdapterAfterDeposit) {
12
withdrawalSystem.resolverTrigger = true;
13
emit EnoughToSatisfy(
14
msg.sender,
15
inAdapterAfterDeposit,
16
withdrawalSystem.totalWithdrawalAmount
17
);
18
}
19
}
Last modified 11mo ago