forked from sherlock-audit/2023-06-symmetrical
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AccountFacetImpl.sol
158 lines (144 loc) · 6.88 KB
/
AccountFacetImpl.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
// SPDX-License-Identifier: SYMM-Core-Business-Source-License-1.1
// This contract is licensed under the SYMM Core Business Source License 1.1
// Copyright (c) 2023 Symmetry Labs AG
// For more information, see https://docs.symm.io/legal-disclaimer/license
pragma solidity >=0.8.18;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "../../storages/AccountStorage.sol";
import "../../storages/GlobalAppStorage.sol";
import "../../storages/MAStorage.sol";
import "../../storages/MuonStorage.sol";
import "../../libraries/LibMuon.sol";
import "../../libraries/LibAccount.sol";
library AccountFacetImpl {
using SafeERC20 for IERC20;
function deposit(address user, uint256 amount) internal {
GlobalAppStorage.Layout storage appLayout = GlobalAppStorage.layout();
IERC20(appLayout.collateral).safeTransferFrom(msg.sender, address(this), amount);
uint256 amountWith18Decimals = (amount * 1e18) /
(10 ** IERC20Metadata(appLayout.collateral).decimals());
AccountStorage.layout().balances[user] += amountWith18Decimals;
}
function withdraw(address user, uint256 amount) internal {
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
GlobalAppStorage.Layout storage appLayout = GlobalAppStorage.layout();
require(
block.timestamp >=
accountLayout.withdrawCooldown[msg.sender] + MAStorage.layout().deallocateCooldown,
"AccountFacet: Cooldown hasn't reached"
);
uint256 amountWith18Decimals = (amount * 1e18) /
(10 ** IERC20Metadata(appLayout.collateral).decimals());
accountLayout.balances[msg.sender] -= amountWith18Decimals;
IERC20(appLayout.collateral).safeTransfer(user, amount);
}
function allocate(uint256 amount) internal {
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
require(
accountLayout.allocatedBalances[msg.sender] + amount <=
GlobalAppStorage.layout().balanceLimitPerUser,
"AccountFacet: Allocated balance limit reached"
);
require(accountLayout.balances[msg.sender] >= amount, "AccountFacet: Insufficient balance");
accountLayout.partyANonces[msg.sender] += 1;
accountLayout.balances[msg.sender] -= amount;
accountLayout.allocatedBalances[msg.sender] += amount;
}
function deallocate(uint256 amount, SingleUpnlSig memory upnlSig) internal {
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
require(
accountLayout.allocatedBalances[msg.sender] >= amount,
"AccountFacet: Insufficient allocated Balance"
);
LibMuon.verifyPartyAUpnl(upnlSig, msg.sender);
int256 availableBalance = LibAccount.partyAAvailableForQuote(upnlSig.upnl, msg.sender);
require(availableBalance >= 0, "AccountFacet: Available balance is lower than zero");
require(uint256(availableBalance) >= amount, "AccountFacet: partyA will be liquidatable");
accountLayout.partyANonces[msg.sender] += 1;
accountLayout.allocatedBalances[msg.sender] -= amount;
accountLayout.balances[msg.sender] += amount;
accountLayout.withdrawCooldown[msg.sender] = block.timestamp;
}
function transferAllocation(
uint256 amount,
address origin,
address recipient,
SingleUpnlSig memory upnlSig
) internal {
MAStorage.Layout storage maLayout = MAStorage.layout();
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
require(
!maLayout.partyBLiquidationStatus[msg.sender][origin],
"PartyBFacet: PartyB isn't solvent"
);
require(
!maLayout.partyBLiquidationStatus[msg.sender][recipient],
"PartyBFacet: PartyB isn't solvent"
);
// deallocate from origin
require(
accountLayout.partyBAllocatedBalances[msg.sender][origin] >= amount,
"PartyBFacet: Insufficient locked balance"
);
LibMuon.verifyPartyBUpnl(upnlSig, msg.sender, origin);
int256 availableBalance = LibAccount.partyBAvailableForQuote(
upnlSig.upnl,
msg.sender,
origin
);
require(availableBalance >= 0, "PartyBFacet: Available balance is lower than zero");
require(uint256(availableBalance) >= amount, "PartyBFacet: Will be liquidatable");
accountLayout.partyBNonces[msg.sender][origin] += 1;
accountLayout.partyBAllocatedBalances[msg.sender][origin] -= amount;
// allocate for recipient
accountLayout.partyBNonces[msg.sender][recipient] += 1;
accountLayout.partyBAllocatedBalances[msg.sender][recipient] += amount;
}
function depositForPartyB(uint256 amount) internal {
IERC20(GlobalAppStorage.layout().collateral).safeTransferFrom(
msg.sender,
address(this),
amount
);
uint256 amountWith18Decimals = (amount * 1e18) /
(10 ** IERC20Metadata(GlobalAppStorage.layout().collateral).decimals());
AccountStorage.layout().balances[msg.sender] += amountWith18Decimals;
}
function allocateForPartyB(uint256 amount, address partyA, bool increaseNonce) internal {
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
require(accountLayout.balances[msg.sender] >= amount, "PartyBFacet: Insufficient balance");
require(
!MAStorage.layout().partyBLiquidationStatus[msg.sender][partyA],
"PartyBFacet: PartyB isn't solvent"
);
if (increaseNonce) {
accountLayout.partyBNonces[msg.sender][partyA] += 1;
}
accountLayout.balances[msg.sender] -= amount;
accountLayout.partyBAllocatedBalances[msg.sender][partyA] += amount;
}
function deallocateForPartyB(
uint256 amount,
address partyA,
SingleUpnlSig memory upnlSig
) internal {
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
require(
accountLayout.partyBAllocatedBalances[msg.sender][partyA] >= amount,
"PartyBFacet: Insufficient locked balance"
);
LibMuon.verifyPartyBUpnl(upnlSig, msg.sender, partyA);
int256 availableBalance = LibAccount.partyBAvailableForQuote(
upnlSig.upnl,
msg.sender,
partyA
);
require(availableBalance >= 0, "PartyBFacet: Available balance is lower than zero");
require(uint256(availableBalance) >= amount, "PartyBFacet: Will be liquidatable");
accountLayout.partyBNonces[msg.sender][partyA] += 1;
accountLayout.partyBAllocatedBalances[msg.sender][partyA] -= amount;
accountLayout.balances[msg.sender] += amount;
accountLayout.withdrawCooldown[msg.sender] = block.timestamp;
}
}