This repository has been archived by the owner on Jan 14, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBridgeLogic.sol
155 lines (132 loc) · 5.82 KB
/
BridgeLogic.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.10;
import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import {GPv2SafeERC20} from '../../../dependencies/gnosis/contracts/GPv2SafeERC20.sol';
import {SafeCast} from '../../../dependencies/openzeppelin/contracts/SafeCast.sol';
import {IAToken} from '../../../interfaces/IAToken.sol';
import {DataTypes} from '../types/DataTypes.sol';
import {UserConfiguration} from '../configuration/UserConfiguration.sol';
import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol';
import {WadRayMath} from '../math/WadRayMath.sol';
import {PercentageMath} from '../math/PercentageMath.sol';
import {Errors} from '../helpers/Errors.sol';
import {ValidationLogic} from './ValidationLogic.sol';
import {ReserveLogic} from './ReserveLogic.sol';
/**
* @title BridgeLogic library
* @author Aave
* @notice Implements functions to mint unbacked aTokens and back the unbacked tokens.
*/
library BridgeLogic {
using ReserveLogic for DataTypes.ReserveCache;
using ReserveLogic for DataTypes.ReserveData;
using UserConfiguration for DataTypes.UserConfigurationMap;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using WadRayMath for uint256;
using PercentageMath for uint256;
using SafeCast for uint256;
using GPv2SafeERC20 for IERC20;
// See `IPool` for descriptions
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
event MintUnbacked(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referralCode
);
event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee);
/**
* @notice Mint unbacked aTokens to a user and updates the unbacked for the reserve.
* @dev Essentially a supply without transferring the underlying.
* @dev Emits the `MintUnbacked` event
* @dev Emits the `ReserveUsedAsCollateralEnabled` if asset is set as collateral
* @param reservesData The state of all the reserves
* @param reservesList The addresses of all the active reserves
* @param userConfig The user configuration mapping that tracks the supplied/borrowed assets
* @param asset The address of the underlying asset to mint aTokens of
* @param amount The amount to mint
* @param onBehalfOf The address that will receive the aTokens
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function executeMintUnbacked(
mapping(address => DataTypes.ReserveData) storage reservesData,
mapping(uint256 => address) storage reservesList,
DataTypes.UserConfigurationMap storage userConfig,
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external {
DataTypes.ReserveData storage reserve = reservesData[asset];
DataTypes.ReserveCache memory reserveCache = reserve.cache();
reserve.updateState(reserveCache);
ValidationLogic.validateSupply(reserveCache, reserve, amount, onBehalfOf);
uint256 unbackedMintCap = reserveCache.reserveConfiguration.getUnbackedMintCap();
uint256 reserveDecimals = reserveCache.reserveConfiguration.getDecimals();
uint256 unbacked = reserve.unbacked += amount.toUint128();
require(
unbacked <= unbackedMintCap * (10 ** reserveDecimals),
Errors.UNBACKED_MINT_CAP_EXCEEDED
);
reserve.updateInterestRatesAndVirtualBalance(reserveCache, asset, 0, 0);
bool isFirstSupply = IAToken(reserveCache.aTokenAddress).mint(
msg.sender,
onBehalfOf,
amount,
reserveCache.nextLiquidityIndex
);
if (isFirstSupply) {
if (
ValidationLogic.validateAutomaticUseAsCollateral(
reservesData,
reservesList,
userConfig,
reserveCache.reserveConfiguration,
reserveCache.aTokenAddress
)
) {
userConfig.setUsingAsCollateral(reserve.id, true);
emit ReserveUsedAsCollateralEnabled(asset, onBehalfOf);
}
}
emit MintUnbacked(asset, msg.sender, onBehalfOf, amount, referralCode);
}
/**
* @notice Back the current unbacked with `amount` and pay `fee`.
* @dev It is not possible to back more than the existing unbacked amount of the reserve
* @dev Emits the `BackUnbacked` event
* @param reserve The reserve to back unbacked for
* @param asset The address of the underlying asset to repay
* @param amount The amount to back
* @param fee The amount paid in fees
* @param protocolFeeBps The fraction of fees in basis points paid to the protocol
* @return The backed amount
*/
function executeBackUnbacked(
DataTypes.ReserveData storage reserve,
address asset,
uint256 amount,
uint256 fee,
uint256 protocolFeeBps
) external returns (uint256) {
DataTypes.ReserveCache memory reserveCache = reserve.cache();
reserve.updateState(reserveCache);
uint256 backingAmount = (amount < reserve.unbacked) ? amount : reserve.unbacked;
uint256 feeToProtocol = fee.percentMul(protocolFeeBps);
uint256 feeToLP = fee - feeToProtocol;
uint256 added = backingAmount + fee;
reserveCache.nextLiquidityIndex = reserve.cumulateToLiquidityIndex(
IERC20(reserveCache.aTokenAddress).totalSupply() +
uint256(reserve.accruedToTreasury).rayMul(reserveCache.nextLiquidityIndex),
feeToLP
);
reserve.accruedToTreasury += feeToProtocol.rayDiv(reserveCache.nextLiquidityIndex).toUint128();
reserve.unbacked -= backingAmount.toUint128();
reserve.updateInterestRatesAndVirtualBalance(reserveCache, asset, added, 0);
IERC20(asset).safeTransferFrom(msg.sender, reserveCache.aTokenAddress, added);
emit BackUnbacked(asset, msg.sender, backingAmount, fee);
return backingAmount;
}
}