-
Notifications
You must be signed in to change notification settings - Fork 0
/
moonbeam_evm_verifier.sol
241 lines (195 loc) Β· 7.88 KB
/
moonbeam_evm_verifier.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "./interfaces/MoonbeamXcmTransactor.sol";
import "./interfaces/IERC721.sol";
import "./utils/ScaleCodec.sol";
contract Verifier {
// Collection::Contract20([u8; 20])
bytes1 internal constant COLLECTION_CONTRACT_20 = 0x01;
// Nft::U256Id(U256)
bytes1 internal constant NFT_U256_ID = 0x01;
// NftOrigins Pallet in Tinkernet
uint8 public constant PALLET_INDEX = 74;
// dispatch_registered_call_as_nft call in NftOrigins Pallet
uint8 public constant CALL_INDEX = 1;
// Index for VoteInMultisig registered call
uint8 public constant VOTE_CALL_INDEX = 0;
// Index for WithdrawVoteInMultisig registered call
uint8 public constant WITHDRAW_VOTE_CALL_INDEX = 1;
// Index for OperateMultisig registered call
uint8 public constant OPERATE_CALL_INDEX = 2;
address public owner;
XcmTransactorV3.Multilocation internal xcmTransactorDestination;
XcmTransactorV3.Multilocation internal xcmTransactorFeeAsset;
constructor() {
owner = msg.sender;
bytes[] memory destInterior = new bytes[](1);
destInterior[0] = bytes.concat(hex"00", bytes4(uint32(2125)));
xcmTransactorDestination = XcmTransactorV3.Multilocation({
parents: 1,
interior: destInterior
});
bytes[] memory assetInterior = new bytes[](2);
assetInterior[0] = bytes.concat(hex"00", bytes4(uint32(2125)));
assetInterior[1] = bytes.concat(hex"05", abi.encodePacked(uint128(0)));
xcmTransactorFeeAsset = XcmTransactorV3.Multilocation({
parents: 1,
interior: assetInterior
});
}
enum Operation {
Vote,
WithdrawVote,
Operate
}
enum FeeAsset {
TNKR,
KSM
}
struct FeeInfo {
XcmTransactorV3.Weight transactRequiredWeightAtMost;
XcmTransactorV3.Weight overallWeight;
uint256 feeAmount;
}
mapping(Operation => FeeInfo) public operationToFeeInfo;
function setOperationToFeeInfo(
Operation _operation,
uint64 _transactRequiredWeightAtMostRefTime,
uint64 _transactRequiredWeightAtMostProofSize,
uint64 _overallWeightRefTime,
uint64 _overallWeightProofSize,
uint256 _feeAmount
) external {
require(msg.sender == owner);
operationToFeeInfo[_operation] = FeeInfo(
XcmTransactorV3.Weight(_transactRequiredWeightAtMostRefTime, _transactRequiredWeightAtMostProofSize),
XcmTransactorV3.Weight(_overallWeightRefTime, _overallWeightProofSize),
_feeAmount
);
}
function vote_in_multisig(address _contract, uint256 _nft, uint32 core_id, bytes32 proposal, bool aye) external {
// Verify if caller owns NFT
// address caller = msg.sender;
// require(IERC721(_contract).ownerOf(_nft) == caller, "Caller is not the owner of the NFT provided");
// Send XCM
bytes memory call_data = build_vote_call(_contract, _nft, core_id, proposal, aye);
FeeInfo memory fee_info = operationToFeeInfo[Operation.Vote];
XcmTransactorV3(XCM_TRANSACTOR_V3_ADDRESS).transactThroughSignedMultilocation(
// Destination MultiLocation
xcmTransactorDestination,
// Fee MultiLocation
xcmTransactorFeeAsset,
// Max weight
fee_info.transactRequiredWeightAtMost,
// Call
call_data,
// Fee amount
fee_info.feeAmount,
// Overall weight
fee_info.overallWeight,
// Refund
true
);
}
function withdraw_vote_in_multisig(address _contract, uint256 _nft, uint32 core_id, bytes32 proposal) external {
// Verify if caller owns NFT
// address caller = msg.sender;
// require(IERC721(_contract).ownerOf(_nft) == caller, "Caller is not the owner of the NFT provided");
// Send XCM
bytes memory call_data = build_withdraw_vote_call(_contract, _nft, core_id, proposal);
FeeInfo memory fee_info = operationToFeeInfo[Operation.WithdrawVote];
XcmTransactorV3(XCM_TRANSACTOR_V3_ADDRESS).transactThroughSignedMultilocation(
// Destination MultiLocation
xcmTransactorDestination,
// Fee MultiLocation
xcmTransactorFeeAsset,
// Max weight
fee_info.transactRequiredWeightAtMost,
// Call
call_data,
// Fee amount
fee_info.feeAmount,
// Overall weight
fee_info.overallWeight,
// Refund
true
);
}
function operate_multisig(address _contract, uint256 _nft, uint32 core_id, FeeAsset fee_asset, bytes memory proposed_call) external {
// Verify if caller owns NFT
// address caller = msg.sender;
// require(IERC721(_contract).ownerOf(_nft) == caller, "Caller is not the owner of the NFT provided");
// Send XCM
bytes memory call_data = build_operate_multisig_call(_contract, _nft, core_id, fee_asset, proposed_call);
FeeInfo memory fee_info = operationToFeeInfo[Operation.Operate];
XcmTransactorV3(XCM_TRANSACTOR_V3_ADDRESS).transactThroughSignedMultilocation(
// Destination MultiLocation
xcmTransactorDestination,
// Fee MultiLocation
xcmTransactorFeeAsset,
// Max weight
fee_info.transactRequiredWeightAtMost,
// Call
call_data,
// Fee amount
fee_info.feeAmount,
// Overall weight
fee_info.overallWeight,
// Refund
true
);
}
function build_vote_call(address _contract, uint256 _nft, uint32 core_id, bytes32 proposal, bool aye) internal pure returns (bytes memory) {
bytes memory prefix = new bytes(2);
prefix[0] = bytes1(PALLET_INDEX);
prefix[1] = bytes1(CALL_INDEX);
uint8 vote = 0;
if (aye) vote = 1;
bytes memory vote_call = bytes.concat(
bytes1(uint8(VOTE_CALL_INDEX)),
ScaleCodec.encodeU32(core_id),
proposal,
bytes1(uint8(vote))
);
return bytes.concat(
prefix,
abi.encodePacked(COLLECTION_CONTRACT_20, _contract),
abi.encodePacked(NFT_U256_ID, ScaleCodec.encodeU256(_nft)),
vote_call
);
}
function build_withdraw_vote_call(address _contract, uint256 _nft, uint32 core_id, bytes32 proposal) internal pure returns (bytes memory) {
bytes memory prefix = new bytes(2);
prefix[0] = bytes1(PALLET_INDEX);
prefix[1] = bytes1(CALL_INDEX);
bytes memory withdraw_vote_call = bytes.concat(
bytes1(uint8(WITHDRAW_VOTE_CALL_INDEX)),
ScaleCodec.encodeU32(core_id),
proposal
);
return bytes.concat(
prefix,
abi.encodePacked(COLLECTION_CONTRACT_20, _contract),
abi.encodePacked(NFT_U256_ID, ScaleCodec.encodeU256(_nft)),
withdraw_vote_call
);
}
function build_operate_multisig_call(address _contract, uint256 _nft, uint32 core_id, FeeAsset fee_asset, bytes memory proposed_call) internal pure returns (bytes memory) {
bytes memory prefix = new bytes(2);
prefix[0] = bytes1(PALLET_INDEX);
prefix[1] = bytes1(CALL_INDEX);
bytes memory operate_multisig_call = bytes.concat(
bytes1(uint8(OPERATE_CALL_INDEX)),
ScaleCodec.encodeU32(core_id),
bytes1(uint8(0)),
bytes1(uint8(fee_asset)),
proposed_call
);
return bytes.concat(
prefix,
abi.encodePacked(COLLECTION_CONTRACT_20, _contract),
abi.encodePacked(NFT_U256_ID, ScaleCodec.encodeU256(_nft)),
operate_multisig_call
);
}
}