generated from transmissions11/dapptools-template
-
Notifications
You must be signed in to change notification settings - Fork 14
/
TurboRouter.sol
173 lines (134 loc) · 5.94 KB
/
TurboRouter.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.10;
import {TurboMaster} from "./TurboMaster.sol";
import {TurboSafe} from "./TurboSafe.sol";
import {ENSReverseRecordAuth} from "./ens/ENSReverseRecordAuth.sol";
import {IERC4626, ERC4626RouterBase, IWETH9, PeripheryPayments} from "ERC4626/ERC4626RouterBase.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import {ERC4626} from "solmate/mixins/ERC4626.sol";
import {Auth, Authority} from "solmate/auth/Auth.sol";
/**
@title a router which can perform multiple Turbo actions between Master and the Safes
@notice routes custom users flows between actions on the master and safes.
Extends the ERC4626RouterBase to allow for flexible combinations of actions involving ERC4626 and permit, weth, and Turbo specific actions.
Safe Creation has functions bundled with deposit (and optionally boost) because a newly created Safe address can only be known at runtime.
The caller is always atomically given the owner role of a new safe.
Authentication requires the caller to be the owner of the Safe to perform any ERC4626 method or TurboSafe requiresAuth method.
Assumes the Safe's authority gives permission to call these functions to the TurboRouter.
*/
contract TurboRouter is ERC4626RouterBase, ENSReverseRecordAuth {
using SafeTransferLib for ERC20;
TurboMaster public immutable master;
constructor (TurboMaster _master, address _owner, Authority _authority, IWETH9 weth) Auth(_owner, _authority) PeripheryPayments(weth) {
master = _master;
}
modifier authenticate(address target) {
require(msg.sender == Auth(target).owner() || Auth(target).authority().canCall(msg.sender, target, msg.sig), "NOT_AUTHED");
_;
}
function createSafe(ERC20 underlying) external returns (TurboSafe safe) {
(safe, ) = master.createSafe(underlying);
safe.setOwner(msg.sender);
}
function createSafeAndDeposit(ERC20 underlying, address to, uint256 amount, uint256 minSharesOut) external returns (TurboSafe safe) {
(safe, ) = master.createSafe(underlying);
// approve max from router to save depositor gas in future.
approve(underlying, address(safe), type(uint256).max);
super.deposit(IERC4626(address(safe)), to, amount, minSharesOut);
safe.setOwner(msg.sender);
}
function createSafeAndDepositAndBoost(
ERC20 underlying,
address to,
uint256 amount,
uint256 minSharesOut,
ERC4626 boostedVault,
uint256 boostedFeiAmount
) public returns (TurboSafe safe) {
(safe, ) = master.createSafe(underlying);
// approve max from router to save depositor gas in future.
approve(underlying, address(safe), type(uint256).max);
super.deposit(IERC4626(address(safe)), to, amount, minSharesOut);
safe.boost(boostedVault, boostedFeiAmount);
safe.setOwner(msg.sender);
}
function createSafeAndDepositAndBoostMany(
ERC20 underlying,
address to,
uint256 amount,
uint256 minSharesOut,
ERC4626[] calldata boostedVaults,
uint256[] calldata boostedFeiAmounts
) public returns (TurboSafe safe) {
(safe, ) = master.createSafe(underlying);
// approve max from router to save depositor gas in future.
approve(underlying, address(safe), type(uint256).max);
super.deposit(IERC4626(address(safe)), to, amount, minSharesOut);
unchecked {
require(boostedVaults.length == boostedFeiAmounts.length, "length");
for (uint256 i = 0; i < boostedVaults.length; i++) {
safe.boost(boostedVaults[i], boostedFeiAmounts[i]);
}
}
safe.setOwner(msg.sender);
}
function deposit(IERC4626 safe, address to, uint256 amount, uint256 minSharesOut)
public
payable
override
authenticate(address(safe))
returns (uint256)
{
return super.deposit(safe, to, amount, minSharesOut);
}
function mint(IERC4626 safe, address to, uint256 shares, uint256 maxAmountIn)
public
payable
override
authenticate(address(safe))
returns (uint256)
{
return super.mint(safe, to, shares, maxAmountIn);
}
function withdraw(IERC4626 safe, address to, uint256 amount, uint256 maxSharesOut)
public
payable
override
authenticate(address(safe))
returns (uint256)
{
return super.withdraw(safe, to, amount, maxSharesOut);
}
function redeem(IERC4626 safe, address to, uint256 shares, uint256 minAmountOut)
public
payable
override
authenticate(address(safe))
returns (uint256)
{
return super.redeem(safe, to, shares, minAmountOut);
}
function slurp(TurboSafe safe, ERC4626 vault) external authenticate(address(safe)) {
safe.slurp(vault);
}
function boost(TurboSafe safe, ERC4626 vault, uint256 feiAmount) public authenticate(address(safe)) {
safe.boost(vault, feiAmount);
}
function less(TurboSafe safe, ERC4626 vault, uint256 feiAmount) external authenticate(address(safe)) {
safe.less(vault, feiAmount);
}
function lessAll(TurboSafe safe, ERC4626 vault) external authenticate(address(safe)) {
safe.less(vault, vault.maxWithdraw(address(safe)));
}
function sweep(TurboSafe safe, address to, ERC20 token, uint256 amount) external authenticate(address(safe)) {
safe.sweep(to, token, amount);
}
function sweepAll(TurboSafe safe, address to, ERC20 token) external authenticate(address(safe)) {
safe.sweep(to, token, token.balanceOf(address(safe)));
}
function slurpAndLessAll(TurboSafe safe, ERC4626 vault) external authenticate(address(safe)) {
safe.slurp(vault);
safe.less(vault, vault.maxWithdraw(address(safe)));
}
}