-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOperator.sol
154 lines (135 loc) · 4.41 KB
/
Operator.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
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
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity ^0.8.0;
import { IFismoOperate } from "./interfaces/IFismoOperate.sol";
import { FismoConstants } from "./domain/FismoConstants.sol";
import { FismoTypes } from "./domain/FismoTypes.sol";
/**
* @title Operator
*
* This is a basic, cloneable, Fismo operator contract.
* Anyone can invoke actions.
*
* @author Cliff Hall <[email protected]> (https://twitter.com/seaofarrows)
*/
contract Operator is FismoConstants {
/// Emitted when a user clones the Operator contract
event OperatorCloned(
address indexed clonedBy,
address indexed clone,
address indexed fismo
);
/// Emitted when a user invokes an action
event ActionInvoked(
address indexed invokedBy,
bytes4 indexed machineId,
bytes4 indexed actionId,
FismoTypes.ActionResponse response
);
/// The Fismo instance to invoke actions upon
IFismoOperate private fismo;
/// Is this the original Operator instance or a clone?
bool private isOperator;
/**
* @notice Constructor
*
* Note:
* - Only executed in an actual contract deployment
* - Clones have their init() method called to do same
*
* @param _fismo - address of the Fismo instance
*/
constructor(address _fismo) payable {
initialize(_fismo, true);
}
/**
* @notice Initialize a cloned Operator instance.
*
* Reverts if:
* - Current Fismo address is not the zero address
*
* Note:
* - Must be external to be called from the Operator factory.
* - Sets `isOperator` to false, so that `cloneOperator` will revert.
*
* @param _fismo - address of the Fismo instance
*/
function init(address _fismo)
external
{
require(address(fismo) == address(0), ALREADY_INITIALIZED);
initialize(_fismo, false);
}
/**
* @notice Initialize Operator contract
*
* @param _fismo - address of the Fismo instance
* @param _isOperator - are we initializing the a just-deployed instance?
*/
function initialize(address _fismo, bool _isOperator) internal {
fismo = IFismoOperate(_fismo);
isOperator = _isOperator;
}
/**
* Invoke a Fismo action
*
* Note:
* - In this basic implementation anyone can invoke actions
*
* @param _machineId - the id of the target machine
* @param _actionId - the id of the action to invoke
*
* @return response - the response message. see {FismoTypes.ActionResponse}
*/
function invokeAction(bytes4 _machineId, bytes4 _actionId)
external
returns(FismoTypes.ActionResponse memory response) {
response = fismo.invokeAction(msg.sender, _machineId, _actionId);
// Notify watchers of state change
emit ActionInvoked(msg.sender, _machineId, _actionId, response);
}
/**
* @notice Deploys and returns the address of an Operator clone.
*
* Emits:
* - OperatorCloned
*
* @param _fismo - the address of the Fismo instance to operate
* @return instance - the address of the Operator clone instance
*/
function cloneOperator(address _fismo)
external
returns (address instance)
{
// Make sure this isn't a clone
require(isOperator, MULTIPLICITY);
// Clone the contract
instance = clone();
// Initialize the clone
Operator(instance).init(_fismo);
// Notify watchers of state change
emit OperatorCloned(msg.sender, instance, _fismo);
}
/**
* @dev Deploys and returns the address of an Operator clone
*
* Note:
* - This function uses the create opcode, which should never revert.
*
* @return instance - the address of the Fismo clone
*/
function clone()
internal
returns (address instance) {
// Clone this contract
address implementation = address(this);
// solhint-disable-next-line no-inline-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create(0, ptr, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
}