As a first time reader, it seemed a little overwhelming when going through tutorial 3 āFungible Tokensā. Thereās a ton of public interfaces, but are they indispensable? Simply using the Vault type in the type casts while interacting with storage or capabilities seems sufficient.
Hereās the base contract I composed, without any interfaces.
As far as I can tell, every example/idea that flows in the tutorial when it comes to fungible tokens still holds. I would really appreciate comments if Iām thinking about this wrong, thanks!
Hi @morgan, Iām only learning about Cadende/flow for a few weeks too, so what I say might not be completely correct, but let me just give me 2 cents here.
Definitely a valid question of yours.
I believe that the contract that you wrote would perfectly work.
However, I believe the interfaces are incredibly important for security reasons.
Imagine that your contract would be deployed.
And 0x02 has a vault with this WildeToken and wants to make a public capability so that people can deposit more WildeTokens in his vault. (of course, he does not want other people to be able to withdraw from his vault) In that case, he would use the following operation in a transaction (with acct is the authAccount of 0x02):
Now, this second code example is extremely dangerous. By not restricting the access (with the interfaces), someone who āborrowsā that capability can perform all existing public actions on that vault of 0x02. He can even perform a Withdrawal and empty the vault.
In short: Capabilities are used to give access to certain resources, while interfaces are used for restricting the actions that can be performed on/with the resource. Thatās why I think you should always have both.
Although this security aspect might be a bit complicated for a tutorial, I do not think it is a good idea to remove it.
I hope I made myself clear. Please let me know if my explanation makes sense
Thatās awesome @jerre ! Thanks for the insight. I havenāt tested the contract in such a way and it seemed to perform exactly as the one in the tutorial.
I now believe that it would be best to start with a contract like the one I described and the showcase a transaction thatās able to withdraw funds without the ownerās consent and THEN introducing interfaces as a fix to a problem after the demonstration.
Initiated 0x02 by creating a new, empty vault and storing it
Steal the coins from 0x01 with the following transaction:
// Steal Tokens
import WildeToken from 0x01
transaction {
var myVaultRef: &WildeToken.Vault
prepare(acct: AuthAccount) {
self.myVaultRef = acct.borrow<&WildeToken.Vault>(from: /storage/MainVault)
?? panic("Could not borrow a reference to the owner's vault")
}
execute {
let victim = getAccount(0x01)
let victimRef = victim.getCapability(/public/MainReceiver)
.borrow<&WildeToken.Vault>()
?? panic("Could not borrow a reference to the receiver")
var coins <- victimRef.withdraw(amount: 100.0)
self.myVaultRef.deposit(from: <- coins)
log("Transfer succeeded!")
}
}
Iām with you! On an educational level, it would indeed be very interesting to have it explained in such way as the you put stress on the security breach.
On the other hand, I could also argue that you want all examples in the playground to be perfect and complete. People might end up copying the code from the playground without really understanding it, which can lead to less secure contracts (instead of more secure contracts)
Very cool stuff @jerre ! One thing that wasnāt mentioned, although I guess itās implied, which account signed the transaction (I understand itās 0x02, but could well be any account)?
@morgan Thanks man!
In this case it was 0x02. But it could indeed be any account that is able to receive the tokens (= has a WildeToken vault in storage)
And as anyone can create such a vault, anyone can steal.
Note that 0x01 is also able to steal them back from 0x02.
Haha indeed, in such a world, possessions wouldnāt mean anything so actually, there is no point in stealing
In the example above, it is also possible to stop the āstealingā. If 0x02 would not create any public capability, nobody (except for himself) would be able to reach his vault or perform any actions with it.
But that would also mean that nobody can send him WildeTokens