免责声明:不要被标题和缩略图所惊吓。没有什么出错,我只是希望正在编写智能合约的人确保他们了解代币智能合约的这个非常重要的部分。
欢迎来到我的Cadence博客!我是Josh,是Dapper Labs的Flow团队的智能合约开发者,我今天在这里告诉大家所有代币Cadence智能合约的一个关键部分,每个人都需要注意,至少在代币的这部分功能被内置到语言中。
如果你是新来的,我建议你先阅读我关于开始使用Flow和Cadence的介绍性博文。
使用Cadence迈出第一步
每个Flow的新人都应该完成的资源总结,以适应在Cadence中编写智能合约。
joshuahannan.medium.com
什么是代币智能合约?
这里的 "代币 "一词可以指这两种类型的智能合约中的任何一种。
- 可兑换代币(FT)。类似于普通货币,每个代币与其他代币完全相同,具有相同的价值。ERC-20是以太坊上的可替换代币标准,而FungibleToken是Flow区块链上的可比标准。FLOW网络加密货币是一种可替换的代币,实现了Flow FungibleToken标准。
- 不可伪造的代币(NFT)。 这些是最近流行的。NFT是在一个相关主题下的资产,但每个代币都是独特的,有不同的元数据和价值。ERC-721和ERC-1155是以太坊的NFT标准,而NonFungibleToken是Flow区块链的类似标准。NBA顶级投篮时刻是Flow NFT的例子
这两种类型的智能合约很重要,因为它们是大多数区块链上最常见的智能合约类型。这些合约需要相互操作,所以它们需要利用一个共同的标准。我们使用Cadence合约接口来定义一个标准。
接口
接口
接口是一种抽象的类型,它规定了实现该接口的类型的行为。接口声明...
docs.onflow.org
接口是Cadence编程的一个非常重要的部分,所以如果你还没有读过接口的语言参考文件,请点击上面的链接,开始吧!😃
任何合同都可以实现合同接口中定义的功能。对于代币来说,这些接口包含余额等字段以及提款和存款等功能。它们强制要求每个符合接口的智能合约都必须遵循所有相同的规则。
然后,其他合同可以指定他们可以与任何遵循通用接口的令牌互动。这使得互操作性更容易。任何人都可以将一个新的代币插入生态系统或使用通用代币的新应用程序,而不必做任何专门的整合。
你可以在这里看到FungibleToken的标准。
onflow/flow-ft
这是对可替换代币合约的Flow标准的描述。它旨在包含最低限度的...
github.com
以及这里的NonFungibleToken的标准。
onflow/flow-nft
这是对Flow区块链上不可伪造的代币合约的工作进展标准的描述。它是...
github.com
接口(目前)指定确切的签名和类型
看一下fungible token的接口。每次指定@Vault类型时,比如在存款函数或提款函数中,@Vault指的是@FungibleToken.Vault ,这实际上意味着参数或返回值是FungibleToken.Vault类型。
实现该接口的合同必须与接口规范完全匹配。deposith的确切函数签名必须是
So if I was making a JoshToken contract, my depositfunction would not be allowed to accept a @JoshToken.Vault . It would still have to accept a FungibleToken.Vault , just like the standard interface specifies. If someone wanted to call my deposit function with a JoshToken.Vault , they would first have to cast it to a FungibleToken.Vault before passing it as a parameter.
This also applies to the NFT standard. The deposit function in implementations of the standards HAS to be
This causes a problem! If the type of the parameter that is passed to the deposit function is just a generic token, then anyone could deposit any token they want into your Vault or Collection! This is obviously be a problem, because supply of the token could be artificially increased by depositing random tokens into any Vault .
The CRITICAL PART
This leads me to the subject of the title of this post: The critical part of every token contract that you cannot forget. In order to ensure that only tokens of the correct type are deposited to your Vault or Collection , you need to cast the generic object to the concrete type of your contract with a line like this.
as! is the force-cast operator. It attempts to cast the object to the left of the operator as the type to the right of the operator. If the cast succeeds, meaning that the object is the type on the right, the execution of the function continues with the object as the new casted type. If the cast fails, then execution halts and the state is reverted. With this line, if a different token type is deposited, then the deposit will fail and you can maintain the integrity of your token!
You should see this line in many widely used smart contracts on mainnet, such as the FlowToken contract and the NBA Top Shot contract. If you find a token contract that doesn’t have this line in its deposit function, you should try to update it immediately if you can or contact the developer if you cant.
If you are copying and pasting popular smart contracts like FlowToken or Top Shot, this will already be included, but it is still important to ensure it is there.
Why can’t the type system handle this?
You might be thinking, “why does this important behavior need to be enforced by the implementation and not the type system?”
The answer is that this behavior can be enforced by the type system, but is complicated. The Cadence team has unfortunately not been able to add in this feature yet, but plans to include it in the future. We will also be having a token standard retrospective with the community in the future to discuss how the token standards could be improved. If you have thoughts, please let me know here or in the Flow discord and we can make sure you are included in the conversation!
This also underscores an important thing to remember if you are a Cadence developer: Cadence is still a very young language, and is still evolving very quickly. We’re constantly adding significant new features, and figuring out best practices for a wide variety of applications! If you are a Cadence developer right now, you are an early adopter and are part of the beginning of the first mainstream resource-oriented programming language! We are on the cutting edge of this technology and are learning new things every day, and every member of the community is extremely valuable in making Cadence as good as it can be.
I know dealing with things like the subject of this post can be a bit awkward sometimes, and it can be frustrating to work with a language that is still a work in progress, but that is what comes with being on the cutting edge. You should be proud that you are one of the first to take the plunge!
See ya next time, all-star! ⛹️♀️
Flow Discord: https://discord.gg/flow
Flow Forum: https://forum.onflow.org
Flow Github: https://github.com/onflow/flow