Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FUN-877] persist data fetched from allowlist contract #11648

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d0d45b0
feat: add allowlist cache layer migration
agparadiso Dec 20, 2023
39f3085
feat: add getAllowedSendersInRange and getAllowedSendersCount methods…
agparadiso Dec 21, 2023
a72d063
feat: iterate over allowlist contract response, load and update allow…
agparadiso Jan 2, 2024
8e4840c
feat: reduce gas by removing mapping and using EnumerableSet .length(…
agparadiso Jan 8, 2024
cdbced5
feat: implement orm level for allowlist
agparadiso Jan 8, 2024
98062b4
fix: fix iteration loop and add tests
agparadiso Jan 8, 2024
6de74c8
fix: correct var naming, zero indexing array, doc
agparadiso Jan 10, 2024
7f72ef3
chore: rename cache to stored, split batchSize onchain vs stored
agparadiso Jan 10, 2024
80e116d
fix: remove id from allowlist primary key, use it only for ordering
agparadiso Jan 11, 2024
4b21109
feat: store allowlist in batches
agparadiso Jan 12, 2024
bf994cd
chore: correct CreateAllowedSenders naming
agparadiso Jan 16, 2024
3ede899
chore: CreateAllowedSenders in main routine
agparadiso Jan 16, 2024
b07c454
fix: add a trottle to prevent RPC rate limiting
agparadiso Jan 16, 2024
f410edf
chore: split orm in subscriptions and allowlist pkgs
agparadiso Jan 17, 2024
ab8dec7
feat: put the new functionality under a feature flag
agparadiso Jan 17, 2024
d796d7f
fix: fix subscriptions consumers address
agparadiso Jan 18, 2024
1be1f8a
fix: store only on feature enable to prevent blocked addresses not be…
agparadiso Jan 18, 2024
9389302
chore: rename CachedSubscriptions to StoredSubscriptions
agparadiso Jan 18, 2024
6b57041
feat: implement GetBlockedSendersInRange and GetBlockedSendersCount i…
agparadiso Jan 19, 2024
f34208d
feat: implement sync of blocked senders with allowed
agparadiso Jan 19, 2024
f9fa8f2
chore: add checks and table constraints
agparadiso Jan 22, 2024
2feab3a
chore: methods renaming
agparadiso Jan 23, 2024
e338964
chore: correct log and var name
agparadiso Jan 24, 2024
11091cd
Merge branch 'develop' into feature/FUN-877_persist_data_fetched_from…
agparadiso Jan 24, 2024
d84246f
Merge branch 'develop' into feature/FUN-877_persist_data_fetched_from…
agparadiso Jan 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 80 additions & 70 deletions contracts/gas-snapshots/functions.gas-snapshot

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController,
string public constant override typeAndVersion = "Functions Terms of Service Allow List v1.1.0";

EnumerableSet.AddressSet private s_allowedSenders;
mapping(address => bool) private s_blockedSenders;
EnumerableSet.AddressSet private s_blockedSenders;

event AddedAccess(address user);
event BlockedAccess(address user);
Expand All @@ -29,6 +29,7 @@ contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController,
error InvalidSignature();
error InvalidUsage();
error RecipientIsBlocked();
error InvalidCalldata();

TermsOfServiceAllowListConfig private s_config;

Expand Down Expand Up @@ -70,7 +71,7 @@ contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController,

/// @inheritdoc ITermsOfServiceAllowList
function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external override {
if (s_blockedSenders[recipient]) {
if (s_blockedSenders.contains(recipient)) {
revert RecipientIsBlocked();
}

Expand Down Expand Up @@ -101,6 +102,32 @@ contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController,
return s_allowedSenders.values();
}

/// @inheritdoc ITermsOfServiceAllowList
function getAllowedSendersCount() external view override returns (uint64) {
return uint64(s_allowedSenders.length());
}

/// @inheritdoc ITermsOfServiceAllowList
function getAllowedSendersInRange(
agparadiso marked this conversation as resolved.
Show resolved Hide resolved
uint64 allowedSenderIdxStart,
uint64 allowedSenderIdxEnd
) external view override returns (address[] memory allowedSenders) {
if (
allowedSenderIdxStart > allowedSenderIdxEnd ||
allowedSenderIdxEnd >= s_allowedSenders.length() ||
s_allowedSenders.length() == 0
) {
revert InvalidCalldata();
}

allowedSenders = new address[]((allowedSenderIdxEnd - allowedSenderIdxStart) + 1);
for (uint256 i = 0; i <= allowedSenderIdxEnd - allowedSenderIdxStart; ++i) {
allowedSenders[i] = s_allowedSenders.at(uint256(allowedSenderIdxStart + i));
}

return allowedSenders;
}

/// @inheritdoc IAccessController
function hasAccess(address user, bytes calldata /* data */) external view override returns (bool) {
if (!s_config.enabled) {
Expand All @@ -118,19 +145,45 @@ contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController,
if (!s_config.enabled) {
return false;
}
return s_blockedSenders[sender];
return s_blockedSenders.contains(sender);
}

/// @inheritdoc ITermsOfServiceAllowList
function blockSender(address sender) external override onlyOwner {
s_allowedSenders.remove(sender);
s_blockedSenders[sender] = true;
s_blockedSenders.add(sender);
emit BlockedAccess(sender);
}

/// @inheritdoc ITermsOfServiceAllowList
function unblockSender(address sender) external override onlyOwner {
s_blockedSenders[sender] = false;
s_blockedSenders.remove(sender);
emit UnblockedAccess(sender);
}

/// @inheritdoc ITermsOfServiceAllowList
function getBlockedSendersCount() external view override returns (uint64) {
return uint64(s_blockedSenders.length());
}

/// @inheritdoc ITermsOfServiceAllowList
function getBlockedSendersInRange(
uint64 blockedSenderIdxStart,
uint64 blockedSenderIdxEnd
) external view override returns (address[] memory blockedSenders) {
if (
blockedSenderIdxStart > blockedSenderIdxEnd ||
blockedSenderIdxEnd >= s_blockedSenders.length() ||
s_blockedSenders.length() == 0
) {
revert InvalidCalldata();
}

blockedSenders = new address[]((blockedSenderIdxEnd - blockedSenderIdxStart) + 1);
for (uint256 i = 0; i <= blockedSenderIdxEnd - blockedSenderIdxStart; ++i) {
blockedSenders[i] = s_blockedSenders.at(uint256(blockedSenderIdxStart + i));
}

return blockedSenders;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ interface ITermsOfServiceAllowList {
/// @return addresses - all allowed addresses
function getAllAllowedSenders() external view returns (address[] memory);

/// @notice Get details about the total number of allowed senders
/// @return count - total number of allowed senders in the system
function getAllowedSendersCount() external view returns (uint64);

/// @notice Retrieve a list of allowed senders using an inclusive range
/// @dev WARNING: getAllowedSendersInRange uses EnumerableSet .length() and .at() methods to iterate over the list
bolekk marked this conversation as resolved.
Show resolved Hide resolved
/// without the need for an extra mapping. These method can not guarantee the ordering when new elements are added.
/// Evaluate if eventual consistency will satisfy your usecase before using it.
/// @param allowedSenderIdxStart - index of the allowed sender to start the range at
/// @param allowedSenderIdxEnd - index of the allowed sender to end the range at
/// @return allowedSenders - allowed addresses in the range provided
function getAllowedSendersInRange(
uint64 allowedSenderIdxStart,
uint64 allowedSenderIdxEnd
) external view returns (address[] memory allowedSenders);

/// @notice Allows access to the sender based on acceptance of the Terms of Service
/// @param acceptor - The wallet address that has accepted the Terms of Service on the UI
/// @param recipient - The recipient address that the acceptor is taking responsibility for
Expand All @@ -37,6 +53,22 @@ interface ITermsOfServiceAllowList {
/// @notice Re-allows a previously blocked sender to accept the Terms of Service
/// @param sender - Address of the sender to unblock
function unblockSender(address sender) external;

/// @notice Get details about the total number of blocked senders
/// @return count - total number of blocked senders in the system
function getBlockedSendersCount() external view returns (uint64);

/// @notice Retrieve a list of blocked senders using an inclusive range
/// @dev WARNING: getBlockedSendersInRange uses EnumerableSet .length() and .at() methods to iterate over the list
bolekk marked this conversation as resolved.
Show resolved Hide resolved
/// without the need for an extra mapping. These method can not guarantee the ordering when new elements are added.
/// Evaluate if eventual consistency will satisfy your usecase before using it.
/// @param blockedSenderIdxStart - index of the blocked sender to start the range at
/// @param blockedSenderIdxEnd - index of the blocked sender to end the range at
/// @return blockedSenders - blocked addresses in the range provided
function getBlockedSendersInRange(
uint64 blockedSenderIdxStart,
uint64 blockedSenderIdxEnd
) external view returns (address[] memory blockedSenders);
}

// ================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,69 @@ contract FunctionsTermsOfServiceAllowList_GetAllAllowedSenders is FunctionsOwner
}
}

/// @notice #getAllowedSendersCount
contract FunctionsTermsOfServiceAllowList_GetAllowedSendersCount is FunctionsOwnerAcceptTermsOfServiceSetup {
function test_GetAllowedSendersCount_Success() public {
// Send as stranger
vm.stopPrank();
vm.startPrank(STRANGER_ADDRESS);

uint96 allowedSendersCount = s_termsOfServiceAllowList.getAllowedSendersCount();
// One allowed sender was made during setup
assertEq(allowedSendersCount, 1);
}
}

/// @notice #getAllowedSendersInRange
contract FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange is FunctionsOwnerAcceptTermsOfServiceSetup {
function test_GetAllowedSendersInRange_Success() public {
// Send as stranger
vm.stopPrank();
vm.startPrank(STRANGER_ADDRESS);

address[] memory expectedSenders = new address[](1);
expectedSenders[0] = OWNER_ADDRESS;

assertEq(s_termsOfServiceAllowList.getAllowedSendersInRange(0, 0), expectedSenders);
}

function test_GetAllowedSendersInRange_RevertIfAllowedSendersIsEmpty() public {
// setup a new empty s_termsOfServiceAllowList
FunctionsRoutesSetup.setUp();

// Send as stranger
vm.stopPrank();
vm.startPrank(STRANGER_ADDRESS);

uint64 AllowedSendersCount = s_termsOfServiceAllowList.getAllowedSendersCount();
uint64 expected = 0;
assertEq(AllowedSendersCount, expected);

vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector);
s_termsOfServiceAllowList.getAllowedSendersInRange(0, 0);
}

function test_GetAllowedSendersInRange_RevertIfStartIsAfterEnd() public {
// Send as stranger
vm.stopPrank();
vm.startPrank(STRANGER_ADDRESS);

vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector);

s_termsOfServiceAllowList.getAllowedSendersInRange(1, 0);
}

function test_GetAllowedSendersInRange_RevertIfEndIsAfterLastAllowedSender() public {
agparadiso marked this conversation as resolved.
Show resolved Hide resolved
// Send as stranger
vm.stopPrank();
vm.startPrank(STRANGER_ADDRESS);

uint64 AllowedSendersCount = s_termsOfServiceAllowList.getAllowedSendersCount();
vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector);
s_termsOfServiceAllowList.getAllowedSendersInRange(1, AllowedSendersCount + 1);
}
}

