翻译者: 大杨, 链因智能CEO, 一家初创区块链技术公司,DEFI布道者。
技术点: DEFI,ETH,NODEJS,SOLIDITY
今天抽出了一些时间,翻译了CoinBase的Pete Kim 写的【Introduction to Building on DeFi with Ethereum and USDC — Part 1】DEFI编程入门学习的文章。
翻了下Pete Kim的twitter和他的github,发现是个全栈高手和社区活跃者,看上去应该是韩国人,技术很不错,人也很帅 😂。
最为美系的第一交易所CoinBase对整个Crypto生态的贡献是巨大的,本篇DEFI编程的入门文章也非常适合新手,看了有很想翻译的冲动,就花了2小时做了下整理,并在kovan的网络上实战了一把,对很多细节的地方做了补充,强烈推荐给大家。 经历DEFI,后续链因智能3年积累的相关技术都会进行开源,通过开源促进技术发展。
以下是文章的内容:
首先介绍 CoinBase 的价值观和愿景。
在Coinbase,我们的任务是建立一个开放的财务系统。我们坚信,促进经济自由将使世界变得更美好。分布式金融,简称DeFi-一种开放,无边界和可编程的金融-是我们伟大愿景不可分割的一部分。
智能合约
DeFi由运行在分布式网络(例如以太坊(“区块链”))上的数字货币(如美元代币(USDC))智能合约组成。智能合约的想法由来实际上很简单。数字货币和密码学的先驱尼克·萨博(Nick Szabo)最初在1997年提出了这个想法,他将自动售货机描述为智能合约的始祖。
自动售货机是合同的自动化版本,以电子硬件的形式表示:
您通过向机器中投入钱来支付显示的价格,机器将为您分配饮料
您不支付显示的价格,也不分配饮料
如果您支付了显示的价格但机器没有分配饮料,或者即使您没有支付显示的价格也分配了饮料,则违反了合同
自动售货机无需人工干预即可完全自主地管理其合同义务。
现代智能合约的工作方式相同,但是合约条款被表示为可执行的计算机代码,而不是在硬件中实现。在其上运行智能合约的网络的分散性确保了它们以书面形式执行,并且没有任何单个实体能够弯曲规则或操纵结果。一个重要的警告是,因为网络逐字执行代码,所以错误的智能合约代码可能会导致意外的后果(“代码就是法律”)。
没有比现在更好的时机
许多人发现基于加密技术构建的区块链非常令人生畏,并认为只有坚韧的计算机科学家才能使用它。尽管就在几年前,情况确实如此,但自那时以来,工具和开发人员用户体验已有了显着改善,任何具有基本编程技能的人都可以开始构建。
DeFi生态系统目前正在爆炸性增长。 USDC在不到2年的时间里达到了$1B的市值,并且在不到3年的时间内,存储在各种DeFi服务中的资产总值超过$2B。确实没有一个哪个领域有这么好的时机快速发展。
来源:DeFi Pulse
以下教程是开始开发自己的DeFi智能合约的简单指南。
我们希望,这样的指南将有助于建立全球开放的民主化金融体系。
入门
本教程系列假定您具有JavaScript的经验,JavaScript是世界上使用最广泛的编程语言。您也可能被介绍过Solidity,这是一种在以太坊上使用的智能合约编程语言,这是世界上使用最广泛的智能合约区块链编程语言。最后,您将与DeFi应用常用稳定币USDC进行交互(这里我们Fake了一个USDC,不是真实USDC)。
搭建开发环境
首先,我们需要一个类似Unix的环境,并在其上安装Node.js v12.x(最新的LTS版本)。 MacOS本质上是Unix环境,Windows用户可以通过从Microsoft Store在WSL上安装Ubuntu来获得它。在MacOS和Windows中可以找到更详细的步骤。对于代码编辑器,强烈建议使用 Visual Studio Code,因为您要使用的项目模板已经预先配置好了,但是从技术上讲,您可以使用任何编辑器。哦,我更喜欢Vim而不是Emacs。
设置项目
设置Solidity项目需要一些工作,老实说,分心对于这个阶段的学习不是很有用,因此已经为您准备了一个预先配置的模板。
这块作者提供了一个很好的模版来跑,原地址: https://github.com/CoinbaseStablecoin/solidity-tutorial ,这里我做了一些修改,FORK了一个项目地址,大家需要看代码的可以用下面的地址,作者提供的模版非常方便,可以让动手,推荐使用作者的地址。
在终端中运行以下命令以下载并设置模板:
1 | git clone https://github.com/CoinbaseStablecoin/solidity-tutorial.git # 作者原模版地址 |
当yarn尝试构建本机扩展时,您可能会看到一些编译错误。这些是可选的,可以忽略这些错误。只要您最后看到“完成”消息,就可以继续。
在Visual Studio Code中打开项目
在Visual Studio Code中打开项目文件夹(solidity-tutorial)。第一次打开项目时,Visual Studio Code可能会提示您安装扩展。继续并单击“全部安装”,这将向编辑器添加各种有用的扩展,例如自动代码格式和Solidity语法突出显示。
在以太坊上创建账户
在以太坊上进行任何操作之前,您需要拥有一个帐户。帐户通常称为“钱包”,因为它们可以包含ETH和USDC等数字资产。最终用户通常使用Coinbase Wallet或Metamask等以太坊钱包应用程序创建帐户,但是使用模板随附的出色的ethers.js库,以编程方式创建帐户也非常简单。
在src文件夹中创建一个名为createWallet.js的新JavaScript文件,然后输入以下代码:
保存文件,并使用Node执行代码,如下所示:
1 | const ethers = require("ethers"); |
在shell命令行状态下执行:
1 | node src/createWallet.js |
执行后生成如下结果, 生成助记词和地址:
1 | Mnemonic: viable glow tone pole input series weather slam blouse embark achieve position |
刚才发生了什么? 好吧,您拥有了一个全新的以太坊账户。 “助记符”或可能更普遍地称为“恢复短语”是从帐户执行操作所需的密钥的人类可读表示,并且地址是帐户的名称和标识符。将它们复制到某个地方。附带说明一下,本文中显示的助记符已稍作更改,以阻止您使用它,请使用您自己的助记符!
可以将它们视为银行帐户的密码和帐号,只需要几秒钟即可创建一个,并且不必填写申请表或共享任何个人信息。您也可以在任何地方运行此代码。
⚠️注意该帐户的记忆符号必须保密。如果丢失,您将永远无法访问您的帐户以及该帐户中存储的所有资产,没有人能够为您提供帮助!妥善保管!
从技术上讲,您本身并没有真正“创建”帐户。相反,您创建的是私钥/公钥对。如果您对引擎盖下实际发生的事情感到好奇,请阅读椭圆曲线密码学以及比特币和以太坊规范BIP39,BIP32,EIP55及其在此项目中的实现。
关于Gas燃料和挖矿
以太坊是一个分布式网络,由世界各地成千上万的计算机组成,它们并非完全免费。要在区块链上执行任何状态更改(例如存储和更新数据),您必须向网络运营商支付以太坊(ETH)的交易费,在以太坊上也称为“ GAS”。这与运营商为在链中添加新区块而获得的奖励一样,也激励着他们保持计算机正常运行。此过程称为“挖矿”,而网络运营商称为“矿工”。我们将在本教程的后面部分(GAS,GAS价格和GAS限制)再次讨论这一点。
获取测试网ETH
现在您已经有一个帐户,您应该存入一些ETH。我们不想在开发时浪费真钱,因此我们将获得一些假的ETH,用于在测试网络(“ testnet”)上进行开发和测试。有许多不同的以太坊测试网,但由于容易获得测试Token,因此我们将使用Kovan。首先,让我们使用以太坊的区块浏览器Etherscan检查当前余额。为此,您可以在浏览器中输入以下网址,然后用您之前创建的地址(从0x开始)替换 0x6598f11d48Da2bfA897d5Eb3968223f98dabc008。
https://kovan.etherscan.io/address/0x6598f11d48Da2bfA897d5Eb3968223f98dabc008
您应该看到您的余额为0 ETH。保持此选项卡处于打开状态,然后在其他选项卡中打开Kovan Ethereum Faucet 地址: https://faucet.kovan.network。在页面中,输入您的地址,然后单击“发送给我”按钮。交易可能只需要几秒钟到一分钟或一两分钟即可完成。再次检查Etherscan,您应该在列表中看到1 ETH的新余额和一笔传入交易。
资料来源:https://faucet.kovan.network
以编程方式获取ETH余额
连接以太坊,使用Etherscan查看余额非常有用,但是也可以通过代码轻松查看余额。但是,在回到代码之前,我们需要一种连接到以太坊的方法。有很多方法可以做到这一点,包括自己在计算机上运行网络节点,但是到目前为止,最快,最简单的方法是通过诸如INFURA或Alchemy之类的托管节点提供程序来实现,也可以自建节点。前往INFURA,创建一个免费帐户并创建一个新项目以获取API密钥(项目ID),链接这里: https://infura.io/dashboard/ethereum 注册后在面板中创建自己的Project,然后拿到APIKEY。如果要自己搭建节点,也可以使用Go Ethereum(“ geth”)和Open Ethereum(以前称为Parity Ethereum)是两种使用最广泛的以太坊节点软件,这里后续我会在后续章节中列举节点搭建。
用代码查看ETH余额
首先,让我们编写代码以从助记符中读取并获取帐户。在src文件夹中创建一个名为wallet.js的新JavaScript文件,然后输入以下代码:
1 | const ethers = require("ethers"); |
用您自己的代码替换助记符字符串。请注意,在生产代码中,助记符不应该这样硬编码。相反,应从配置文件或环境变量中读取它,以免例如由于将其检入源代码存储库而意外泄漏。
执行代码,您应该能够看到与之前获得的地址相同的地址:
1 | ➜ solidity-tutorial git:(master) ✗ node src/wallet.js |
看到生成的地址:0x6598f11d48Da2bfA897d5Eb3968223f98dabc008
接下来,在同一文件夹中创建一个名为provider.js的新文件。在此文件中,我们将使用我们先前获得的INFURA API密钥初始化提供者对象。确保将API密钥字符串替换为您自己的字符串:
1 | const ethers = require("ethers"); |
注意这里需要在truffle-config.js进行网络配置:
1 | networks: { |
最后,我们将使用在同一文件夹中新建名为getBalance.js的新文件,并通过wallet.js和provider.js来获取ETH余额:
1 | const ethers = require("ethers"); |
运行代码,您将看到ETH余额!
1 | node src/getBalance.js |
代币计价
我们刚刚创建的代码很容易解释,但是您可能想知道ethers.utils.formatUnits(balance,18)的作用。好吧,ETH实际上可以整除到小数点后18位,最小的面额单位称为“ wei”(发音为“ way”)。换句话说,一个ETH等于1,000,000,000,000,000,000 wei。另一个常见的面额是Gwei(发音为“ Giga-way”),为10亿魏。 getBalance方法碰巧以wei返回结果,因此我们必须通过将结果乘以10⁸将其转换回ETH。可以在这里找到所有面额的清单。
您还可以使用ethers.utils.formatEther(balance),这是ethers.utils.formatUnits(balance,18)的简写。
获取Testnet USDC
您帐户中的ETH感到有些孤单,所以我们也想获取其中的USDC。我在Kovan测试网上部署了一个FakeUSDC智能合约。它没有专门的水龙头网站,但合同包含一项功能,在调用该功能时,您将获得一些免费的Kovan测试网USDC。如果您导航到Etherscan中的合同代码选项卡,并在合同源代码中搜索gimmeSome。这就是我们要调用的功能,用于将一些USDC发送到我们的帐户。
1 | pragma solidity 0.6.12; |
进行交易以调用智能合约
在以太坊智能合约中主要有两种类型的功能:读写和只读。前者可能导致存储在区块链中的数据发生变化,而后者纯粹是读取但从未写入。可以在不创建事务的情况下调用只读函数,因此无需支付交易费用,除非作为读写函数的一部分进行调用。另一方面,必须在交易内部调用读写功能,并且必须支付交易费(GAS)。调用gimmeSome函数会导致存储在区块链中的USDC余额发生变化,因此必须在交易内部调用它。
调用智能合约功能需要一些额外的步骤,但这并不太困难。首先,我们需要找到我们要调用的函数的完整接口,也称为函数签名或函数原型。在合同源代码中再次查找gimmeSome,您将发现界面如下:
1 | function gimmeSome() external |
这是一个非常简单的函数,不带任何参数,并且被标记为外部函数,这意味着该函数只能从外部调用,而不能从该协定内的其他函数调用。因为我们将在事务中直接调用此函数。
显而易见,在以太坊主网络上部署的“真实” USDC合约中 不存在gimmeSome功能。 下面需要去部署智能合约,才能获取合约的地址,以便在下面调用:
1 | MNEMONIC="viable glow tone pole input series weather slam blouse embark achieve position" INFURA_API_KEY="c844845b06f84d379ba3fb3bba5a1f99" truffle deploy --network=kovan |
我们执行 truffle deploy 命令,在kovan测试网络中发布我们写好的合约。 签名的2个是地址的私钥和INFURA的KEY,这样能够用这个账户部署合约,部署完成后将现实如下过程,部署的合约数量和总共花费的GAS的费用。
1 | 3_init_FakeUSDC.js |
拿到合约地址,在src文件夹中创建一个名为getTestnetUSDC.js的新文件,然后输入以下代码:
1 | const ethers = require("ethers"); |
该代码首先使用我们感兴趣的函数gimmeSome的接口实例化一个合同对象(新ethers.Contract),并将其指向testnet Fake USDC合同的地址:0x68ec⋯69c4。然后,您可以调用列出的任何功能。 gimmeSome函数本身不会接受任何参数,但是您可以将事务选项指定为最后一个参数。在这种情况下,我们给它20 Gwei的GAS价格,这将加快交易速度。本质上,与网络交互的所有方法都是异步的,并返回Promise,因此我们使用的是JavaScript的await表达式。然后,代码将打印交易哈希,这是您交易的唯一标识符,可用于跟踪进度。然后等待直到确认交易。
运行代码,您将看到类似以下内容:
1 | node src/getTestnetUSDC.js |
输出结果:
1 | ➜ solidity-tutorial git:(master) ✗ node src/getTestnetUSDC.js |
瞧!您已经使用代码进行了首次以太坊交易!在Kovan Etherscan中检查您的地址和交易哈希。现在您应该看到,由于执行交易所支付的汽油费用,您现在拥有10个测试网USDC和略少于1 ETH。
ℹ️如果您在Etherscan中检查交易,您会发现这是将 (0)ETH与4字节数据一起发送到合约地址的交易。如果函数调用具有参数,则将不止4个字节的数据。如果您想了解此数据的编码方式,请阅读以太坊合约ABI规范。
GAS,GAS价格和GAS限额
之前,我提到过,我们为交易提供20 Gwei的价格,以加快交易速度,并且脚本还显示使用的GAS量。这些都是什么意思?嗯,以太坊是一个由网络运营商组成的网络。将其视为一台世界计算机。它不是一台免费的计算机,您在该计算机上运行的每条指令都需要钱。该计算机也被世界各地的所有人共享,这意味着每个人都必须互相竞争才能在此计算机上花费时间。
我们如何做到这一点?
好吧,我们可以在这台计算机上拍卖时间,而您愿意为在此计算机上运行的每条计算指令支付的费用越多,网络运营商(矿工)将给您更多的时间。这种确定不是完美的,因为它可能会导致只有富人才能使用此系统的特权。但是,这是我们拥有的最差的解决方案,直到系统具有更高的可伸缩性并可以容纳更多的交易为止。
回到区块链的术语上,“已使用的GAS”是您运行交易后消耗的计算资源量,“GAS价格”是您愿意为每单位天然气支付多少费用。通常,您愿意支付的费用越高,交易的优先级就越高,并且网络会更快地对其进行确认。在我们的案例中,我们使用20 Gwei作为GAS价格,使用的GAS为35121(您还可以通过在Etherscan中检查交易来找到此价格),因此总GAS成本为35121 * 20 Gwei = 702,420 Gwei 或0.00070242 ETH。
由于用GAS要花钱,因此您可能需要设置您愿意花费的最大GAS上限。幸运的是,您可以设置“GAS限制”。如果交易最终需要的GAS超过指定的GAS上限,则交易将失败,而不是继续执行并消耗比您愿意支付的更多的GAS。要注意的一个副作用是,如果执行由于限制而最终失败,那么已花费的汽油量将不会退还给您。
调用智能合约功能以读取数据
您可以检查是否在Etherscan上收到了10 USDC,但请通过代码检查余额来确认这一点。
我们在src文件夹中的创建个新文件getFakeUSDCBalance.js,内容如下:
1 | const ethers = require("ethers"); |
USDC是ERC20代币,因此它包含ERC20规范中定义的所有方法。 balanceOf是其中之一,其接口直接来自规格。 balanceOf是一个只读函数,因此可以免费调用,不需要作为事务提交。 最后,重要的是要注意,USDC使用6个小数位精度,而许多其他ERC20令牌使用18个精度。
您可以在此处了解有关Solidity函数的更多信息。
运行代码,现在您还将看到USDC余额:执行:
1 | ➜ solidity-tutorial git:(master) ✗ node src/getFakeUSDCBalance.js |
转移ETH和USDC
现在,让我们看看如何使用帐户中的ETH和USDC。
转移ETH
在src文件夹中创建transferETH.js并输入以下代码:
1 | const ethers = require("ethers"); |
这段代码虽然比以前的代码长,但实际上只是到目前为止所学到的一切的结合。该脚本接受两个命令行参数。第一个是收件人地址,第二个是发送金额。然后,它确保提供的地址有效,提供的金额不为负,并且帐户具有足够的余额以能够发送所请求的金额。然后,它提交交易并等待确认。
使用我们之前创建的createWallet.js脚本创建一个新帐户,然后尝试向新地址汇款:
1 | ➜ solidity-tutorial git:(master) ✗ node src/createWallet.js |
我们建了个新地址,在将0.1 ETH转移到 0x7B6d22b2130e585f5dacb40dE9Ff9DbD23E5CDB0 新地址上:
1 | ➜ solidity-tutorial git:(master) ✗ node src/transferETH.js 0x7B6d22b2130e585f5dacb40dE9Ff9DbD23E5CDB0 0.1 |
您可以在Etherscan中验证结果。
我们还要测试验证逻辑是否有效, 以下是一些无效的例子:
1 | $ node src/transferETH.js foo |
转移USDC
您将能够复用大部分代码。主要区别在于USDC有6个小数位,并且您必须使用ERC20规格的传递函数来执行交易。您还需要将参数“ to”和“ value”传递给转让智能合约功能,而不是以太坊交易本身。在同一文件夹中创建transferUSDC.js并输入以下内容:
1 | const ethers = require("ethers"); |
尝试一下向新地址转1个FakeUSDC,它应该也可以正常工作:
1 | ➜ solidity-tutorial git:(master) ✗ node src/transferUSDC.js 0x7B6d22b2130e585f5dacb40dE9Ff9DbD23E5CDB0 1 |
恭喜你,完成了!
最后看看之前的地址还有多少个ETH和USDC
1 | ➜ solidity-tutorial git:(master) ✗ node src/getFakeUSDCBalance.js |
在本教程中,您学习了如何生成帐户,查询余额,转移代币以及调用智能合约。您可能以为您对加密还不很了解,但是实际上您已经足够了解能够构建自己的加密钱包应用程序了。我们一直在编写命令行脚本来简化操作,但是如何使用基于Web的漂亮图形界面来完成作业来构建脚本呢?
在本教程系列的下一部分中,我们将使用Solidity从零开始编写我们自己的以太坊智能合约,并学习如何构建自己的可与USDC交换的代币。我们还将使用今天学到的技术与该合约进行互动。敬请关注。这个是之前作者的下一篇, 之后大杨会加上如何使用脚本自动化的调用Uniswap进行自动交易。
如果您对分布式金融DEFI的未来感兴趣,请关注Chaininout链因智能,大杨作为创始人,会努力的科普DEFI技能,促进生态发展。
作者原文中有CoinBase的免责声明,这里略过,以下也是常规的我们的免责声明。
以上表达的观点是作者的观点,并不代表Chaininout链因智能的观点和立场。信息仅用于一般教育目的,并不构成对金融产品的投资或其他建议。大杨和Chaininout对本篇内容上任何信息的准确性,完整性,及时性,适用性或有效性不做任何陈述,对于该信息的任何错误,遗漏或延误,或因其造成的任何损失,伤害或损害,概不负责。显示或使用。除非另有说明,否则本文提供的所有图像均为大杨的财产,所有商标均为其各自所有者的财产。