Skip to content

Commit 644c3a9

Browse files
committed
add collateral manager storage structs and packing helpers for collateral positions
1 parent 4d89ab4 commit 644c3a9

3 files changed

Lines changed: 104 additions & 2 deletions

File tree

src/CollateralManager.sol

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity 0.8.30;
33

4-
contract CollateralManager { }
4+
import { ICollateralManager } from "./interfaces/ICollateralManager.sol";
5+
import { CollateralUtils } from "./libraries/CollateralUtils.sol";
6+
import { SafeCastLib } from "solady/utils/SafeCastLib.sol";
7+
8+
contract CollateralManager is ICollateralManager {
9+
using SafeCastLib for uint256;
10+
using CollateralUtils for CollateralStore;
11+
12+
mapping(address => CollateralStore) private collateral;
13+
}
Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity 0.8.30;
33

4-
interface ICollateralManager { }
4+
interface ICollateralManager {
5+
struct CollateralStore {
6+
uint256[] slot; // first 160 token | 96 amount
7+
mapping(address => uint256) index;
8+
}
9+
10+
struct CollateralPosition {
11+
address token;
12+
uint256 amount;
13+
}
14+
}

src/libraries/CollateralUtils.sol

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
2+
pragma solidity 0.8.30;
3+
4+
import { ICollateralManager } from "../interfaces/ICollateralManager.sol";
5+
import { SafeCastLib } from "solady/utils/SafeCastLib.sol";
6+
7+
library CollateralUtils {
8+
using SafeCastLib for *;
9+
uint256 constant AMOUNT_BITS = 96;
10+
uint256 constant AMOUNT_MASK = (uint256(1) << AMOUNT_BITS) - 1;
11+
12+
function pack(address _token, uint96 _amount) internal pure returns (uint256 packed) {
13+
packed = uint256(uint160(_token)) << AMOUNT_BITS | _amount;
14+
}
15+
16+
function unpack(uint256 _packed) internal pure returns (address token, uint96 amount) {
17+
token = address((_packed >> AMOUNT_BITS).toUint160());
18+
amount = _packed.toUint96();
19+
}
20+
21+
function add(ICollateralManager.CollateralStore storage _store, address _token, uint96 _amount) internal {
22+
if (_store.index[_token] != 0) revert();
23+
_store.slot.push(pack(_token, _amount));
24+
_store.index[_token] = _store.slot.length;
25+
}
26+
27+
function update(ICollateralManager.CollateralStore storage _store, address _token, uint96 _amount) internal {
28+
uint256 idx = _store.index[_token];
29+
if (idx == 0) revert();
30+
31+
_store.slot[idx - 1] = pack(_token, _amount);
32+
}
33+
34+
function remove(ICollateralManager.CollateralStore storage _store, address _token) internal {
35+
uint256 idx = _store.index[_token];
36+
uint256 slotLength = _store.slot.length;
37+
38+
if (idx != slotLength) {
39+
uint256 lastPack = _store.slot[slotLength - 1];
40+
(address lastToken,) = unpack(lastPack);
41+
42+
_store.slot[idx - 1] = lastPack;
43+
_store.index[lastToken] = idx;
44+
}
45+
46+
_store.slot.pop();
47+
delete _store.index[_token];
48+
}
49+
50+
function get(ICollateralManager.CollateralStore storage _store, address _token)
51+
internal
52+
view
53+
returns (uint96 amount)
54+
{
55+
uint256 idx = _store.index[_token];
56+
if (idx == 0) return 0;
57+
(, amount) = unpack(_store.slot[idx - 1]);
58+
}
59+
60+
function getAll(ICollateralManager.CollateralStore storage _store)
61+
internal
62+
view
63+
returns (ICollateralManager.CollateralPosition[] memory position)
64+
{
65+
uint256 length = _store.slot.length;
66+
position = new ICollateralManager.CollateralPosition[](length);
67+
for (uint256 i = 0; i < length; i++) {
68+
(address token, uint96 amount) = unpack(_store.slot[i]);
69+
position[i] = ICollateralManager.CollateralPosition({ token: token, amount: amount });
70+
}
71+
}
72+
73+
function getAllCollateralValue(
74+
ICollateralManager.CollateralStore storage _store,
75+
function(address) internal view returns (uint256) getTokenValueInUsd
76+
) internal view returns (uint256 value) {
77+
for (uint256 i = 0; i < _store.slot.length; i++) {
78+
(address token, uint96 amount) = unpack(_store.slot[i]);
79+
80+
value += uint256(amount) * getTokenValueInUsd(token);
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)