-
Notifications
You must be signed in to change notification settings - Fork 0
/
BehaviorGraph.sol
126 lines (95 loc) · 3.79 KB
/
BehaviorGraph.sol
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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import '@openzeppelin/contracts/token/ERC721/ERC721.sol';
import '@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/utils/Counters.sol';
enum NodeType {
Action,
DataSource
}
struct TokenGateRule {
bool active;
address tokenContract;
}
struct Node {
string id;
NodeType nodeType;
TokenGateRule tokenGateRule;
}
contract BehaviorGraph is ERC721, ERC721URIStorage, Ownable {
using Counters for Counters.Counter;
mapping(uint256 => mapping(string => Node)) private _tokenNodes;
mapping(uint256 => mapping(string => uint256)) private _tokenNodeEmitCount;
Counters.Counter private _nodeCounter;
Counters.Counter private _tokenIdCounter;
event SafeMint(uint256 tokenId, address to, string uri, Node[] nodes);
error InvalidActionId(string nodeId);
error MissingTokens(string nodeId, address tokenAddress);
event ActionExecuted(address executor, uint256 tokenId, string actionId, uint256 count);
constructor() ERC721("MyToken", "MTK") {}
function _baseURI() internal pure override returns (string memory) {
return "ipfs://";
}
function safeMint(string memory sceneUri, Node[] calldata _nodes) public returns(uint256) {
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
address to = msg.sender;
_safeMint(to, tokenId);
_setTokenURI(tokenId, sceneUri);
_createNodes(tokenId, _nodes);
emit SafeMint(tokenId, to, sceneUri, _nodes);
return tokenId;
}
// The following functions are overrides required by Solidity.
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function _createNodes(uint256 tokenId, Node[] calldata _nodes) private {
for(uint256 i = 0; i < _nodes.length; i++) {
Node calldata node = _nodes[i];
_tokenNodes[tokenId][node.id] = node;
}
}
function getNode(uint256 tokenId, string memory _nodeId) public view returns(Node memory) {
return _tokenNodes[tokenId][_nodeId];
}
function executeAction(uint256 tokenId, string calldata _nodeId) public {
Node memory node = getNode(tokenId, _nodeId);
_assertCanExecuteAction(node);
uint256 actionCount = ++_tokenNodeEmitCount[tokenId][_nodeId];
emit ActionExecuted(msg.sender, tokenId, _nodeId, actionCount);
}
function getActionCount(uint256 tokenId, string calldata _nodeId) public view returns(uint256) {
// uint256 numberElems = _nodeIds.length;
return _tokenNodeEmitCount[tokenId][_nodeId];
}
function getActionCounts(uint256 tokenId, string[] calldata _nodeIds) public view returns(uint256[] memory) {
// uint256 numberElems = _nodeIds.length;
uint256[] memory result = new uint256[](_nodeIds.length);
for(uint256 i = 0; i < _nodeIds.length; i++) {
string memory _nodeId = _nodeIds[i];
uint256 count = _tokenNodeEmitCount[tokenId][_nodeId];
result[i] = count;
}
return result;
}
function _assertCanExecuteAction(Node memory node) private view {
if (!node.tokenGateRule.active) {
return;
}
ERC721 erc721Contract = ERC721(node.tokenGateRule.tokenContract);
uint256 balance = erc721Contract.balanceOf(msg.sender);
if (balance <= 0) {
revert MissingTokens(node.id, msg.sender);
}
}
}