generated from PaulRBerg/foundry-template
-
Notifications
You must be signed in to change notification settings - Fork 3
/
BalancerWrapper.sol
79 lines (62 loc) · 2.51 KB
/
BalancerWrapper.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
// SPDX-License-Identifier: MIT
// Thanks to ultrasecr.eth
pragma solidity ^0.8.19;
import { IFlashLoanRecipient } from "./interfaces/IFlashLoanRecipient.sol";
import { IFlashLoaner } from "./interfaces/IFlashLoaner.sol";
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
import { Arrays } from "../utils/Arrays.sol";
import { WAD } from "../utils/constants.sol";
import { BaseWrapper, IERC7399, IERC20 } from "../BaseWrapper.sol";
/// @dev Balancer Flash Lender that uses Balancer Pools as source of liquidity.
/// Balancer allows pushing repayments, so we override `_repayTo`.
contract BalancerWrapper is BaseWrapper, IFlashLoanRecipient {
using Arrays for uint256;
using Arrays for address;
error NotBalancer();
error HashMismatch();
IFlashLoaner public immutable balancer;
bytes32 private flashLoanDataHash;
constructor(IFlashLoaner _balancer) {
balancer = _balancer;
}
/// @inheritdoc IERC7399
function maxFlashLoan(address asset) external view returns (uint256) {
return _maxFlashLoan(asset);
}
/// @inheritdoc IERC7399
function flashFee(address asset, uint256 amount) external view returns (uint256) {
uint256 max = _maxFlashLoan(asset);
require(max > 0, "Unsupported currency");
return amount >= max ? type(uint256).max : _flashFee(amount);
}
/// @inheritdoc IFlashLoanRecipient
function receiveFlashLoan(
address[] memory assets,
uint256[] memory amounts,
uint256[] memory fees,
bytes memory params
)
external
override
{
if (msg.sender != address(balancer)) revert NotBalancer();
if (keccak256(params) != flashLoanDataHash) revert HashMismatch();
delete flashLoanDataHash;
_bridgeToCallback(assets[0], amounts[0], fees[0], params);
}
function _flashLoan(address asset, uint256 amount, bytes memory data) internal override {
flashLoanDataHash = keccak256(data);
balancer.flashLoan(this, asset.toArray(), amount.toArray(), data);
}
function _repayTo() internal view override returns (address) {
return address(balancer);
}
function _flashFee(uint256 amount) internal view returns (uint256) {
return Math.mulDiv(
amount, balancer.getProtocolFeesCollector().getFlashLoanFeePercentage(), WAD, Math.Rounding.Ceil
);
}
function _maxFlashLoan(address asset) internal view returns (uint256) {
return IERC20(asset).balanceOf(address(balancer));
}
}