diff --git a/src/core/TrustManager.sol b/src/core/TrustManager.sol index 5ba82ba..e38e4e1 100644 --- a/src/core/TrustManager.sol +++ b/src/core/TrustManager.sol @@ -27,6 +27,20 @@ abstract contract TrustManager is IRegistry { mapping(address account => TrustedAttesterRecord attesters) internal $accountToAttester; + function _requireEmptyList(TrustedAttesterRecord storage $trustedAttester) internal view { + address _tmp = $trustedAttester.attester; + + // if the first entry is zero, the trusted list was not previously initialized, and can thus be safely set. + if (_tmp == ZERO_ADDRESS) return; + + // otherwise, loop over the linked list to check if it is empty + // find the last entry in the linked list. + for (uint256 i; i <= type(uint8).max; i++) { + _tmp = $trustedAttester.linkedAttesters[_tmp][msg.sender]; + if (_tmp == ZERO_ADDRESS) return; + } + } + /** * @inheritdoc IERC7484 */ @@ -49,6 +63,9 @@ abstract contract TrustManager is IRegistry { revert InvalidThreshold(); } + // ensure that the trusted attester list is cleared before re-initializing it. + _requireEmptyList($trustedAttester); + $trustedAttester.attesterCount = uint8(attestersLength); $trustedAttester.threshold = threshold; $trustedAttester.attester = attesters[0]; diff --git a/test/TrustedAttesterList.t.sol b/test/TrustedAttesterList.t.sol new file mode 100644 index 0000000..d69618b --- /dev/null +++ b/test/TrustedAttesterList.t.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import "./Attestation.t.sol"; +import "src/DataTypes.sol"; +import { LibSort } from "solady/utils/LibSort.sol"; + +contract POCTest is AttestationTest { + using LibSort for address[]; + + function setUp() public override { + super.setUp(); + } + + function testPOC() external prankWithAccount(smartAccount1) { + uint8 threshold = 1; + address[] memory trustedAttesters = new address[](3); + trustedAttesters[0] = address(attester1.addr); + trustedAttesters[1] = address(attester2.addr); + trustedAttesters[2] = makeAddr("attester3"); + + trustedAttesters.sort(); + trustedAttesters.uniquifySorted(); + + registry.trustAttesters(threshold, trustedAttesters); + + address[] memory result = registry.findTrustedAttesters(smartAccount1.addr); + + assertEq(result.length, trustedAttesters.length); + for (uint256 i; i < trustedAttesters.length; i++) { + assertEq(result[i], trustedAttesters[i]); + } + + _make_WhenUsingValidECDSA(attester2); + registry.check(address(module1), ModuleType.wrap(1)); + + address[] memory newTrustedAttesters = new address[](1); + newTrustedAttesters[0] = address(attester1.addr); + registry.trustAttesters(1, newTrustedAttesters); + address[] memory newResult = registry.findTrustedAttesters(smartAccount1.addr); + assertEq(newResult.length, 1); + assertEq(newResult[0], address(attester1.addr)); + + registry.check(address(module1), ModuleType.wrap(1)); + } +}