Skip to content

Commit 65fe0d7

Browse files
committed
WIP
1 parent b3dcea2 commit 65fe0d7

File tree

2 files changed

+162
-118
lines changed

2 files changed

+162
-118
lines changed

packages/ethereum-contracts/contracts/agreements/gdav1/GeneralDistributionAgreementV1.sol

Lines changed: 161 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,167 @@ import { AgreementBase } from "../AgreementBase.sol";
3232
import { AgreementLibrary } from "../AgreementLibrary.sol";
3333

3434

35+
/*
36+
function getAgreementData(
37+
address agreementClass,
38+
bytes32 id,
39+
uint dataLength
40+
)
41+
42+
function getAgreementStateSlot(
43+
address agreementClass,
44+
address account,
45+
uint256 slotId,
46+
uint dataLength
47+
)
48+
49+
*/
50+
3551
/// @dev Universal Index state slot id for storing universal index data
3652
function _universalIndexStateSlotId() pure returns (uint256) {
3753
return 0;
3854
}
3955

56+
library GeneralDistributionAgreementV1Storage {
57+
58+
uint256 internal constant ACCOUNT_DATA_STATE_SLOT_ID = 0;
59+
60+
// # Account Data Operations
61+
//
62+
// Account data includes:
63+
// - Semantic universal index (a basic particle)
64+
// - buffer amount
65+
// - isPool flag
66+
// store buffer (96) and one bit to specify is pool in free
67+
// -------- ------------------ ------------------ ------------------ ------------------
68+
// WORD 1: | flowRate | settledAt | totalBuffer | isPool |
69+
// -------- ------------------ ------------------ ------------------ ------------------
70+
// | 96b | 32b | 96b | 32b |
71+
// -------- ------------------ ------------------ ------------------ ------------------
72+
// WORD 2: | settledValue |
73+
// -------- ------------------ ------------------ ------------------ ------------------
74+
// | 256b |
75+
// -------- ------------------ ------------------ ------------------ ------------------
76+
77+
struct AccountData {
78+
int96 flowRate;
79+
uint32 settledAt;
80+
uint256 totalBuffer;
81+
bool isPool;
82+
int256 settledValue;
83+
}
84+
85+
function encodeUpdatedUniversalIndex(AccountData memory accountData, BasicParticle memory uIndex)
86+
internal
87+
pure
88+
returns (bytes32[] memory data)
89+
{
90+
data = new bytes32[](2);
91+
data[0] = bytes32(
92+
(uint256(int256(FlowRate.unwrap(uIndex.flow_rate()))) << 160) |
93+
(uint256(Time.unwrap(uIndex.settled_at())) << 128) |
94+
(uint256(SafeCast.toUint96(accountData.totalBuffer) << 32)) | (accountData.isPool ? 1 : 0)
95+
);
96+
data[1] = bytes32(uint256(Value.unwrap(uIndex._settled_value)));
97+
}
98+
99+
function encodeUpdatedTotalBuffer(AccountData memory accountData, uint256 totalBuffer)
100+
internal
101+
pure
102+
returns (bytes32[] memory data)
103+
{
104+
data = new bytes32[](1);
105+
data[0] = bytes32(
106+
(uint256(int256(accountData.flowRate)) << 160) |
107+
(uint256(accountData.settledAt) << 128) |
108+
(uint256(SafeCast.toUint96(totalBuffer) << 32)) | (accountData.isPool ? 1 : 0)
109+
);
110+
}
111+
112+
function decodeAccountData(bytes32[] memory data)
113+
internal
114+
pure
115+
returns (AccountData memory accountData)
116+
{
117+
uint256 a = uint256(data[0]);
118+
uint256 b = uint256(data[1]);
119+
bool exists = a > 0 || b > 0;
120+
121+
if (exists) {
122+
accountData.flowRate = int96(int256(a >> 160) & int256(uint256(type(uint96).max)));
123+
accountData.settledAt = uint32(uint256(a >> 128) & uint256(type(uint32).max));
124+
accountData.totalBuffer = uint256(a >> 32) & uint256(type(uint96).max);
125+
accountData.isPool = ((a << 224) >> 224) & 1 == 1;
126+
accountData.settledValue = int256(b);
127+
}
128+
}
129+
130+
function getAccountData(bytes memory eff, address owner)
131+
internal
132+
view
133+
returns (AccountData memory accountData)
134+
{
135+
return decodeAccountData(
136+
ISuperfluidToken(abi.decode(eff, (address))).getAgreementStateSlot(
137+
address(this), owner, ACCOUNT_DATA_STATE_SLOT_ID, 2
138+
)
139+
);
140+
}
141+
142+
function getUniversalIndexFromAccountData(AccountData memory accountData)
143+
internal
144+
pure
145+
returns (BasicParticle memory uIndex)
146+
{
147+
uIndex._flow_rate = FlowRate.wrap(accountData.flowRate);
148+
uIndex._settled_at = Time.wrap(accountData.settledAt);
149+
uIndex._settled_value = Value.wrap(accountData.settledValue);
150+
}
151+
152+
function setUniversalIndex(bytes memory eff, address owner, BasicParticle memory uIndex)
153+
internal
154+
returns (bytes memory)
155+
{
156+
AccountData memory accountData = getAccountData(eff, owner);
157+
158+
ISuperfluidToken(abi.decode(eff, (address))).updateAgreementStateSlot(
159+
owner,
160+
ACCOUNT_DATA_STATE_SLOT_ID,
161+
encodeUpdatedUniversalIndex(accountData, uIndex)
162+
);
163+
164+
return eff;
165+
}
166+
167+
function setTotalBuffer(bytes memory eff, address owner, uint256 totalBuffer)
168+
internal
169+
returns (bytes memory)
170+
{
171+
AccountData memory accountData = getAccountData(eff, owner);
172+
173+
ISuperfluidToken(abi.decode(eff, (address))).updateAgreementStateSlot(
174+
owner,
175+
ACCOUNT_DATA_STATE_SLOT_ID,
176+
encodeUpdatedTotalBuffer(accountData, totalBuffer)
177+
);
178+
179+
return eff;
180+
}
181+
182+
// ..............
183+
184+
/* struct PoolMemberData { */
185+
/* address pool; */
186+
/* uint32 poolID; // the slot id in the pool's subs bitmap */
187+
/* } */
188+
189+
/* struct FlowDistributionData { */
190+
/* uint32 lastUpdated; */
191+
/* int96 flowRate; */
192+
/* uint256 buffer; // stored as uint96 */
193+
/* } */
194+
}
195+
40196
/// @dev returns true if the account is a pool
41197
function _isPool(
42198
IGeneralDistributionAgreementV1 gda,
@@ -101,14 +257,6 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
101257
using SafeCast for int256;
102258
using SemanticMoney for BasicParticle;
103259

104-
struct UniversalIndexData {
105-
int96 flowRate;
106-
uint32 settledAt;
107-
uint256 totalBuffer;
108-
bool isPool;
109-
int256 settledValue;
110-
}
111-
112260
struct PoolMemberData {
113261
address pool;
114262
uint32 poolID; // the slot id in the pool's subs bitmap
@@ -144,12 +292,13 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
144292
override
145293
returns (int256 rtb, uint256 buf, uint256 owedBuffer)
146294
{
147-
UniversalIndexData memory universalIndexData = _getUIndexData(abi.encode(token), account);
295+
GeneralDistributionAgreementV1Storage.AccountData memory accountData =
296+
GeneralDistributionAgreementV1Storage.getAccountData(abi.encode(token), account);
148297

149298
if (_isPool(this, token, account)) {
150299
rtb = ISuperfluidPool(account).getDisconnectedBalance(uint32(time));
151300
} else {
152-
rtb = Value.unwrap(_getBasicParticleFromUIndex(universalIndexData).rtb(Time.wrap(uint32(time))));
301+
rtb = Value.unwrap(_getBasicParticleFromUIndexData(accountData).rtb(Time.wrap(uint32(time))));
153302
}
154303

155304
int256 fromPools;
@@ -166,7 +315,7 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
166315
}
167316
rtb += fromPools;
168317

169-
buf = uint256(universalIndexData.totalBuffer.toInt256()); // upcasting to uint256 is safe
318+
buf = uint256(accountData.totalBuffer.toInt256()); // upcasting to uint256 is safe
170319
owedBuffer = 0;
171320
}
172321

@@ -790,112 +939,7 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
790939
return keccak256(abi.encode(block.chainid, "poolAdjustmentFlow", from, to));
791940
}
792941

