mirror of
https://github.com/lens-protocol/core.git
synced 2026-01-10 22:58:08 -05:00
Merge pull request #143 from lens-protocol/test/token-handle-registry
test: Improve test coverage of TokenHandleRegistry
This commit is contained in:
@@ -4,6 +4,7 @@ pragma solidity ^0.8.13;
|
||||
import 'test/base/TestSetup.t.sol';
|
||||
import 'contracts/libraries/constants/Types.sol';
|
||||
import {Typehash} from 'contracts/libraries/constants/Typehash.sol';
|
||||
import {Typehash as NamespacesTypehash} from 'contracts/namespaces/constants/Typehash.sol';
|
||||
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';
|
||||
import {Address} from '@openzeppelin/contracts/utils/Address.sol';
|
||||
|
||||
@@ -444,4 +445,18 @@ contract BaseTest is TestSetup {
|
||||
function _encodeUsingEip712Rules(bytes memory bytesValue) internal pure returns (bytes32) {
|
||||
return keccak256(bytesValue);
|
||||
}
|
||||
|
||||
function _transferHandle(address to, uint256 handleId) internal {
|
||||
address initialHandleHolder = lensHandles.ownerOf(handleId);
|
||||
_effectivelyDisableGuardian(address(lensHandles), initialHandleHolder);
|
||||
vm.prank(initialHandleHolder);
|
||||
lensHandles.transferFrom(initialHandleHolder, to, handleId);
|
||||
}
|
||||
|
||||
function _transferProfile(address to, uint256 profileId) internal {
|
||||
address initialProfileHolder = hub.ownerOf(profileId);
|
||||
_effectivelyDisableProfileGuardian(initialProfileHolder);
|
||||
vm.prank(initialProfileHolder);
|
||||
hub.transferFrom(initialProfileHolder, to, profileId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import 'test/base/BaseTest.t.sol';
|
||||
import {ERC1271WalletMock} from '@openzeppelin/contracts/mocks/ERC1271WalletMock.sol';
|
||||
import {MetaTxNegatives} from 'test/MetaTxNegatives.t.sol';
|
||||
import {RegistryErrors} from 'contracts/namespaces/constants/Errors.sol';
|
||||
import {RegistryEvents} from 'contracts/namespaces/constants/Events.sol';
|
||||
import {RegistryTypes} from 'contracts/namespaces/constants/Types.sol';
|
||||
@@ -13,7 +15,7 @@ contract TokenHandleRegistryTest is BaseTest {
|
||||
address initialProfileHolder = makeAddr('INITIAL_PROFILE_HOLDER');
|
||||
address initialHandleHolder = makeAddr('INITIAL_HANDLE_HOLDER');
|
||||
|
||||
function setUp() public override {
|
||||
function setUp() public virtual override {
|
||||
super.setUp();
|
||||
|
||||
profileId = _createProfile(initialProfileHolder);
|
||||
@@ -64,6 +66,24 @@ contract TokenHandleRegistryTest is BaseTest {
|
||||
tokenHandleRegistry.link(handleId, profileId);
|
||||
}
|
||||
|
||||
function testCannot_Link_IfNotOwnerOrDelegatedExecutor(address otherAddress) public {
|
||||
address holder = makeAddr('holder');
|
||||
|
||||
vm.assume(otherAddress != holder);
|
||||
vm.assume(otherAddress != address(0));
|
||||
vm.assume(!_isLensHubProxyAdmin(otherAddress));
|
||||
|
||||
_transferHandle(holder, handleId);
|
||||
_transferProfile(holder, profileId);
|
||||
|
||||
_effectivelyDisableProfileGuardian(holder);
|
||||
|
||||
vm.expectRevert(RegistryErrors.DoesNotHavePermissions.selector);
|
||||
|
||||
vm.prank(otherAddress);
|
||||
tokenHandleRegistry.link(handleId, profileId);
|
||||
}
|
||||
|
||||
function testCannot_Link_IfHandleDoesNotExist(uint256 nonexistingHandleId) public {
|
||||
vm.assume(!lensHandles.exists(nonexistingHandleId));
|
||||
|
||||
@@ -792,3 +812,288 @@ contract TokenHandleRegistryTest is BaseTest {
|
||||
tokenHandleRegistry.getDefaultHandle(profileId);
|
||||
}
|
||||
}
|
||||
|
||||
abstract contract TokenHandleRegistryMetaTxBaseTest is BaseTest, MetaTxNegatives {
|
||||
uint256 internal constant NO_DEADLINE = type(uint256).max;
|
||||
|
||||
uint256 profileId;
|
||||
uint256 handleId;
|
||||
|
||||
uint256 constant holderPk = 0x401DE8;
|
||||
address holder;
|
||||
|
||||
function setUp() public override (BaseTest, MetaTxNegatives) {
|
||||
BaseTest.setUp();
|
||||
MetaTxNegatives.setUp();
|
||||
|
||||
holder = vm.addr(holderPk);
|
||||
profileId = _createProfile(holder);
|
||||
|
||||
vm.prank(governance);
|
||||
handleId = lensHandles.mintHandle(holder, 'handle');
|
||||
|
||||
domainSeparator = keccak256(
|
||||
abi.encode(
|
||||
Typehash.EIP712_DOMAIN,
|
||||
keccak256('TokenHandleRegistry'),
|
||||
keccak256(bytes('1')),
|
||||
block.chainid,
|
||||
address(tokenHandleRegistry)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function _incrementNonce(uint8 increment) internal override {
|
||||
vm.prank(vm.addr(_getDefaultMetaTxSignerPk()));
|
||||
tokenHandleRegistry.incrementNonce(increment);
|
||||
}
|
||||
|
||||
function _getDefaultMetaTxSignerPk() internal override returns (uint256) {
|
||||
return holderPk;
|
||||
}
|
||||
|
||||
function _getMetaTxNonce(address signer) internal override returns (uint256) {
|
||||
return tokenHandleRegistry.nonces(signer);
|
||||
}
|
||||
|
||||
function _getDomainName() internal override returns (bytes memory) {
|
||||
return bytes('TokenHandleRegistry');
|
||||
}
|
||||
|
||||
function _getRevisionNumber() internal override returns (bytes memory) {
|
||||
return bytes('1');
|
||||
}
|
||||
|
||||
function _getVerifyingContract() internal override returns (address) {
|
||||
return address(tokenHandleRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
contract TokenHandleRegistryLinkMetaTxTest is TokenHandleRegistryMetaTxBaseTest {
|
||||
function testFreshLinkWithSig(address relayer) public {
|
||||
vm.assume(relayer != holder);
|
||||
vm.assume(relayer != address(0));
|
||||
vm.assume(!_isLensHubProxyAdmin(relayer));
|
||||
|
||||
RegistryTypes.Handle memory handle = RegistryTypes.Handle({collection: address(lensHandles), id: handleId});
|
||||
RegistryTypes.Token memory token = RegistryTypes.Token({collection: address(hub), id: profileId});
|
||||
|
||||
Types.EIP712Signature memory sig = _getLinkSigStruct(holder, holderPk, _getMetaTxNonce(holder), NO_DEADLINE);
|
||||
|
||||
vm.expectEmit(true, true, true, true, address(tokenHandleRegistry));
|
||||
emit RegistryEvents.HandleLinked(handle, token, holder, block.timestamp);
|
||||
|
||||
vm.prank(relayer);
|
||||
tokenHandleRegistry.linkWithSig(handleId, profileId, sig);
|
||||
|
||||
assertEq(tokenHandleRegistry.resolve(handleId), profileId);
|
||||
assertEq(tokenHandleRegistry.getDefaultHandle(profileId), handleId);
|
||||
}
|
||||
|
||||
function testFreshLinkWithSig_WithERC1271Wallet() public {
|
||||
uint256 walletOwnerPk = 0x77a1137077438;
|
||||
address walletOwner = vm.addr(walletOwnerPk);
|
||||
|
||||
address relayer = makeAddr('relayer');
|
||||
|
||||
address wallet = address(new ERC1271WalletMock(walletOwner));
|
||||
|
||||
_transferHandle(wallet, handleId);
|
||||
_transferProfile(wallet, profileId);
|
||||
|
||||
RegistryTypes.Handle memory handle = RegistryTypes.Handle({collection: address(lensHandles), id: handleId});
|
||||
RegistryTypes.Token memory token = RegistryTypes.Token({collection: address(hub), id: profileId});
|
||||
|
||||
Types.EIP712Signature memory sig = _getLinkSigStruct(wallet, walletOwnerPk, _getMetaTxNonce(wallet), NO_DEADLINE);
|
||||
|
||||
vm.expectEmit(true, true, true, true, address(tokenHandleRegistry));
|
||||
emit RegistryEvents.HandleLinked(handle, token, wallet, block.timestamp);
|
||||
|
||||
vm.prank(address(relayer));
|
||||
tokenHandleRegistry.linkWithSig(handleId, profileId, sig);
|
||||
|
||||
assertEq(tokenHandleRegistry.resolve(handleId), profileId);
|
||||
assertEq(tokenHandleRegistry.getDefaultHandle(profileId), handleId);
|
||||
}
|
||||
|
||||
function testCannot_LinkWithSig_IfWalletValidationFails() public {
|
||||
uint256 otherPk = 0x07438;
|
||||
address walletOwner = makeAddr('walletOwner');
|
||||
|
||||
address relayer = makeAddr('relayer');
|
||||
|
||||
address wallet = address(new ERC1271WalletMock(walletOwner));
|
||||
|
||||
_transferHandle(wallet, handleId);
|
||||
_transferProfile(wallet, profileId);
|
||||
|
||||
Types.EIP712Signature memory sig = _getLinkSigStruct(wallet, otherPk, _getMetaTxNonce(wallet), NO_DEADLINE);
|
||||
|
||||
vm.expectRevert(Errors.SignatureInvalid.selector);
|
||||
|
||||
vm.prank(relayer);
|
||||
tokenHandleRegistry.linkWithSig(handleId, profileId, sig);
|
||||
}
|
||||
|
||||
function _executeMetaTx(uint256 pKey, uint256 nonce, uint256 deadline) internal override {
|
||||
tokenHandleRegistry.linkWithSig({
|
||||
handleId: handleId,
|
||||
profileId: profileId,
|
||||
signature: _getLinkSigStruct({
|
||||
signer: vm.addr(_getDefaultMetaTxSignerPk()),
|
||||
pKey: pKey,
|
||||
nonce: nonce,
|
||||
deadline: deadline
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function _getLinkSigStruct(
|
||||
address signer,
|
||||
uint256 pKey,
|
||||
uint256 nonce,
|
||||
uint256 deadline
|
||||
) internal view returns (Types.EIP712Signature memory) {
|
||||
return _getSigStruct({
|
||||
signer: signer,
|
||||
pKey: pKey,
|
||||
deadline: deadline,
|
||||
digest: _calculateDigest(
|
||||
keccak256(
|
||||
abi.encode(
|
||||
NamespacesTypehash.LINK,
|
||||
handleId,
|
||||
profileId,
|
||||
signer,
|
||||
nonce,
|
||||
deadline
|
||||
)
|
||||
)
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
contract TokenHandleRegistryUnlinkMetaTxTest is TokenHandleRegistryMetaTxBaseTest {
|
||||
function testUnlinkWithSig(address relayer) public {
|
||||
vm.assume(relayer != holder);
|
||||
vm.assume(relayer != address(0));
|
||||
vm.assume(!_isLensHubProxyAdmin(relayer));
|
||||
|
||||
vm.prank(holder);
|
||||
tokenHandleRegistry.link(handleId, profileId);
|
||||
|
||||
assertEq(tokenHandleRegistry.resolve(handleId), profileId);
|
||||
assertEq(tokenHandleRegistry.getDefaultHandle(profileId), handleId);
|
||||
|
||||
RegistryTypes.Handle memory handle = RegistryTypes.Handle({collection: address(lensHandles), id: handleId});
|
||||
RegistryTypes.Token memory token = RegistryTypes.Token({collection: address(hub), id: profileId});
|
||||
|
||||
Types.EIP712Signature memory sig = _getUnlinkSigStruct(holder, holderPk, _getMetaTxNonce(holder), NO_DEADLINE);
|
||||
|
||||
vm.expectEmit(true, true, true, true, address(tokenHandleRegistry));
|
||||
emit RegistryEvents.HandleUnlinked(handle, token, holder, block.timestamp);
|
||||
|
||||
vm.prank(relayer);
|
||||
tokenHandleRegistry.unlinkWithSig(handleId, profileId, sig);
|
||||
|
||||
assertEq(tokenHandleRegistry.resolve(handleId), 0);
|
||||
assertEq(tokenHandleRegistry.getDefaultHandle(profileId), 0);
|
||||
}
|
||||
|
||||
function testUnlinkWithSig_WithERC1271Wallet() public {
|
||||
uint256 walletOwnerPk = 0x77a1137077438;
|
||||
address walletOwner = vm.addr(walletOwnerPk);
|
||||
|
||||
address relayer = makeAddr('relayer');
|
||||
|
||||
address wallet = address(new ERC1271WalletMock(walletOwner));
|
||||
|
||||
_transferHandle(wallet, handleId);
|
||||
_transferProfile(wallet, profileId);
|
||||
|
||||
vm.prank(wallet);
|
||||
tokenHandleRegistry.link(handleId, profileId);
|
||||
|
||||
assertEq(tokenHandleRegistry.resolve(handleId), profileId);
|
||||
assertEq(tokenHandleRegistry.getDefaultHandle(profileId), handleId);
|
||||
|
||||
RegistryTypes.Handle memory handle = RegistryTypes.Handle({collection: address(lensHandles), id: handleId});
|
||||
RegistryTypes.Token memory token = RegistryTypes.Token({collection: address(hub), id: profileId});
|
||||
|
||||
Types.EIP712Signature memory sig = _getUnlinkSigStruct(wallet, walletOwnerPk, _getMetaTxNonce(wallet), NO_DEADLINE);
|
||||
|
||||
vm.expectEmit(true, true, true, true, address(tokenHandleRegistry));
|
||||
emit RegistryEvents.HandleUnlinked(handle, token, wallet, block.timestamp);
|
||||
|
||||
vm.prank(relayer);
|
||||
tokenHandleRegistry.unlinkWithSig(handleId, profileId, sig);
|
||||
|
||||
assertEq(tokenHandleRegistry.resolve(handleId), 0);
|
||||
assertEq(tokenHandleRegistry.getDefaultHandle(profileId), 0);
|
||||
}
|
||||
|
||||
function testCannot_UnlinkWithSig_IfWalletValidationFails() public {
|
||||
uint256 otherPk = 0x07438;
|
||||
address walletOwner = makeAddr('walletOwner');
|
||||
|
||||
address relayer = makeAddr('relayer');
|
||||
|
||||
address wallet = address(new ERC1271WalletMock(walletOwner));
|
||||
|
||||
_transferHandle(wallet, handleId);
|
||||
_transferProfile(wallet, profileId);
|
||||
|
||||
vm.prank(wallet);
|
||||
tokenHandleRegistry.link(handleId, profileId);
|
||||
|
||||
assertEq(tokenHandleRegistry.resolve(handleId), profileId);
|
||||
assertEq(tokenHandleRegistry.getDefaultHandle(profileId), handleId);
|
||||
|
||||
Types.EIP712Signature memory sig = _getUnlinkSigStruct(wallet, otherPk, _getMetaTxNonce(wallet), NO_DEADLINE);
|
||||
|
||||
vm.expectRevert(Errors.SignatureInvalid.selector);
|
||||
|
||||
vm.prank(relayer);
|
||||
tokenHandleRegistry.unlinkWithSig(handleId, profileId, sig);
|
||||
}
|
||||
|
||||
function _executeMetaTx(uint256 signerPk, uint256 nonce, uint256 deadline) internal override {
|
||||
tokenHandleRegistry.unlinkWithSig({
|
||||
handleId: handleId,
|
||||
profileId: profileId,
|
||||
signature: _getUnlinkSigStruct({
|
||||
signer: vm.addr(_getDefaultMetaTxSignerPk()),
|
||||
pKey: signerPk,
|
||||
nonce: nonce,
|
||||
deadline: deadline
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function _getUnlinkSigStruct(
|
||||
address signer,
|
||||
uint256 pKey,
|
||||
uint256 nonce,
|
||||
uint256 deadline
|
||||
) internal view returns (Types.EIP712Signature memory) {
|
||||
return _getSigStruct({
|
||||
signer: signer,
|
||||
pKey: pKey,
|
||||
deadline: deadline,
|
||||
digest: _calculateDigest(
|
||||
keccak256(
|
||||
abi.encode(
|
||||
NamespacesTypehash.UNLINK,
|
||||
handleId,
|
||||
profileId,
|
||||
signer,
|
||||
nonce,
|
||||
deadline
|
||||
)
|
||||
)
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user