mirror of
https://github.com/lens-protocol/core.git
synced 2026-01-09 14:18:04 -05:00
feat: PublicActProxy - added universal publicPaidAct
This commit is contained in:
@@ -29,4 +29,6 @@ library Typehash {
|
||||
bytes32 constant SET_PROFILE_METADATA_URI = keccak256('SetProfileMetadataURI(uint256 profileId,string metadataURI,uint256 nonce,uint256 deadline)');
|
||||
|
||||
bytes32 constant UNFOLLOW = keccak256('Unfollow(uint256 unfollowerProfileId,uint256[] idsOfProfilesToUnfollow,uint256 nonce,uint256 deadline)');
|
||||
|
||||
bytes32 constant PUBLIC_PAID_ACT = keccak256('PublicPaidAct(uint256 publicationActedProfileId,uint256 publicationActedId,uint256 actorProfileId,uint256[] referrerProfileIds,uint256[] referrerPubIds,address actionModuleAddress,bytes actionModuleData,address currency,uint256 amount,address approveTo,uint256 nonce,uint256 deadline)');
|
||||
}
|
||||
|
||||
@@ -8,7 +8,10 @@ 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 {MetaTxLib} from 'contracts/libraries/MetaTxLib.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';
|
||||
|
||||
interface IProtocolSharedRevenueMinFeeMintModule {
|
||||
function getMintFeeParams() external view returns (address, uint256);
|
||||
@@ -19,6 +22,10 @@ interface IProtocolSharedRevenueMinFeeMintModule {
|
||||
/// @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;
|
||||
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
ILensHub public immutable HUB;
|
||||
@@ -59,42 +66,183 @@ contract PublicActProxy {
|
||||
HUB.act(publicationActionParams);
|
||||
}
|
||||
|
||||
function publicPaidAct(
|
||||
Types.PublicationActionParams calldata publicationActionParams,
|
||||
address currency,
|
||||
uint256 amount,
|
||||
address approveTo
|
||||
) external {
|
||||
_publicAct(publicationActionParams, currency, amount, approveTo, msg.sender);
|
||||
}
|
||||
|
||||
function publicPaidActWithSig(
|
||||
Types.PublicationActionParams calldata publicationActionParams,
|
||||
address currency,
|
||||
uint256 amount,
|
||||
address approveTo,
|
||||
Types.EIP712Signature calldata signature
|
||||
) external {
|
||||
_validatePaidActSignature(signature, publicationActionParams, PaymentParams(currency, amount, approveTo));
|
||||
_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:
|
||||
function publicCollect(Types.PublicationActionParams calldata publicationActionParams) external {
|
||||
_publicCollect(publicationActionParams, msg.sender);
|
||||
}
|
||||
|
||||
// DEPRECATED:
|
||||
function publicCollectWithSig(
|
||||
Types.PublicationActionParams calldata publicationActionParams,
|
||||
Types.EIP712Signature calldata signature
|
||||
) external {
|
||||
MetaTxLib.validateActSignature(signature, publicationActionParams);
|
||||
_validateActSignature(signature, publicationActionParams);
|
||||
_publicCollect(publicationActionParams, signature.signer);
|
||||
}
|
||||
|
||||
function publicSharedRevenueCollect(Types.PublicationActionParams calldata publicationActionParams) external {
|
||||
_publicSharedRevenueCollect(publicationActionParams, msg.sender);
|
||||
}
|
||||
// Internal functions
|
||||
|
||||
function publicSharedRevenueCollectWithSig(
|
||||
function _publicAct(
|
||||
Types.PublicationActionParams calldata publicationActionParams,
|
||||
Types.EIP712Signature calldata signature
|
||||
) external {
|
||||
MetaTxLib.validateActSignature(signature, publicationActionParams);
|
||||
_publicSharedRevenueCollect(publicationActionParams, signature.signer);
|
||||
}
|
||||
|
||||
function nonces(address signer) public view returns (uint256) {
|
||||
return _nonces[signer];
|
||||
}
|
||||
|
||||
function incrementNonce(uint8 increment) external {
|
||||
MetaTxLib.incrementNonce(increment);
|
||||
address currency,
|
||||
uint256 amount,
|
||||
address approveTo,
|
||||
address transactionExecutor
|
||||
) internal {
|
||||
if (amount > 0) {
|
||||
IERC20(currency).safeTransferFrom(transactionExecutor, address(this), amount);
|
||||
IERC20(currency).safeIncreaseAllowance(approveTo, amount);
|
||||
}
|
||||
HUB.act(publicationActionParams);
|
||||
}
|
||||
|
||||
// DEPRECATED:
|
||||
function _publicCollect(
|
||||
Types.PublicationActionParams calldata publicationActionParams,
|
||||
address transactionExecutor
|
||||
@@ -119,36 +267,20 @@ contract PublicActProxy {
|
||||
HUB.act(publicationActionParams);
|
||||
}
|
||||
|
||||
function _publicSharedRevenueCollect(
|
||||
Types.PublicationActionParams calldata publicationActionParams,
|
||||
address transactionExecutor
|
||||
) internal {
|
||||
address collectModule = COLLECT_PUBLICATION_ACTION
|
||||
.getCollectData(
|
||||
publicationActionParams.publicationActedProfileId,
|
||||
publicationActionParams.publicationActedId
|
||||
)
|
||||
.collectModule;
|
||||
// View functions
|
||||
|
||||
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);
|
||||
} else {
|
||||
(address currency, uint256 amount) = IProtocolSharedRevenueMinFeeMintModule(collectModule)
|
||||
.getMintFeeParams();
|
||||
IERC20(currency).safeTransferFrom(transactionExecutor, address(this), amount);
|
||||
IERC20(currency).safeIncreaseAllowance(collectModule, amount);
|
||||
}
|
||||
|
||||
HUB.act(publicationActionParams);
|
||||
function nonces(address signer) public view returns (uint256) {
|
||||
return _nonces[signer];
|
||||
}
|
||||
|
||||
function name() external pure returns (string memory) {
|
||||
/// @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';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,320 +218,321 @@ contract PublicActProxyTest is BaseTest {
|
||||
assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
|
||||
}
|
||||
|
||||
function testCanPublicSharedRevenueCollectPaid() public {
|
||||
vm.prank(deployer);
|
||||
address revenueShareModule = address(
|
||||
new ProtocolSharedRevenueMinFeeMintModule(
|
||||
address(hub),
|
||||
address(collectPublicationAction),
|
||||
address(moduleRegistry),
|
||||
address(this)
|
||||
)
|
||||
);
|
||||
// TODO: Move these to the PublicSharedRevenue module tests and add the PublicPaidAct tests
|
||||
// function testCanPublicSharedRevenueCollectPaid() public {
|
||||
// vm.prank(deployer);
|
||||
// address revenueShareModule = addreeeess(
|
||||
// new ProtocolSharedRevenueMinFeeMintModule(
|
||||
// address(hub),
|
||||
// address(collectPublicationAction),
|
||||
// address(moduleRegistry),
|
||||
// address(this)
|
||||
// )
|
||||
// );
|
||||
|
||||
collectPublicationAction.registerCollectModule(revenueShareModule);
|
||||
// collectPublicationAction.registerCollectModule(revenueShareModule);
|
||||
|
||||
MockCurrency currency = new MockCurrency();
|
||||
currency.mint(payer, 10 ether);
|
||||
// MockCurrency currency = new MockCurrency();
|
||||
// currency.mint(payer, 10 ether);
|
||||
|
||||
ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
|
||||
exampleInitData.amount = 1 ether;
|
||||
exampleInitData.collectLimit = 0;
|
||||
exampleInitData.currency = address(currency);
|
||||
exampleInitData.referralFee = 0;
|
||||
exampleInitData.followerOnly = false;
|
||||
exampleInitData.endTimestamp = 0;
|
||||
exampleInitData.recipient = defaultAccount.owner;
|
||||
exampleInitData.creatorClient = address(0);
|
||||
// ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
|
||||
// exampleInitData.amount = 1 ether;
|
||||
// exampleInitData.collectLimit = 0;
|
||||
// exampleInitData.currency = address(currency);
|
||||
// exampleInitData.referralFee = 0;
|
||||
// exampleInitData.followerOnly = false;
|
||||
// exampleInitData.endTimestamp = 0;
|
||||
// exampleInitData.recipient = defaultAccount.owner;
|
||||
// exampleInitData.creatorClient = address(0);
|
||||
|
||||
Types.PostParams memory postParams = _getDefaultPostParams();
|
||||
postParams.actionModules[0] = address(collectPublicationAction);
|
||||
postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
|
||||
// Types.PostParams memory postParams = _getDefaultPostParams();
|
||||
// postParams.actionModules[0] = address(collectPublicationAction);
|
||||
// postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
|
||||
|
||||
vm.prank(defaultAccount.owner);
|
||||
defaultPubId = hub.post(postParams);
|
||||
// vm.prank(defaultAccount.owner);
|
||||
// defaultPubId = hub.post(postParams);
|
||||
|
||||
collectActionParams = Types.PublicationActionParams({
|
||||
publicationActedProfileId: defaultAccount.profileId,
|
||||
publicationActedId: defaultPubId,
|
||||
actorProfileId: publicProfile.profileId,
|
||||
referrerProfileIds: _emptyUint256Array(),
|
||||
referrerPubIds: _emptyUint256Array(),
|
||||
actionModuleAddress: address(collectPublicationAction),
|
||||
actionModuleData: abi.encode(nftRecipient, abi.encode(currency, exampleInitData.amount, address(0)))
|
||||
});
|
||||
// collectActionParams = Types.PublicationActionParams({
|
||||
// publicationActedProfileId: defaultAccount.profileId,
|
||||
// publicationActedId: defaultPubId,
|
||||
// actorProfileId: publicProfile.profileId,
|
||||
// referrerProfileIds: _emptyUint256Array(),
|
||||
// referrerPubIds: _emptyUint256Array(),
|
||||
// actionModuleAddress: address(collectPublicationAction),
|
||||
// actionModuleData: abi.encode(nftRecipient, abi.encode(currency, exampleInitData.amount, address(0)))
|
||||
// });
|
||||
|
||||
vm.startPrank(payer);
|
||||
currency.approve(address(publicActProxy), exampleInitData.amount);
|
||||
publicActProxy.publicSharedRevenueCollect(collectActionParams);
|
||||
vm.stopPrank();
|
||||
// vm.startPrank(payer);
|
||||
// currency.approve(address(publicActProxy), exampleInitData.amount);
|
||||
// publicActProxy.publicSharedRevenueCollect(collectActionParams);
|
||||
// vm.stopPrank();
|
||||
|
||||
CollectNFT collectNFT = CollectNFT(
|
||||
CollectPublicationAction(collectPublicationAction)
|
||||
.getCollectData(defaultAccount.profileId, defaultPubId)
|
||||
.collectNFT
|
||||
);
|
||||
// CollectNFT collectNFT = CollectNFT(
|
||||
// CollectPublicationAction(collectPublicationAction)
|
||||
// .getCollectData(defaultAccount.profileId, defaultPubId)
|
||||
// .collectNFT
|
||||
// );
|
||||
|
||||
assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
|
||||
}
|
||||
// assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
|
||||
// }
|
||||
|
||||
function testCanPublicSharedRevenueCollectPaidWithSig() public {
|
||||
vm.prank(deployer);
|
||||
address revenueShareModule = address(
|
||||
new ProtocolSharedRevenueMinFeeMintModule(
|
||||
address(hub),
|
||||
address(collectPublicationAction),
|
||||
address(moduleRegistry),
|
||||
address(this)
|
||||
)
|
||||
);
|
||||
// function testCanPublicSharedRevenueCollectPaidWithSig() public {
|
||||
// vm.prank(deployer);
|
||||
// address revenueShareModule = address(
|
||||
// new ProtocolSharedRevenueMinFeeMintModule(
|
||||
// address(hub),
|
||||
// address(collectPublicationAction),
|
||||
// address(moduleRegistry),
|
||||
// address(this)
|
||||
// )
|
||||
// );
|
||||
|
||||
collectPublicationAction.registerCollectModule(revenueShareModule);
|
||||
// collectPublicationAction.registerCollectModule(revenueShareModule);
|
||||
|
||||
MockCurrency currency = new MockCurrency();
|
||||
currency.mint(payer, 10 ether);
|
||||
// MockCurrency currency = new MockCurrency();
|
||||
// currency.mint(payer, 10 ether);
|
||||
|
||||
ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
|
||||
exampleInitData.amount = 1 ether;
|
||||
exampleInitData.collectLimit = 0;
|
||||
exampleInitData.currency = address(currency);
|
||||
exampleInitData.referralFee = 0;
|
||||
exampleInitData.followerOnly = false;
|
||||
exampleInitData.endTimestamp = 0;
|
||||
exampleInitData.recipient = defaultAccount.owner;
|
||||
exampleInitData.creatorClient = address(0);
|
||||
// ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
|
||||
// exampleInitData.amount = 1 ether;
|
||||
// exampleInitData.collectLimit = 0;
|
||||
// exampleInitData.currency = address(currency);
|
||||
// exampleInitData.referralFee = 0;
|
||||
// exampleInitData.followerOnly = false;
|
||||
// exampleInitData.endTimestamp = 0;
|
||||
// exampleInitData.recipient = defaultAccount.owner;
|
||||
// exampleInitData.creatorClient = address(0);
|
||||
|
||||
Types.PostParams memory postParams = _getDefaultPostParams();
|
||||
postParams.actionModules[0] = address(collectPublicationAction);
|
||||
postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
|
||||
// Types.PostParams memory postParams = _getDefaultPostParams();
|
||||
// postParams.actionModules[0] = address(collectPublicationAction);
|
||||
// postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
|
||||
|
||||
vm.prank(defaultAccount.owner);
|
||||
defaultPubId = hub.post(postParams);
|
||||
// vm.prank(defaultAccount.owner);
|
||||
// defaultPubId = hub.post(postParams);
|
||||
|
||||
collectActionParams = Types.PublicationActionParams({
|
||||
publicationActedProfileId: defaultAccount.profileId,
|
||||
publicationActedId: defaultPubId,
|
||||
actorProfileId: publicProfile.profileId,
|
||||
referrerProfileIds: _emptyUint256Array(),
|
||||
referrerPubIds: _emptyUint256Array(),
|
||||
actionModuleAddress: address(collectPublicationAction),
|
||||
actionModuleData: abi.encode(nftRecipient, abi.encode(currency, exampleInitData.amount, address(0)))
|
||||
});
|
||||
// collectActionParams = Types.PublicationActionParams({
|
||||
// publicationActedProfileId: defaultAccount.profileId,
|
||||
// publicationActedId: defaultPubId,
|
||||
// actorProfileId: publicProfile.profileId,
|
||||
// referrerProfileIds: _emptyUint256Array(),
|
||||
// referrerPubIds: _emptyUint256Array(),
|
||||
// actionModuleAddress: address(collectPublicationAction),
|
||||
// actionModuleData: abi.encode(nftRecipient, abi.encode(currency, exampleInitData.amount, address(0)))
|
||||
// });
|
||||
|
||||
vm.prank(payer);
|
||||
currency.approve(address(publicActProxy), exampleInitData.amount);
|
||||
// vm.prank(payer);
|
||||
// currency.approve(address(publicActProxy), exampleInitData.amount);
|
||||
|
||||
domainSeparator = keccak256(
|
||||
abi.encode(
|
||||
Typehash.EIP712_DOMAIN,
|
||||
keccak256('PublicActProxy'),
|
||||
MetaTxLib.EIP712_DOMAIN_VERSION_HASH,
|
||||
block.chainid,
|
||||
address(publicActProxy)
|
||||
)
|
||||
);
|
||||
// domainSeparator = keccak256(
|
||||
// abi.encode(
|
||||
// Typehash.EIP712_DOMAIN,
|
||||
// keccak256('PublicActProxy'),
|
||||
// MetaTxLib.EIP712_DOMAIN_VERSION_HASH,
|
||||
// block.chainid,
|
||||
// address(publicActProxy)
|
||||
// )
|
||||
// );
|
||||
|
||||
publicActProxy.publicSharedRevenueCollectWithSig({
|
||||
publicationActionParams: collectActionParams,
|
||||
signature: _getSigStruct({
|
||||
pKey: payerPk,
|
||||
digest: _getActTypedDataHash(collectActionParams, publicActProxy.nonces(payer), type(uint256).max),
|
||||
deadline: type(uint256).max
|
||||
})
|
||||
});
|
||||
// publicActProxy.publicSharedRevenueCollectWithSig({
|
||||
// publicationActionParams: collectActionParams,
|
||||
// signature: _getSigStruct({
|
||||
// pKey: payerPk,
|
||||
// digest: _getActTypedDataHash(collectActionParams, publicActProxy.nonces(payer), type(uint256).max),
|
||||
// deadline: type(uint256).max
|
||||
// })
|
||||
// });
|
||||
|
||||
CollectNFT collectNFT = CollectNFT(
|
||||
CollectPublicationAction(collectPublicationAction)
|
||||
.getCollectData(defaultAccount.profileId, defaultPubId)
|
||||
.collectNFT
|
||||
);
|
||||
// CollectNFT collectNFT = CollectNFT(
|
||||
// CollectPublicationAction(collectPublicationAction)
|
||||
// .getCollectData(defaultAccount.profileId, defaultPubId)
|
||||
// .collectNFT
|
||||
// );
|
||||
|
||||
assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
|
||||
}
|
||||
// assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
|
||||
// }
|
||||
|
||||
function testCanPublicSharedRevenueCollectFree() public {
|
||||
address creatorClient = makeAddr('CREATOR_CLIENT');
|
||||
address executorClient = makeAddr('EXECUTOR_CLIENT');
|
||||
// function testCanPublicSharedRevenueCollectFree() public {
|
||||
// address creatorClient = makeAddr('CREATOR_CLIENT');
|
||||
// address executorClient = makeAddr('EXECUTOR_CLIENT');
|
||||
|
||||
uint256 mintFee = 10 ether;
|
||||
// uint256 mintFee = 10 ether;
|
||||
|
||||
vm.prank(deployer);
|
||||
address revenueShareModule = address(
|
||||
new ProtocolSharedRevenueMinFeeMintModule(
|
||||
address(hub),
|
||||
address(collectPublicationAction),
|
||||
address(moduleRegistry),
|
||||
address(this)
|
||||
)
|
||||
);
|
||||
// vm.prank(deployer);
|
||||
// address revenueShareModule = address(
|
||||
// new ProtocolSharedRevenueMinFeeMintModule(
|
||||
// address(hub),
|
||||
// address(collectPublicationAction),
|
||||
// address(moduleRegistry),
|
||||
// address(this)
|
||||
// )
|
||||
// );
|
||||
|
||||
collectPublicationAction.registerCollectModule(revenueShareModule);
|
||||
// collectPublicationAction.registerCollectModule(revenueShareModule);
|
||||
|
||||
MockCurrency currency = new MockCurrency();
|
||||
currency.mint(payer, mintFee);
|
||||
// MockCurrency currency = new MockCurrency();
|
||||
// currency.mint(payer, mintFee);
|
||||
|
||||
ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setMintFeeParams(address(currency), mintFee);
|
||||
ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setProtocolSharedRevenueDistribution(
|
||||
ProtocolSharedRevenueDistribution({
|
||||
creatorSplit: 5000,
|
||||
protocolSplit: 2000,
|
||||
creatorClientSplit: 1500,
|
||||
executorClientSplit: 1500
|
||||
})
|
||||
);
|
||||
// ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setMintFeeParams(address(currency), mintFee);
|
||||
// ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setProtocolSharedRevenueDistribution(
|
||||
// ProtocolSharedRevenueDistribution({
|
||||
// creatorSplit: 5000,
|
||||
// protocolSplit: 2000,
|
||||
// creatorClientSplit: 1500,
|
||||
// executorClientSplit: 1500
|
||||
// })
|
||||
// );
|
||||
|
||||
ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
|
||||
exampleInitData.amount = 0 ether;
|
||||
exampleInitData.collectLimit = 0;
|
||||
exampleInitData.currency = address(0);
|
||||
exampleInitData.referralFee = 0;
|
||||
exampleInitData.followerOnly = false;
|
||||
exampleInitData.endTimestamp = 0;
|
||||
exampleInitData.recipient = defaultAccount.owner;
|
||||
exampleInitData.creatorClient = creatorClient;
|
||||
// ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
|
||||
// exampleInitData.amount = 0 ether;
|
||||
// exampleInitData.collectLimit = 0;
|
||||
// exampleInitData.currency = address(0);
|
||||
// exampleInitData.referralFee = 0;
|
||||
// exampleInitData.followerOnly = false;
|
||||
// exampleInitData.endTimestamp = 0;
|
||||
// exampleInitData.recipient = defaultAccount.owner;
|
||||
// exampleInitData.creatorClient = creatorClient;
|
||||
|
||||
Types.PostParams memory postParams = _getDefaultPostParams();
|
||||
postParams.actionModules[0] = address(collectPublicationAction);
|
||||
postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
|
||||
// Types.PostParams memory postParams = _getDefaultPostParams();
|
||||
// postParams.actionModules[0] = address(collectPublicationAction);
|
||||
// postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
|
||||
|
||||
vm.prank(defaultAccount.owner);
|
||||
defaultPubId = hub.post(postParams);
|
||||
// vm.prank(defaultAccount.owner);
|
||||
// defaultPubId = hub.post(postParams);
|
||||
|
||||
collectActionParams = Types.PublicationActionParams({
|
||||
publicationActedProfileId: defaultAccount.profileId,
|
||||
publicationActedId: defaultPubId,
|
||||
actorProfileId: publicProfile.profileId,
|
||||
referrerProfileIds: _emptyUint256Array(),
|
||||
referrerPubIds: _emptyUint256Array(),
|
||||
actionModuleAddress: address(collectPublicationAction),
|
||||
actionModuleData: abi.encode(
|
||||
nftRecipient,
|
||||
abi.encode(exampleInitData.currency, exampleInitData.amount, executorClient)
|
||||
)
|
||||
});
|
||||
// collectActionParams = Types.PublicationActionParams({
|
||||
// publicationActedProfileId: defaultAccount.profileId,
|
||||
// publicationActedId: defaultPubId,
|
||||
// actorProfileId: publicProfile.profileId,
|
||||
// referrerProfileIds: _emptyUint256Array(),
|
||||
// referrerPubIds: _emptyUint256Array(),
|
||||
// actionModuleAddress: address(collectPublicationAction),
|
||||
// actionModuleData: abi.encode(
|
||||
// nftRecipient,
|
||||
// abi.encode(exampleInitData.currency, exampleInitData.amount, executorClient)
|
||||
// )
|
||||
// });
|
||||
|
||||
vm.startPrank(payer);
|
||||
currency.approve(address(publicActProxy), mintFee);
|
||||
publicActProxy.publicSharedRevenueCollect(collectActionParams);
|
||||
vm.stopPrank();
|
||||
// vm.startPrank(payer);
|
||||
// currency.approve(address(publicActProxy), mintFee);
|
||||
// publicActProxy.publicSharedRevenueCollect(collectActionParams);
|
||||
// vm.stopPrank();
|
||||
|
||||
CollectNFT collectNFT = CollectNFT(
|
||||
CollectPublicationAction(collectPublicationAction)
|
||||
.getCollectData(defaultAccount.profileId, defaultPubId)
|
||||
.collectNFT
|
||||
);
|
||||
// CollectNFT collectNFT = CollectNFT(
|
||||
// CollectPublicationAction(collectPublicationAction)
|
||||
// .getCollectData(defaultAccount.profileId, defaultPubId)
|
||||
// .collectNFT
|
||||
// );
|
||||
|
||||
assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
|
||||
// assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
|
||||
|
||||
assertEq(currency.balanceOf(defaultAccount.owner), (mintFee * 5000) / 10000, 'Creator balance is incorrect');
|
||||
assertEq(
|
||||
currency.balanceOf(hub.getTreasury()),
|
||||
(mintFee * 2000) / 10000,
|
||||
'Protocol treasury client balance is incorrect'
|
||||
);
|
||||
assertEq(currency.balanceOf(creatorClient), (mintFee * 1500) / 10000, 'Creator client balance is incorrect');
|
||||
assertEq(currency.balanceOf(executorClient), (mintFee * 1500) / 10000, 'Executor client balance is incorrect');
|
||||
}
|
||||
// assertEq(currency.balanceOf(defaultAccount.owner), (mintFee * 5000) / 10000, 'Creator balance is incorrect');
|
||||
// assertEq(
|
||||
// currency.balanceOf(hub.getTreasury()),
|
||||
// (mintFee * 2000) / 10000,
|
||||
// 'Protocol treasury client balance is incorrect'
|
||||
// );
|
||||
// assertEq(currency.balanceOf(creatorClient), (mintFee * 1500) / 10000, 'Creator client balance is incorrect');
|
||||
// assertEq(currency.balanceOf(executorClient), (mintFee * 1500) / 10000, 'Executor client balance is incorrect');
|
||||
// }
|
||||
|
||||
function testCanPublicSharedRevenueCollectFreeWithSig() public {
|
||||
address creatorClient = makeAddr('CREATOR_CLIENT');
|
||||
address executorClient = makeAddr('EXECUTOR_CLIENT');
|
||||
// function testCanPublicSharedRevenueCollectFreeWithSig() public {
|
||||
// address creatorClient = makeAddr('CREATOR_CLIENT');
|
||||
// address executorClient = makeAddr('EXECUTOR_CLIENT');
|
||||
|
||||
uint256 mintFee = 10 ether;
|
||||
// uint256 mintFee = 10 ether;
|
||||
|
||||
vm.prank(deployer);
|
||||
address revenueShareModule = address(
|
||||
new ProtocolSharedRevenueMinFeeMintModule(
|
||||
address(hub),
|
||||
address(collectPublicationAction),
|
||||
address(moduleRegistry),
|
||||
address(this)
|
||||
)
|
||||
);
|
||||
// vm.prank(deployer);
|
||||
// address revenueShareModule = address(
|
||||
// new ProtocolSharedRevenueMinFeeMintModule(
|
||||
// address(hub),
|
||||
// address(collectPublicationAction),
|
||||
// address(moduleRegistry),
|
||||
// address(this)
|
||||
// )
|
||||
// );
|
||||
|
||||
collectPublicationAction.registerCollectModule(revenueShareModule);
|
||||
// collectPublicationAction.registerCollectModule(revenueShareModule);
|
||||
|
||||
MockCurrency currency = new MockCurrency();
|
||||
currency.mint(payer, mintFee);
|
||||
// MockCurrency currency = new MockCurrency();
|
||||
// currency.mint(payer, mintFee);
|
||||
|
||||
ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setMintFeeParams(address(currency), mintFee);
|
||||
ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setProtocolSharedRevenueDistribution(
|
||||
ProtocolSharedRevenueDistribution({
|
||||
creatorSplit: 5000,
|
||||
protocolSplit: 2000,
|
||||
creatorClientSplit: 1500,
|
||||
executorClientSplit: 1500
|
||||
})
|
||||
);
|
||||
// ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setMintFeeParams(address(currency), mintFee);
|
||||
// ProtocolSharedRevenueMinFeeMintModule(revenueShareModule).setProtocolSharedRevenueDistribution(
|
||||
// ProtocolSharedRevenueDistribution({
|
||||
// creatorSplit: 5000,
|
||||
// protocolSplit: 2000,
|
||||
// creatorClientSplit: 1500,
|
||||
// executorClientSplit: 1500
|
||||
// })
|
||||
// );
|
||||
|
||||
ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
|
||||
exampleInitData.amount = 0 ether;
|
||||
exampleInitData.collectLimit = 0;
|
||||
exampleInitData.currency = address(0);
|
||||
exampleInitData.referralFee = 0;
|
||||
exampleInitData.followerOnly = false;
|
||||
exampleInitData.endTimestamp = 0;
|
||||
exampleInitData.recipient = defaultAccount.owner;
|
||||
exampleInitData.creatorClient = creatorClient;
|
||||
// ProtocolSharedRevenueMinFeeMintModuleInitData memory exampleInitData;
|
||||
// exampleInitData.amount = 0 ether;
|
||||
// exampleInitData.collectLimit = 0;
|
||||
// exampleInitData.currency = address(0);
|
||||
// exampleInitData.referralFee = 0;
|
||||
// exampleInitData.followerOnly = false;
|
||||
// exampleInitData.endTimestamp = 0;
|
||||
// exampleInitData.recipient = defaultAccount.owner;
|
||||
// exampleInitData.creatorClient = creatorClient;
|
||||
|
||||
Types.PostParams memory postParams = _getDefaultPostParams();
|
||||
postParams.actionModules[0] = address(collectPublicationAction);
|
||||
postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
|
||||
// Types.PostParams memory postParams = _getDefaultPostParams();
|
||||
// postParams.actionModules[0] = address(collectPublicationAction);
|
||||
// postParams.actionModulesInitDatas[0] = abi.encode(revenueShareModule, abi.encode(exampleInitData));
|
||||
|
||||
vm.prank(defaultAccount.owner);
|
||||
defaultPubId = hub.post(postParams);
|
||||
// vm.prank(defaultAccount.owner);
|
||||
// defaultPubId = hub.post(postParams);
|
||||
|
||||
collectActionParams = Types.PublicationActionParams({
|
||||
publicationActedProfileId: defaultAccount.profileId,
|
||||
publicationActedId: defaultPubId,
|
||||
actorProfileId: publicProfile.profileId,
|
||||
referrerProfileIds: _emptyUint256Array(),
|
||||
referrerPubIds: _emptyUint256Array(),
|
||||
actionModuleAddress: address(collectPublicationAction),
|
||||
actionModuleData: abi.encode(
|
||||
nftRecipient,
|
||||
abi.encode(exampleInitData.currency, exampleInitData.amount, executorClient)
|
||||
)
|
||||
});
|
||||
// collectActionParams = Types.PublicationActionParams({
|
||||
// publicationActedProfileId: defaultAccount.profileId,
|
||||
// publicationActedId: defaultPubId,
|
||||
// actorProfileId: publicProfile.profileId,
|
||||
// referrerProfileIds: _emptyUint256Array(),
|
||||
// referrerPubIds: _emptyUint256Array(),
|
||||
// actionModuleAddress: address(collectPublicationAction),
|
||||
// actionModuleData: abi.encode(
|
||||
// nftRecipient,
|
||||
// abi.encode(exampleInitData.currency, exampleInitData.amount, executorClient)
|
||||
// )
|
||||
// });
|
||||
|
||||
vm.startPrank(payer);
|
||||
currency.approve(address(publicActProxy), mintFee);
|
||||
vm.stopPrank();
|
||||
// vm.startPrank(payer);
|
||||
// currency.approve(address(publicActProxy), mintFee);
|
||||
// vm.stopPrank();
|
||||
|
||||
domainSeparator = keccak256(
|
||||
abi.encode(
|
||||
Typehash.EIP712_DOMAIN,
|
||||
keccak256('PublicActProxy'),
|
||||
MetaTxLib.EIP712_DOMAIN_VERSION_HASH,
|
||||
block.chainid,
|
||||
address(publicActProxy)
|
||||
)
|
||||
);
|
||||
// domainSeparator = keccak256(
|
||||
// abi.encode(
|
||||
// Typehash.EIP712_DOMAIN,
|
||||
// keccak256('PublicActProxy'),
|
||||
// MetaTxLib.EIP712_DOMAIN_VERSION_HASH,
|
||||
// block.chainid,
|
||||
// address(publicActProxy)
|
||||
// )
|
||||
// );
|
||||
|
||||
publicActProxy.publicSharedRevenueCollectWithSig({
|
||||
publicationActionParams: collectActionParams,
|
||||
signature: _getSigStruct({
|
||||
pKey: payerPk,
|
||||
digest: _getActTypedDataHash(collectActionParams, publicActProxy.nonces(payer), type(uint256).max),
|
||||
deadline: type(uint256).max
|
||||
})
|
||||
});
|
||||
// publicActProxy.publicSharedRevenueCollectWithSig({
|
||||
// publicationActionParams: collectActionParams,
|
||||
// signature: _getSigStruct({
|
||||
// pKey: payerPk,
|
||||
// digest: _getActTypedDataHash(collectActionParams, publicActProxy.nonces(payer), type(uint256).max),
|
||||
// deadline: type(uint256).max
|
||||
// })
|
||||
// });
|
||||
|
||||
CollectNFT collectNFT = CollectNFT(
|
||||
CollectPublicationAction(collectPublicationAction)
|
||||
.getCollectData(defaultAccount.profileId, defaultPubId)
|
||||
.collectNFT
|
||||
);
|
||||
// CollectNFT collectNFT = CollectNFT(
|
||||
// CollectPublicationAction(collectPublicationAction)
|
||||
// .getCollectData(defaultAccount.profileId, defaultPubId)
|
||||
// .collectNFT
|
||||
// );
|
||||
|
||||
assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
|
||||
// assertTrue(collectNFT.balanceOf(nftRecipient) > 0, 'NFT recipient balance is 0');
|
||||
|
||||
assertEq(currency.balanceOf(defaultAccount.owner), (mintFee * 5000) / 10000, 'Creator balance is incorrect');
|
||||
assertEq(
|
||||
currency.balanceOf(hub.getTreasury()),
|
||||
(mintFee * 2000) / 10000,
|
||||
'Protocol treasury client balance is incorrect'
|
||||
);
|
||||
assertEq(currency.balanceOf(creatorClient), (mintFee * 1500) / 10000, 'Creator client balance is incorrect');
|
||||
assertEq(currency.balanceOf(executorClient), (mintFee * 1500) / 10000, 'Executor client balance is incorrect');
|
||||
}
|
||||
// assertEq(currency.balanceOf(defaultAccount.owner), (mintFee * 5000) / 10000, 'Creator balance is incorrect');
|
||||
// assertEq(
|
||||
// currency.balanceOf(hub.getTreasury()),
|
||||
// (mintFee * 2000) / 10000,
|
||||
// 'Protocol treasury client balance is incorrect'
|
||||
// );
|
||||
// assertEq(currency.balanceOf(creatorClient), (mintFee * 1500) / 10000, 'Creator client balance is incorrect');
|
||||
// assertEq(currency.balanceOf(executorClient), (mintFee * 1500) / 10000, 'Executor client balance is incorrect');
|
||||
// }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user