/// @notice #hasAccess
contract FunctionsTermsOfServiceAllowList_HasAccess is FunctionsRoutesSetup {
function test_HasAccess_FalseWhenEnabled() public {
Expand Down Expand Up @@ -373,3 +436,78 @@ contract FunctionsTermsOfServiceAllowList_UnblockSender is FunctionsRoutesSetup
s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v);
}
}

/// @notice #getBlockedSendersCount
contract FunctionsTermsOfServiceAllowList_GetBlockedSendersCount is FunctionsRoutesSetup {
function setUp() public virtual override {
FunctionsRoutesSetup.setUp();

s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS);
}

function test_GetBlockedSendersCount_Success() public {
// Send as stranger
vm.stopPrank();
vm.startPrank(STRANGER_ADDRESS);

uint96 blockedSendersCount = s_termsOfServiceAllowList.getBlockedSendersCount();
// One blocked sender was made during setup
assertEq(blockedSendersCount, 1);
}
}

/// @notice #getBlockedSendersInRange
contract FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange is FunctionsRoutesSetup {
function setUp() public virtual override {
FunctionsRoutesSetup.setUp();

s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS);
}

function test_GetBlockedSendersInRange_Success() public {
// Send as stranger
vm.stopPrank();
vm.startPrank(STRANGER_ADDRESS);

address[] memory expectedBlockedSenders = new address[](1);
expectedBlockedSenders[0] = STRANGER_ADDRESS;

assertEq(s_termsOfServiceAllowList.getBlockedSendersInRange(0, 0), expectedBlockedSenders);
}

function test_GetBlockedSendersInRange_RevertIfAllowedSendersIsEmpty() public {
// setup a new empty s_termsOfServiceBlockList
FunctionsRoutesSetup.setUp();

// Send as stranger
vm.stopPrank();
vm.startPrank(STRANGER_ADDRESS);

uint64 BlockedSendersCount = s_termsOfServiceAllowList.getBlockedSendersCount();
uint64 expected = 0;
assertEq(BlockedSendersCount, expected);

vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector);
s_termsOfServiceAllowList.getBlockedSendersInRange(0, 0);
}

function test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() public {
// Send as stranger
vm.stopPrank();
vm.startPrank(STRANGER_ADDRESS);

vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector);

s_termsOfServiceAllowList.getBlockedSendersInRange(1, 0);
}

function test_GetBlockedSendersInRange_RevertIfEndIsAfterLastAllowedSender() public {
// Send as stranger
vm.stopPrank();
vm.startPrank(STRANGER_ADDRESS);

uint64 BlockedSendersCount = s_termsOfServiceAllowList.getBlockedSendersCount();
vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector);
s_termsOfServiceAllowList.getBlockedSendersInRange(1, BlockedSendersCount + 1);
}
}
Loading
Loading