-
Notifications
You must be signed in to change notification settings - Fork 115
Expand file tree
/
Copy pathSelfAutomatingContract.sol
More file actions
165 lines (147 loc) · 5.47 KB
/
Copy pathSelfAutomatingContract.sol
File metadata and controls
165 lines (147 loc) · 5.47 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// SPDX-License-Identifier: MIT
pragma solidity 0.8.6;
// UpkeepIDConsumerExample.sol imports functions from both ./KeeperRegistryInterface.sol and
// ./interfaces/LinkTokenInterface.sol
import {KeeperRegistryInterface, State, Config} from "@chainlink/contracts/src/v0.8/interfaces/KeeperRegistryInterface.sol";
import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";
// Counter is a simple contract that keeps track of the number of times it has been called.
import "@openzeppelin/contracts/utils/Counters.sol";
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
interface KeeperRegistrarInterface {
function register(
string memory name,
bytes calldata encryptedEmail,
address upkeepContract,
uint32 gasLimit,
address adminAddress,
bytes calldata checkData,
uint96 amount,
uint8 source,
address sender
) external;
}
contract SelfAutomatingCounters {
// Setup the counters
using Counters for Counters.Counter;
// Store the counter id
Counters.Counter private _counterIdCounter;
// Map the value to the counter
mapping(uint256 => uint256) public counterToValue;
// Map the last updated time to the counter
mapping(uint256 => uint256) public counterToLastTimeStamp;
// Map the counter to the upkeep
mapping(uint256 => uint256) public counterToUpkeepID;
// Set upkeep interval to 60 seconds
uint256 interval = 60;
// Setup keeper registry information
LinkTokenInterface public immutable i_link;
address public immutable registrar;
KeeperRegistryInterface public immutable i_registry;
bytes4 registerSig = KeeperRegistrarInterface.register.selector;
// Pass in the toke nand registry info
constructor(
LinkTokenInterface _link,
address _registrar,
KeeperRegistryInterface _registry
) {
// 0x326C977E6efc84E512bB9C30f76E30c160eD06FB -- Goerli
i_link = _link;
// 0x9806cf6fBc89aBF286e8140C42174B94836e36F2 -- Goerli
registrar = _registrar;
// 0x02777053d6764996e594c3E88AF1D58D5363a2e6 -- Goerli
i_registry = _registry;
}
// Create a new counter
function createNewCounter() public returns (uint256) {
// Grab current counter id
uint256 counterID = _counterIdCounter.current();
// Increment counter id
_counterIdCounter.increment();
// Set the value to 0
counterToValue[counterID] = 0;
// Set the last updated time to now
counterToLastTimeStamp[counterID] = block.timestamp;
// Return the counter id
return counterID;
}
// Register new keeper
function registerAndPredictID(
string memory name,
uint32 gasLimit,
uint96 amount
) public {
// Create a new counter
uint256 counterID = createNewCounter();
(State memory state, Config memory _c, address[] memory _k) = i_registry
.getState();
uint256 oldNonce = state.nonce;
// Pass in the counter id as the check data
bytes memory checkData = abi.encodePacked(counterID);
// Encode the data to send to the registrar
bytes memory payload = abi.encode(
name,
"0x",
address(this),
// 999999
gasLimit,
address(msg.sender),
checkData,
// 5000000000000000000
amount,
0,
address(this)
);
// Transfer LINK and call the registrar
i_link.transferAndCall(
registrar,
amount,
bytes.concat(registerSig, payload)
);
(state, _c, _k) = i_registry.getState();
uint256 newNonce = state.nonce;
if (newNonce == oldNonce + 1) {
uint256 upkeepID = uint256(
keccak256(
abi.encodePacked(
blockhash(block.number - 1),
address(i_registry),
uint32(oldNonce)
)
)
);
// Set the upkeep id for the counter id
counterToUpkeepID[counterID] = upkeepID;
} else {
revert("auto-approve disabled");
}
}
// checkUpkeep expects the counter id as the check data this will run for each new counter
function checkUpkeep(bytes calldata checkData)
external
view
returns (bool upkeepNeeded, bytes memory performData)
{
// Decode the check data
uint256 counterID = abi.decode(checkData, (uint256));
// If the interval has passed then return true
upkeepNeeded =
(block.timestamp - counterToLastTimeStamp[counterID]) > interval;
// Pass checkData through
performData = checkData;
}
function performUpkeep(bytes calldata performData) external {
// Decode the check data
uint256 counterID = abi.decode(performData, (uint256));
//We highly recommend revalidating the upkeep in the performUpkeep function
if ((block.timestamp - counterToLastTimeStamp[counterID]) > interval) {
// Update the last updated time
counterToLastTimeStamp[counterID] = block.timestamp;
// Increment the value
counterToValue[counterID] = counterToValue[counterID] + 1;
}
}
}