interface ISNWPayDelegate3_1_1 is IERC165 {
function didPay(SNWDidPayData3_1_1 calldata data) external payable;
}
struct SNWDidPayData3_1_1 {
address payer;
uint256 projectId;
uint256 currentFundingCycleConfiguration;
SNWTokenAmount amount;
SNWTokenAmount forwardedAmount;
uint256 projectTokenCount;
address beneficiary;
bool preferClaimedTokens;
string memo;
bytes dataSourceMetadata;
bytes payerMetadata;
}
struct SNWTokenAmount {
address token;
uint256 value;
uint256 decimals;
uint256 currency;
}
import '@openzeppelin/contracts/token/ERC721/ERC721.sol';
import '@snx-protocol/contracts-v2/contracts/interfaces/ISNWFundingCycleDataSource.sol';
import '@snx-protocol/contracts-v2/contracts/interfaces/ISNWPayDelegate.sol';
import '@snx-protocol/contracts-v2/contracts/structs/SNWTokenAmount.sol';
contract NFTPayDelegate is ERC721, ISNWFundingCycleDataSource, ISNWPayDelegate {
error INVALID_PAYMENT_EVENT();
ISNWDirectory directory;
uint256 projectId;
SNWTokenAmount contributionThreshold;
uint256 supply;
// This contract can be used as a funding cycle data source to ensure its didPay function is called once the payment has gone through.
function payParams(SNWPayParamsData calldata _data)
external
view
override
returns (
uint256 weight,
string memory memo,
ISNWPayDelegate delegate
)
{
// Forward the received weight and memo, and use this contract as a pay delegate.
return (_data.weight, _data.memo, ISNWPayDelegate(address(this)));
}
// This is unused but needs to be included to fulfill ISNWFundingCycleDataSource.
function redeemParams(SNWRedeemParamsData calldata _data)
external
pure
override
returns (
uint256 reclaimAmount,
string memory memo,
ISNWRedemptionDelegate delegate
)
{
// Return the default values.
return (_data.reclaimAmount.value, _data.memo, ISNWRedemptionDelegate(address(0)));
}
constructor(ISNWDirectory _directory, uint256 _projectId, SNWTokenAmount _contributionThreshold, string calldata _name, string calldata _symbol) ERC721(_name, _symbol) {
directory = _directory;
projectId = _projectId;
},
// Called once the payment has gone through if the project's current funding cycle is using a data source that returns this delegate.
function didPay(SNWDidPayData calldata _data) external override {
// Make sure the caller is a terminal of the project, and the call is being made on behalf of an interaction with the correct project.
if (
!directory.isTerminalOf(projectId, ISNWPaymentTerminal(msg.sender)) ||
_data.projectId != projectId
) revert INVALID_PAYMENT_EVENT();
// Make the contribution is being made in the expected token.
if (_data.amount.token != contributionThreshold.token) return;
// Make sure the values use the same number of decimals.
if (_data.amount.decimals < contributionThreshold.decimals) return;
// Make sure the threshold is met.
if (_data.amount.value < contributionThreshold.value) return;
uint256 _tokenId = ++supply;
_mint(_data.beneficiary, _tokenId);
}
}