793-
// # Universal Index operations
794-
//
795-
// Universal Index packing:
796-
// store buffer (96) and one bit to specify is pool in free
797-
// -------- ------------------ ------------------ ------------------ ------------------
798-
// WORD 1: | flowRate | settledAt | totalBuffer | isPool |
799-
// -------- ------------------ ------------------ ------------------ ------------------
800-
// | 96b | 32b | 96b | 32b |
801-
// -------- ------------------ ------------------ ------------------ ------------------
802-
// WORD 2: | settledValue |
803-
// -------- ------------------ ------------------ ------------------ ------------------
804-
// | 256b |
805-
// -------- ------------------ ------------------ ------------------ ------------------
806-
807-
function _encodeUniversalIndexData(BasicParticle memory p, uint256 buffer, bool isPool_)
808-
internal
809-
pure
810-
returns (bytes32[] memory data)
811-
{
812-
data = new bytes32[](2);
813-
data[0] = bytes32(
814-
(uint256(int256(FlowRate.unwrap(p.flow_rate()))) << 160) | (uint256(Time.unwrap(p.settled_at())) << 128)
815-
| (uint256(buffer.toUint96()) << 32) | (isPool_ ? 1 : 0)
816-
);
817-
data[1] = bytes32(uint256(Value.unwrap(p._settled_value)));
818-
}
819-
820-
function _encodeUniversalIndexData(UniversalIndexData memory uIndexData)
821-
internal
822-
pure
823-
returns (bytes32[] memory data)
824-
{
825-
data = new bytes32[](2);
826-
data[0] = bytes32(
827-
(uint256(int256(uIndexData.flowRate)) << 160) | (uint256(uIndexData.settledAt) << 128)
828-
| (uint256(uIndexData.totalBuffer.toUint96()) << 32) | (uIndexData.isPool ? 1 : 0)
829-
);
830-
data[1] = bytes32(uint256(uIndexData.settledValue));
831-
}
832-
833-
function _decodeUniversalIndexData(bytes32[] memory data)
834-
internal
835-
pure
836-
returns (bool exists, UniversalIndexData memory universalIndexData)
837-
{
838-
uint256 a = uint256(data[0]);
839-
uint256 b = uint256(data[1]);
840-
841-
exists = a > 0 || b > 0;
842-
843-
if (exists) {
844-
universalIndexData.flowRate = int96(int256(a >> 160) & int256(uint256(type(uint96).max)));
845-
universalIndexData.settledAt = uint32(uint256(a >> 128) & uint256(type(uint32).max));
846-
universalIndexData.totalBuffer = uint256(a >> 32) & uint256(type(uint96).max);
847-
universalIndexData.isPool = ((a << 224) >> 224) & 1 == 1;
848-
universalIndexData.settledValue = int256(b);
849-
}
850-
}
851-
852-
function _getUIndexData(bytes memory eff, address owner)
853-
internal
854-
view
855-
returns (UniversalIndexData memory universalIndexData)
856-
{
857-
(, universalIndexData) = _decodeUniversalIndexData(
858-
ISuperfluidToken(abi.decode(eff, (address))).getAgreementStateSlot(
859-
address(this), owner, _universalIndexStateSlotId(), 2
860-
)
861-
);
862-
}
863-
864-
function _getBasicParticleFromUIndex(UniversalIndexData memory universalIndexData)
865-
internal
866-
pure
867-
returns (BasicParticle memory particle)
868-
{
869-
particle._flow_rate = FlowRate.wrap(universalIndexData.flowRate);
870-
particle._settled_at = Time.wrap(universalIndexData.settledAt);
871-
particle._settled_value = Value.wrap(universalIndexData.settledValue);
872-
}
873-
874-
// TokenMonad virtual functions
875-
function _getUIndex(bytes memory eff, address owner) internal view override returns (BasicParticle memory uIndex) {
876-
(, UniversalIndexData memory universalIndexData) = _decodeUniversalIndexData(
877-
ISuperfluidToken(abi.decode(eff, (address))).getAgreementStateSlot(
878-
address(this), owner, _universalIndexStateSlotId(), 2
879-
)
880-
);
881-
uIndex = _getBasicParticleFromUIndex(universalIndexData);
882-
}
883-
884-
function _setUIndex(bytes memory eff, address owner, BasicParticle memory p)
885-
internal
886-
override
887-
returns (bytes memory)
888-
{
889-
UniversalIndexData memory universalIndexData = _getUIndexData(eff, owner);
890-
891-
ISuperfluidToken(abi.decode(eff, (address))).updateAgreementStateSlot(
892-
owner,
893-
_universalIndexStateSlotId(),
894-
_encodeUniversalIndexData(p, universalIndexData.totalBuffer, universalIndexData.isPool)
895-
);
896-
897-
return eff;
898-
}
942+
// FIXME: Pool data refactoring
899943

900944
function _getPDPIndex(
901945
bytes memory, // eff,

packages/ethereum-contracts/test/foundry/agreements/gdav1/GeneralDistributionAgreementV1.prop.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ contract GeneralDistributionAgreementV1Properties is GeneralDistributionAgreemen
319319
}
320320

321321
function testGetBasicParticleFromUIndex(UniversalIndexData memory data) public pure {
322-
BasicParticle memory particle = _getBasicParticleFromUIndex(data);
322+
BasicParticle memory particle = _getBasicParticleFromUIndexData(data);
323323
assertEq(data.flowRate, int96(FlowRate.unwrap(particle._flow_rate)), "flowRate not equal");
324324
assertEq(data.settledAt, Time.unwrap(particle._settled_at), "settledAt not equal");
325325
assertEq(data.settledValue, Value.unwrap(particle._settled_value), "settledValue not equal");

0 commit comments

Comments
 (0)