-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIPFSFunctionsConsumer.sol
More file actions
133 lines (114 loc) · 4.72 KB
/
IPFSFunctionsConsumer.sol
File metadata and controls
133 lines (114 loc) · 4.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.30;
import { FunctionsClient } from "@chainlink/src/v0.8/functions/v1_0_0/FunctionsClient.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { FunctionsRequest } from "@chainlink/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol";
import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import { GiftNFT } from "src/GiftNFT.sol";
contract IPFSFunctionsConsumer is FunctionsClient, Ownable, AccessControl, ReentrancyGuard {
using FunctionsRequest for FunctionsRequest.Request;
error IPFSFunctionsConsumer__UnexpectedRequestID(bytes32 requestId);
error IPFSFunctionsConsumer__GiftNFTContractCannotBeZero();
struct FunctionRequest {
uint256 nftId;
string publicContentHash; // The public content hash of the character
bytes error;
}
bytes32 public constant SEND_REQUEST_ROLE = keccak256("SEND_REQUEST_ROLE");
event GiftContentHashUpdated(bytes32 indexed requestId, uint256 indexed nftId, string publicContentHash);
event GiftNFTContractSet(address giftNFTContract);
event EncryptedSecretsSet();
event GasLimitUpdated(uint32 gasLimit);
event ErrorUpdatingHash(bytes32 indexed requestId, uint256 indexed nftId, bytes error);
event SourceUdated(string source);
uint32 public gasLimit;
bytes32 public immutable donID;
uint64 public subscriptionId;
bytes public encryptedSecretsUrls;
string public source;
GiftNFT internal giftNFTContract;
mapping(bytes32 requestId => FunctionRequest request) public requests;
constructor(
uint64 _subscriptionId,
address _router,
bytes32 _donId,
uint32 _gasLimit,
bytes memory _encryptedSecretsUrls
)
FunctionsClient(_router)
Ownable(msg.sender)
{
subscriptionId = _subscriptionId;
donID = _donId;
gasLimit = _gasLimit;
encryptedSecretsUrls = _encryptedSecretsUrls;
}
function updateSource(string calldata _source) external onlyOwner {
source = _source;
emit SourceUdated(_source);
}
function updateGasLimit(uint32 _gasLimit) external onlyOwner {
gasLimit = _gasLimit;
emit GasLimitUpdated(_gasLimit);
}
function grantSendRequestRole(address account) external onlyOwner {
_grantRole(SEND_REQUEST_ROLE, account);
}
function setGiftNFTContract(address _giftNFTContract) external onlyOwner {
if (_giftNFTContract == address(0)) {
revert IPFSFunctionsConsumer__GiftNFTContractCannotBeZero();
}
giftNFTContract = GiftNFT(_giftNFTContract);
emit GiftNFTContractSet(_giftNFTContract);
}
function updateEncryptedSecrets(bytes calldata _encryptedSecretsUrls) external onlyOwner {
encryptedSecretsUrls = _encryptedSecretsUrls;
emit EncryptedSecretsSet();
}
/**
* @notice Sends request to Chainlink function
* @param nftId NFT including the content hash
* @param args args including private CID, sender and receiver address
*/
function sendRequest(
uint256 nftId,
string[] calldata args
)
external
onlyRole(SEND_REQUEST_ROLE)
nonReentrant
returns (bytes32 requestId)
{
FunctionsRequest.Request memory req;
req.initializeRequestForInlineJavaScript(source);
if (encryptedSecretsUrls.length > 0) {
req.addSecretsReference(encryptedSecretsUrls);
}
if (args.length > 0) req.setArgs(args);
requestId = _sendRequest(req.encodeCBOR(), subscriptionId, gasLimit, donID);
requests[requestId] = FunctionRequest({ nftId: nftId, publicContentHash: hex"", error: hex"" });
return requestId;
}
/**
* @notice Function called when the Chainlink Function completes
* @param requestId Original request id
* @param response Response including public CID
* @param err Error, if any
*/
function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override {
FunctionRequest storage request = requests[requestId];
uint256 nftId = request.nftId;
if (nftId == 0) {
revert IPFSFunctionsConsumer__UnexpectedRequestID(requestId);
}
if (err.length > 0) {
request.error = err;
emit ErrorUpdatingHash(requestId, nftId, err);
} else {
request.publicContentHash = string(response);
giftNFTContract.updateContentHash(nftId, string(response));
emit GiftContentHashUpdated(requestId, nftId, string(response));
}
}
}