Skip to content

Commit 04db208

Browse files
committed
add descriptive error messages to contracts
1 parent 1bbb412 commit 04db208

11 files changed

+123
-1109
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ node_modules/*
33
.env
44
coverage.lcov
55
coverage.json
6+
*.pkey

contracts/FungibleToken.cdc

+60-11
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ access(all) contract interface FungibleToken: ViewResolver {
117117
post {
118118
// `result` refers to the return value
119119
result.balance == amount:
120-
"Withdrawal amount must be the same as the balance of the withdrawn Vault"
120+
"FungibleToken.Provider.withdraw: Cannot withdraw tokens!"
121+
.concat("The balance of the withdrawn tokens (").concat(result.balance.toString())
122+
.concat(") is not equal to the amount requested to be withdrawn (")
123+
.concat(amount.toString()).concat(")")
121124
}
122125
}
123126
}
@@ -178,7 +181,9 @@ access(all) contract interface FungibleToken: ViewResolver {
178181
emit Burned(type: self.getType().identifier, amount: self.balance, fromUUID: self.uuid)
179182
}
180183
post {
181-
self.balance == 0.0: "The balance must be set to zero during the burnCallback method so that it cannot be spammed"
184+
self.balance == 0.0:
185+
"FungibleToken.Vault.burnCallback: Cannot burn this Vault with Burner.burn()."
186+
.concat("The balance must be set to zero during the burnCallback method so that it cannot be spammed")
182187
}
183188
self.balance = 0.0
184189
}
@@ -211,15 +216,29 @@ access(all) contract interface FungibleToken: ViewResolver {
211216
access(Withdraw) fun withdraw(amount: UFix64): @{Vault} {
212217
pre {
213218
self.balance >= amount:
214-
"Amount withdrawn must be less than or equal than the balance of the Vault"
219+
"FungibleToken.Vault.withdraw: Cannot withdraw tokens! "
220+
.concat("The amount requested to be withdrawn (").concat(amount.toString())
221+
.concat(") is greater than the balance of the Vault (")
222+
.concat(self.balance.toString()).concat(").")
215223
}
216224
post {
217-
result.getType() == self.getType(): "Must return the same vault type as self"
225+
result.getType() == self.getType():
226+
"FungibleToken.Vault.withdraw: Cannot withdraw tokens!"
227+
.concat("The withdraw method tried to return an incompatible Vault type <")
228+
.concat(result.getType().identifier).concat(">. ")
229+
.concat("It must return a Vault with the same type as self (")
230+
.concat(self.getType().identifier).concat(">.")
231+
218232
// use the special function `before` to get the value of the `balance` field
219233
// at the beginning of the function execution
220234
//
221235
self.balance == before(self.balance) - amount:
222-
"New Vault balance must be the difference of the previous balance and the withdrawn Vault balance"
236+
"FungibleToken.Vault.withdraw: Cannot withdraw tokens!"
237+
.concat("The sender's balance after the withdrawal (")
238+
.concat(self.balance.toString())
239+
.concat(") must be the difference of the previous balance (").concat(before(self.balance.toString()))
240+
.concat(") and the amount withdrawn (").concat(amount.toString())
241+
223242
emit Withdrawn(
224243
type: result.getType().identifier,
225244
amount: amount,
@@ -238,7 +257,13 @@ access(all) contract interface FungibleToken: ViewResolver {
238257
// as the vault that is accepting the deposit
239258
pre {
240259
from.isInstance(self.getType()):
241-
"Cannot deposit an incompatible token type"
260+
"FungibleToken.Vault.deposit: Cannot deposit tokens!"
261+
.concat("The type of the deposited tokens <")
262+
.concat(from.getType().identifier)
263+
.concat("> has to be the same type as the Vault being deposited into <")
264+
.concat(self.getType().identifier)
265+
.concat(">. Check that you are withdrawing and depositing to the correct paths in the sender and receiver accounts")
266+
.concat("and that those paths hold the same Vault types.")
242267
}
243268
post {
244269
emit Deposited(
@@ -250,7 +275,11 @@ access(all) contract interface FungibleToken: ViewResolver {
250275
balanceAfter: self.balance
251276
)
252277
self.balance == before(self.balance) + before(from.balance):
253-
"New Vault balance must be the sum of the previous balance and the deposited Vault"
278+
"FungibleToken.Vault.deposit: Cannot deposit tokens!"
279+
.concat("The receiver's balance after the deposit (")
280+
.concat(self.balance.toString())
281+
.concat(") must be the sum of the previous balance (").concat(before(self.balance.toString()))
282+
.concat(") and the amount deposited (").concat(before(from.balance).toString())
254283
}
255284
}
256285

@@ -259,8 +288,18 @@ access(all) contract interface FungibleToken: ViewResolver {
259288
/// @return A Vault of the same type that has a balance of zero
260289
access(all) fun createEmptyVault(): @{Vault} {
261290
post {
262-
result.balance == 0.0: "The newly created Vault must have zero balance"
263-
result.getType() == self.getType(): "The newly created Vault must have the same type as the creating vault"
291+
result.balance == 0.0:
292+
"FungibleToken.Vault.createEmptyVault: Empty Vault creation failed!"
293+
.concat("The newly created Vault must have zero balance but it has a balance of ")
294+
.concat(result.balance.toString())
295+
296+
result.getType() == self.getType():
297+
"FungibleToken.Vault.createEmptyVault: Empty Vault creation failed!"
298+
.concat("The type of the new Vault <")
299+
.concat(result.getType().identifier)
300+
.concat("> has to be the same type as the Vault that created it <")
301+
.concat(self.getType().identifier)
302+
.concat(">.")
264303
}
265304
}
266305
}
@@ -270,8 +309,18 @@ access(all) contract interface FungibleToken: ViewResolver {
270309
/// @return A Vault of the requested type that has a balance of zero
271310
access(all) fun createEmptyVault(vaultType: Type): @{FungibleToken.Vault} {
272311
post {
273-
result.getType() == vaultType: "The returned vault does not match the desired type"
274-
result.balance == 0.0: "The newly created Vault must have zero balance"
312+
result.balance == 0.0:
313+
"FungibleToken.createEmptyVault: Empty Vault creation failed!"
314+
.concat("The newly created Vault must have zero balance but it has a balance of ")
315+
.concat(result.balance.toString())
316+
317+
result.getType() == vaultType:
318+
"FungibleToken.Vault.createEmptyVault: Empty Vault creation failed!"
319+
.concat("The type of the new Vault <")
320+
.concat(result.getType().identifier)
321+
.concat("> has to be the same as the type that was requested <")
322+
.concat(vaultType.identifier)
323+
.concat(">.")
275324
}
276325
}
277326
}

contracts/FungibleTokenMetadataViews.cdc

+8-2
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,14 @@ access(all) contract FungibleTokenMetadataViews {
142142
createEmptyVaultFunction: fun(): @{FungibleToken.Vault}
143143
) {
144144
pre {
145-
receiverLinkedType.isSubtype(of: Type<&{FungibleToken.Receiver}>()): "Receiver public type must include FungibleToken.Receiver."
146-
metadataLinkedType.isSubtype(of: Type<&{FungibleToken.Vault}>()): "Metadata linked type must be a fungible token vault"
145+
receiverLinkedType.isSubtype(of: Type<&{FungibleToken.Receiver}>()):
146+
"Receiver public type <".concat(receiverLinkedType.identifier)
147+
.concat("> must be a subtype of <").concat(Type<&{FungibleToken.Receiver}>().identifier)
148+
.concat(">.")
149+
metadataLinkedType.isSubtype(of: Type<&{FungibleToken.Vault}>()):
150+
"Metadata linked type <".concat(metadataLinkedType.identifier)
151+
.concat("> must be a subtype of <").concat(Type<&{FungibleToken.Vault}>().identifier)
152+
.concat(">.")
147153
}
148154
self.storagePath = storagePath
149155
self.receiverPath = receiverPath

contracts/FungibleTokenSwitchboard.cdc

+19-8
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ access(all) contract FungibleTokenSwitchboard {
6767
// Borrow a reference to the vault pointed to by the capability we
6868
// want to store inside the switchboard
6969
let vaultRef = capability.borrow()
70-
?? panic ("Cannot borrow reference to vault from capability")
70+
?? panic("FungibleTokenSwitchboard.Switchboard.addNewVault: Cannot borrow reference to vault from capability"
71+
.concat("Make sure that the capability path points to a Vault that has been properly initialized"))
72+
7173
// Check if there is a previous capability for this token, if not
7274
if (self.receiverCapabilities[vaultRef.getType()] == nil) {
7375
// use the vault reference type as key for storing the
@@ -78,9 +80,6 @@ access(all) contract FungibleTokenSwitchboard {
7880
emit VaultCapabilityAdded(type: vaultRef.getType(),
7981
switchboardOwner: self.owner?.address,
8082
capabilityOwner: capability.address)
81-
} else {
82-
// If there was already a capability for that token, panic
83-
panic("There is already a vault in the Switchboard for this token")
8483
}
8584
}
8685

@@ -135,7 +134,12 @@ access(all) contract FungibleTokenSwitchboard {
135134
access(Owner) fun addNewVaultWrapper(capability: Capability<&{FungibleToken.Receiver}>,
136135
type: Type) {
137136
// Check if the capability is working
138-
assert(capability.check(), message: "The passed capability is not valid")
137+
assert (
138+
capability.check(),
139+
message:
140+
"FungibleTokenSwitchboard.Switchboard.addNewVaultWrapper: Cannot borrow reference to a vault from the provided capability"
141+
.concat("Make sure that the capability path points to a Vault that has been properly initialized")
142+
)
139143
// Use the type parameter as key for the capability
140144
self.receiverCapabilities[type] = capability
141145
// emit the event that indicates that a new capability has been
@@ -192,7 +196,9 @@ access(all) contract FungibleTokenSwitchboard {
192196
// Borrow a reference to the vault pointed to by the capability we
193197
// want to remove from the switchboard
194198
let vaultRef = capability.borrow()
195-
?? panic ("Cannot borrow reference to vault from capability")
199+
?? panic ("FungibleTokenSwitchboard.Switchboard.addNewVaultWrapper: Cannot borrow reference to a vault from the provided capability"
200+
.concat("Make sure that the capability path points to a Vault that has been properly initialized"))
201+
196202
// Use the vault reference to find the capability to remove
197203
self.receiverCapabilities.remove(key: vaultRef.getType())
198204
// Emit the event that indicates that a new capability has been
@@ -212,11 +218,16 @@ access(all) contract FungibleTokenSwitchboard {
212218
access(all) fun deposit(from: @{FungibleToken.Vault}) {
213219
// Get the capability from the ones stored at the switchboard
214220
let depositedVaultCapability = self.receiverCapabilities[from.getType()]
215-
?? panic ("The deposited vault is not available on this switchboard")
221+
?? panic ("FungibleTokenSwitchboard.Switchboard.deposit: Cannot deposit Vault! "
222+
.concat("The deposited vault of type <").concat(from.getType().identifier)
223+
.concat("> is not available on this Fungible Token switchboard. ")
224+
.concat("The recipient needs to initialize their account and switchboard to hold and receive the deposited vault type."))
216225

217226
// Borrow the reference to the desired vault
218227
let vaultRef = depositedVaultCapability.borrow()
219-
?? panic ("Can not borrow a reference to the the vault")
228+
?? panic ("FungibleTokenSwitchboard.Switchboard.deposit: Cannot borrow reference to a vault"
229+
.concat("from the type of the deposited Vault <").concat(from.getType().identifier)
230+
.concat(">. Make sure that the capability path points to a Vault that has been properly initialized"))
220231

221232
vaultRef.deposit(from: <-from)
222233
}

0 commit comments

Comments
 (0)