-
Notifications
You must be signed in to change notification settings - Fork 7
/
FlowEVMBridgeHandlerInterfaces.cdc
207 lines (195 loc) · 9.07 KB
/
FlowEVMBridgeHandlerInterfaces.cdc
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
import "FungibleToken"
import "NonFungibleToken"
import "EVM"
/// FlowEVMBridgeHandlerInterfaces
///
/// This contract defines the interfaces for the FlowEVM Bridge Handlers. These Handlers are intended to encapsulate
/// the logic for bridging edge case assets between Cadence and EVM and require configuration by the bridge account to
/// enable. Contracts implementing these resources should be deployed to the bridge account so that privileged methods,
/// particularly those related to fulfilling bridge requests remain in the closed loop of bridge contract logic and
/// defined assets in the custody of the bridge account.
///
access(all) contract FlowEVMBridgeHandlerInterfaces {
/******************
Entitlements
*******************/
/// Entitlement related to administrative setters
access(all) entitlement Admin
/// Entitlement related to minting handled assets
access(all) entitlement Mint
/*************
Events
**************/
/// Event emitted when a handler is enabled between a Cadence type and an EVM address
access(all) event HandlerEnabled(
handlerType: String,
handlerUUID: UInt64,
targetType: String,
targetEVMAddress: String
)
/// Event emitted when a handler is disabled, pausing bridging between VMs
access(all) event HandlerDisabled(
handlerType: String,
handlerUUID: UInt64,
targetType: String?,
targetEVMAddress: String?
)
/// Emitted when a minter resource is set in a handler
access(all) event MinterSet(handlerType: String,
handlerUUID: UInt64,
targetType: String?,
targetEVMAddress: String?,
minterType: String,
minterUUID: UInt64
)
/****************
Constructs
*****************/
/// Non-privileged interface for querying handler information
///
access(all) resource interface HandlerInfo {
/// Returns whether the Handler is enabled
access(all) view fun isEnabled(): Bool
/// Returns the Cadence type handled by the Handler, nil if not set
access(all) view fun getTargetType(): Type?
/// Returns the EVM address handled by the Handler, nil if not set
access(all) view fun getTargetEVMAddress(): EVM.EVMAddress?
/// Returns the Type of the expected minter if the handler utilizes one
access(all) view fun getExpectedMinterType(): Type?
}
/// Administrative interface for Handler configuration
///
access(all) resource interface HandlerAdmin : HandlerInfo {
/// Sets the target Cadence Type handled by this resource. Once the targe type is set - whether by this method
/// or on initialization - this setter will fail.
access(Admin) fun setTargetType(_ type: Type) {
pre {
self.getTargetType() == nil: "Target Type has already been set"
}
post {
self.getTargetType()! == type: "Problem setting target type"
}
}
/// Sets the target EVM address handled by this resource
access(Admin) fun setTargetEVMAddress(_ address: EVM.EVMAddress) {
pre {
self.getTargetEVMAddress() == nil: "Target EVM address has already been set"
}
post {
self.getTargetEVMAddress()!.equals(address!): "Problem setting target EVM address"
}
}
access(Admin) fun setMinter(_ minter: @{FlowEVMBridgeHandlerInterfaces.TokenMinter}) {
pre {
self.getExpectedMinterType() == minter.getType(): "Minter is not of the expected type"
minter.getMintedType() == self.getTargetType(): "Minter does not mint the target type"
emit MinterSet(
handlerType: self.getType().identifier,
handlerUUID: self.uuid,
targetType: self.getTargetType()?.identifier,
targetEVMAddress: self.getTargetEVMAddress()?.toString(),
minterType: minter.getType().identifier,
minterUUID: minter.uuid
)
}
}
/// Enables the Handler to fulfill bridge requests for the configured targets. If implementers utilize a minter,
/// they should additionally ensure the minter is set before enabling.
access(Admin) fun enableBridging() {
pre {
self.getTargetType() != nil && self.getTargetEVMAddress() != nil:
"Cannot enable before setting bridge target Type and EVM Address"
!self.isEnabled(): "Handler has already been enabled"
}
post {
self.isEnabled(): "Problem enabling Handler"
emit HandlerEnabled(
handlerType: self.getType().identifier,
handlerUUID: self.uuid,
targetType: self.getTargetType()!.identifier,
targetEVMAddress: self.getTargetEVMAddress()!.toString()
)
}
}
/// Disables the Handler from fulfilling bridge requests.
access(Admin) fun disableBridging() {
pre {
self.isEnabled():
"Cannot disable: ".concat(self.getType().identifier).concat(" is already disabled")
}
post {
!self.isEnabled():
"Problem disabling ".concat(self.getType().identifier)
emit HandlerDisabled(
handlerType: self.getType().identifier,
handlerUUID: self.uuid,
targetType: self.getTargetType()?.identifier,
targetEVMAddress: self.getTargetEVMAddress()?.toString()
)
}
}
}
/// Minter interface for configurations requiring the minting of Cadence fungible tokens
///
access(all) resource interface TokenMinter {
/// Returns the Cadence type minted by this resource
access(all) view fun getMintedType(): Type
/// Mints the specified amount of tokens
access(Mint) fun mint(amount: UFix64): @{FungibleToken.Vault} {
pre {
amount > 0.0: "Attempting to mint 0.0 - Amount minted must be greater than 0"
}
post {
result.getType() == self.getMintedType():
"TokenMinter ".concat(self.getType().identifier).concat(" with uuid ").concat(self.uuid.toString())
.concat(" expected to mint ").concat(self.getMintedType().identifier)
.concat(" but returned ").concat(result.getType().identifier)
result.balance == amount:
"Minted amount ".concat(result.balance.toString())
.concat(" does not match requested amount ").concat(amount.toString())
}
}
}
/// Handler interface for bridging FungibleToken assets. Implementations should be stored within the bridge account
/// and called be the bridge contract for bridging operations on the Handler's target Type and EVM contract.
///
access(all) resource interface TokenHandler : HandlerAdmin {
/// Fulfills a request to bridge tokens from the Cadence side to the EVM side
access(account) fun fulfillTokensToEVM(
tokens: @{FungibleToken.Vault},
to: EVM.EVMAddress
) {
pre {
self.isEnabled():
"TokenHandler ".concat(self.getType().identifier).concat(" with uuid ")
.concat(self.uuid.toString()).concat(" is not yet enabled")
tokens.getType() == self.getTargetType():
"TokenHandler ".concat(self.getType().identifier).concat(" with uuid ").concat(self.uuid.toString())
.concat(" expects ").concat(self.getTargetType()?.identifier ?? "nil")
.concat(" but received ").concat(tokens.getType().identifier)
tokens.balance > 0.0:
"Attempting to bridge 0.0 tokens - zero amounts are unsupported"
}
}
/// Fulfills a request to bridge tokens from the EVM side to the Cadence side
access(account) fun fulfillTokensFromEVM(
owner: EVM.EVMAddress,
type: Type,
amount: UInt256,
protectedTransferCall: fun (): EVM.Result
): @{FungibleToken.Vault} {
pre {
self.isEnabled():
"TokenHandler ".concat(self.getType().identifier).concat(" with uuid ")
.concat(self.uuid.toString()).concat(" is not yet enabled")
amount > UInt256(0): "Attempting to bridge 0 tokens from EVM - zero amounts are unsupported"
}
post {
result.getType() == self.getTargetType():
"TokenHandler ".concat(self.getType().identifier).concat(" with uuid ").concat(self.uuid.toString())
.concat(" expected to return ").concat(self.getTargetType()?.identifier ?? "nil")
.concat(" but returned ").concat(result.getType().identifier)
}
}
}
}