mirror of
https://github.com/lens-protocol/core.git
synced 2026-01-09 14:18:04 -05:00
misc: Removed deprecated functions from PublicActProxy and moved metaTx code into a separate file
This commit is contained in:
@@ -7,60 +7,47 @@ import {Types} from 'contracts/libraries/constants/Types.sol';
|
||||
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
|
||||
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
|
||||
import {CollectPublicationAction} from 'contracts/modules/act/collect/CollectPublicationAction.sol';
|
||||
import {BaseProfilePublicationData, IBaseFeeCollectModule} from 'contracts/modules/interfaces/IBaseFeeCollectModule.sol';
|
||||
import {Errors} from 'contracts/libraries/constants/Errors.sol';
|
||||
import {Events} from 'contracts/libraries/constants/Events.sol';
|
||||
import {Typehash} from 'contracts/libraries/constants/Typehash.sol';
|
||||
import {IERC1271} from '@openzeppelin/contracts/interfaces/IERC1271.sol';
|
||||
import {PublicActProxy_MetaTx} from 'contracts/misc/PublicActProxy_MetaTx.sol';
|
||||
|
||||
interface IProtocolSharedRevenueMinFeeMintModule {
|
||||
function getMintFeeParams() external view returns (address, uint256);
|
||||
}
|
||||
// This contract should be the owner/DE of the publicationActionParams.actorProfileId
|
||||
// This contract should be set as publicationActionParams.transactionExecutor
|
||||
// Correct collectNftRecipient should be passed in the publicationActionParams.actionModuleData
|
||||
|
||||
/*
|
||||
Here is an example of PublicationActionParams to pass:
|
||||
|
||||
struct PublicationActionParams {
|
||||
publicationActedProfileId: ---
|
||||
publicationActedId: ---
|
||||
actorProfileId: this contract's profile
|
||||
referrerProfileIds: ---
|
||||
referrerPubIds: ---
|
||||
actionModuleAddress: ---
|
||||
actionModuleData: {
|
||||
collectNftRecipient: who shall receive the NFT
|
||||
collectData: {
|
||||
expectedCurrency: should match what's stored in CollectModule
|
||||
expectedAmount: should match what's stored in CollectModule
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// @title PublicActProxy
|
||||
/// @author LensProtocol
|
||||
/// @notice This contract allows anyone to Act on a publication without holding a profile
|
||||
/// @dev This contract holds a profile (or is a DE of that profile) and acts on behalf of the caller
|
||||
contract PublicActProxy {
|
||||
string constant EIP712_DOMAIN_VERSION = '2';
|
||||
bytes32 constant EIP712_DOMAIN_VERSION_HASH = keccak256(bytes(EIP712_DOMAIN_VERSION));
|
||||
bytes4 constant EIP1271_MAGIC_VALUE = 0x1626ba7e;
|
||||
|
||||
contract PublicActProxy is PublicActProxy_MetaTx {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
ILensHub public immutable HUB;
|
||||
CollectPublicationAction public immutable COLLECT_PUBLICATION_ACTION;
|
||||
|
||||
uint[9] private __gap;
|
||||
mapping(address => uint256) private _nonces; // Slot 10 - to match with MetaTxLib/StorageLib
|
||||
|
||||
constructor(address lensHub, address collectPublicationAction) {
|
||||
HUB = ILensHub(lensHub);
|
||||
COLLECT_PUBLICATION_ACTION = CollectPublicationAction(collectPublicationAction);
|
||||
}
|
||||
|
||||
/*
|
||||
struct PublicationActionParams {
|
||||
publicationActedProfileId: ---
|
||||
publicationActedId: ---
|
||||
actorProfileId: this contract's profile
|
||||
referrerProfileIds: ---
|
||||
referrerPubIds: ---
|
||||
actionModuleAddress: ---
|
||||
actionModuleData: {
|
||||
collectNftRecipient: who shall receive the NFT
|
||||
collectData: {
|
||||
expectedCurrency: should match what's stored in CollectModule
|
||||
expectedAmount: should match what's stored in CollectModule
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// This contract should be the owner/DE of the publicationActionParams.actorProfileId
|
||||
// This contract should be set as publicationActionParams.transactionExecutor
|
||||
// Correct collectNftRecipient should be passed in the publicationActionParams.actionModuleData
|
||||
|
||||
// The free act is pretty simple, but should follow the rules above:
|
||||
/// @notice For actions not involving any ERC20 transfers or approvals from the actor
|
||||
/// @dev This is used in the same way as the general .act() function, while following the rules above.
|
||||
@@ -94,146 +81,6 @@ contract PublicActProxy {
|
||||
_publicAct(publicationActionParams, currency, amount, approveTo, signature.signer);
|
||||
}
|
||||
|
||||
struct PaymentParams {
|
||||
address currency;
|
||||
uint256 amount;
|
||||
address approveTo;
|
||||
}
|
||||
|
||||
function _validatePaidActSignature(
|
||||
Types.EIP712Signature calldata signature,
|
||||
Types.PublicationActionParams calldata publicationActionParams,
|
||||
PaymentParams memory paymentParams
|
||||
) internal {
|
||||
bytes memory encodedAbi = abi.encode(
|
||||
Typehash.PUBLIC_PAID_ACT,
|
||||
publicationActionParams.publicationActedProfileId,
|
||||
publicationActionParams.publicationActedId,
|
||||
publicationActionParams.actorProfileId,
|
||||
_encodeUsingEip712Rules(publicationActionParams.referrerProfileIds),
|
||||
_encodeUsingEip712Rules(publicationActionParams.referrerPubIds),
|
||||
publicationActionParams.actionModuleAddress,
|
||||
_encodeUsingEip712Rules(publicationActionParams.actionModuleData),
|
||||
paymentParams.currency,
|
||||
paymentParams.amount,
|
||||
paymentParams.approveTo,
|
||||
_getNonceIncrementAndEmitEvent(signature.signer),
|
||||
signature.deadline
|
||||
);
|
||||
_validateRecoveredAddress(_calculateDigest(keccak256(encodedAbi)), signature);
|
||||
}
|
||||
|
||||
function _validateActSignature(
|
||||
Types.EIP712Signature calldata signature,
|
||||
Types.PublicationActionParams calldata publicationActionParams
|
||||
) internal {
|
||||
_validateRecoveredAddress(
|
||||
_calculateDigest(
|
||||
keccak256(
|
||||
abi.encode(
|
||||
Typehash.ACT,
|
||||
publicationActionParams.publicationActedProfileId,
|
||||
publicationActionParams.publicationActedId,
|
||||
publicationActionParams.actorProfileId,
|
||||
_encodeUsingEip712Rules(publicationActionParams.referrerProfileIds),
|
||||
_encodeUsingEip712Rules(publicationActionParams.referrerPubIds),
|
||||
publicationActionParams.actionModuleAddress,
|
||||
_encodeUsingEip712Rules(publicationActionParams.actionModuleData),
|
||||
_getNonceIncrementAndEmitEvent(signature.signer),
|
||||
signature.deadline
|
||||
)
|
||||
)
|
||||
),
|
||||
signature
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Wrapper for ecrecover to reduce code size, used in meta-tx specific functions.
|
||||
*/
|
||||
function _validateRecoveredAddress(bytes32 digest, Types.EIP712Signature calldata signature) private view {
|
||||
if (block.timestamp > signature.deadline) revert Errors.SignatureExpired();
|
||||
// If the expected address is a contract, check the signature there.
|
||||
if (signature.signer.code.length != 0) {
|
||||
bytes memory concatenatedSig = abi.encodePacked(signature.r, signature.s, signature.v);
|
||||
if (IERC1271(signature.signer).isValidSignature(digest, concatenatedSig) != EIP1271_MAGIC_VALUE) {
|
||||
revert Errors.SignatureInvalid();
|
||||
}
|
||||
} else {
|
||||
address recoveredAddress = ecrecover(digest, signature.v, signature.r, signature.s);
|
||||
if (recoveredAddress == address(0) || recoveredAddress != signature.signer) {
|
||||
revert Errors.SignatureInvalid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _encodeUsingEip712Rules(bytes memory bytesValue) private pure returns (bytes32) {
|
||||
return keccak256(bytesValue);
|
||||
}
|
||||
|
||||
function _encodeUsingEip712Rules(uint256[] memory uint256Array) private pure returns (bytes32) {
|
||||
return keccak256(abi.encodePacked(uint256Array));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev This fetches a signer's current nonce and increments it so it's ready for the next meta-tx. Also emits
|
||||
* the `NonceUpdated` event.
|
||||
*
|
||||
* @param signer The address to get and increment the nonce for.
|
||||
*
|
||||
* @return uint256 The current nonce for the given signer prior to being incremented.
|
||||
*/
|
||||
function _getNonceIncrementAndEmitEvent(address signer) private returns (uint256) {
|
||||
uint256 currentNonce;
|
||||
unchecked {
|
||||
currentNonce = _nonces[signer]++;
|
||||
}
|
||||
emit Events.NonceUpdated(signer, currentNonce + 1, block.timestamp);
|
||||
return currentNonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates EIP712 digest based on the current DOMAIN_SEPARATOR.
|
||||
*
|
||||
* @param hashedMessage The message hash from which the digest should be calculated.
|
||||
*
|
||||
* @return bytes32 A 32-byte output representing the EIP712 digest.
|
||||
*/
|
||||
function _calculateDigest(bytes32 hashedMessage) private view returns (bytes32) {
|
||||
return keccak256(abi.encodePacked('\x19\x01', _calculateDomainSeparator(), hashedMessage));
|
||||
}
|
||||
|
||||
function _calculateDomainSeparator() internal view returns (bytes32) {
|
||||
return
|
||||
keccak256(
|
||||
abi.encode(
|
||||
Typehash.EIP712_DOMAIN,
|
||||
keccak256(bytes(name())),
|
||||
EIP712_DOMAIN_VERSION_HASH,
|
||||
block.chainid,
|
||||
address(this)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// For the paid collect to work, additional steps are required:
|
||||
// Collector should set enough allowance to this contract to pay for collect NFT
|
||||
// Funds will be taken from msg.sender
|
||||
// Funds will be approved from this contract to collectModule found in publication storage
|
||||
// DEPRECATED. Use publicPaidAct() function instead.
|
||||
function publicCollect(Types.PublicationActionParams calldata publicationActionParams) external {
|
||||
_publicCollect(publicationActionParams, msg.sender);
|
||||
}
|
||||
|
||||
// DEPRECATED. Use publicPaidActWithSig() function instead.
|
||||
function publicCollectWithSig(
|
||||
Types.PublicationActionParams calldata publicationActionParams,
|
||||
Types.EIP712Signature calldata signature
|
||||
) external {
|
||||
_validateActSignature(signature, publicationActionParams);
|
||||
_publicCollect(publicationActionParams, signature.signer);
|
||||
}
|
||||
|
||||
// Internal functions
|
||||
|
||||
function _publicAct(
|
||||
@@ -249,46 +96,4 @@ contract PublicActProxy {
|
||||
}
|
||||
HUB.act(publicationActionParams);
|
||||
}
|
||||
|
||||
// DEPRECATED:
|
||||
function _publicCollect(
|
||||
Types.PublicationActionParams calldata publicationActionParams,
|
||||
address transactionExecutor
|
||||
) internal {
|
||||
address collectModule = COLLECT_PUBLICATION_ACTION
|
||||
.getCollectData(
|
||||
publicationActionParams.publicationActedProfileId,
|
||||
publicationActionParams.publicationActedId
|
||||
)
|
||||
.collectModule;
|
||||
|
||||
BaseProfilePublicationData memory collectData = IBaseFeeCollectModule(collectModule).getBasePublicationData(
|
||||
publicationActionParams.publicationActedProfileId,
|
||||
publicationActionParams.publicationActedId
|
||||
);
|
||||
|
||||
if (collectData.amount > 0) {
|
||||
IERC20(collectData.currency).safeTransferFrom(transactionExecutor, address(this), collectData.amount);
|
||||
IERC20(collectData.currency).safeIncreaseAllowance(collectModule, collectData.amount);
|
||||
}
|
||||
|
||||
HUB.act(publicationActionParams);
|
||||
}
|
||||
|
||||
// View functions
|
||||
|
||||
function nonces(address signer) public view returns (uint256) {
|
||||
return _nonces[signer];
|
||||
}
|
||||
|
||||
/// @dev This function is used to invalidate signatures by incrementing the nonce
|
||||
function incrementNonce(uint8 increment) external {
|
||||
uint256 currentNonce = _nonces[msg.sender];
|
||||
_nonces[msg.sender] = currentNonce + increment;
|
||||
emit Events.NonceUpdated(msg.sender, currentNonce + increment, block.timestamp);
|
||||
}
|
||||
|
||||
function name() public pure returns (string memory) {
|
||||
return 'PublicActProxy';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user