-
Notifications
You must be signed in to change notification settings - Fork 2
/
AccountFacetImpl.sol
134 lines (117 loc) · 7 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
// 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/muon/LibMuonAccount.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.balances[msg.sender] -= amount;
accountLayout.allocatedBalances[msg.sender] += amount;
}
function deallocate(uint256 amount, SingleUpnlSig memory upnlSig) internal {
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
require(
block.timestamp >= accountLayout.withdrawCooldown[msg.sender] + MAStorage.layout().deallocateDebounceTime,
"AccountFacet: Too many deallocate in a short window"
);
require(accountLayout.allocatedBalances[msg.sender] >= amount, "AccountFacet: Insufficient allocated Balance");
LibMuonAccount.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.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");
require(!MAStorage.layout().liquidationStatus[origin], "PartyBFacet: Origin isn't solvent");
require(!MAStorage.layout().liquidationStatus[recipient], "PartyBFacet: Recipient isn't solvent");
// deallocate from origin
require(accountLayout.partyBAllocatedBalances[msg.sender][origin] >= amount, "PartyBFacet: Insufficient locked balance");
LibMuonAccount.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.partyBAllocatedBalances[msg.sender][origin] -= amount;
// allocate for recipient
accountLayout.partyBAllocatedBalances[msg.sender][recipient] += amount;
}
function internalTransfer(address user, uint256 amount) internal {
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
require(
accountLayout.allocatedBalances[user] + amount <= GlobalAppStorage.layout().balanceLimitPerUser,
"AccountFacet: Allocated balance limit reached"
);
require(accountLayout.balances[msg.sender] >= amount, "AccountFacet: Insufficient balance");
accountLayout.balances[msg.sender] -= amount;
accountLayout.allocatedBalances[user] += amount;
}
function allocateForPartyB(uint256 amount, address partyA) internal {
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
require(accountLayout.balances[msg.sender] >= amount, "AccountFacet: Insufficient balance");
require(!MAStorage.layout().partyBLiquidationStatus[msg.sender][partyA], "AccountFacet: PartyB isn't solvent");
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, "AccountFacet: Insufficient allocated balance");
LibMuonAccount.verifyPartyBUpnl(upnlSig, msg.sender, partyA);
int256 availableBalance = LibAccount.partyBAvailableForQuote(upnlSig.upnl, msg.sender, partyA);
require(availableBalance >= 0, "AccountFacet: Available balance is lower than zero");
require(uint256(availableBalance) >= amount, "AccountFacet: Will be liquidatable");
accountLayout.partyBAllocatedBalances[msg.sender][partyA] -= amount;
accountLayout.balances[msg.sender] += amount;
accountLayout.withdrawCooldown[msg.sender] = block.timestamp;
}
function depositToReserveVault(uint256 amount, address partyB) internal {
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
require(amount <= accountLayout.balances[msg.sender], "AccountFacet: Insufficient balance");
require(MAStorage.layout().partyBStatus[partyB], "AccountFacet: Should be partyB");
accountLayout.balances[msg.sender] -= amount;
accountLayout.reserveVault[partyB] += amount;
}
function withdrawFromReserveVault(uint256 amount) internal {
AccountStorage.Layout storage accountLayout = AccountStorage.layout();
require(amount > 0 && amount <= accountLayout.reserveVault[msg.sender], "AccountFacet: Insufficient balance");
accountLayout.reserveVault[msg.sender] -= amount;
accountLayout.balances[msg.sender] += amount;
accountLayout.withdrawCooldown[msg.sender] = block.timestamp;
}
}