经过一段时间的学习,我写了一些简单的solidity代码,然后我决定把它们部署到区块链上
测试环境部署
这里我们选择的环境是
会发现我们的钱包被自动注入了,然后点击确认部署合约
我理解的Injected Provider 就是从本地的 VM测试环境 切换到 网络的测试环境
部署成功咯
这没什么难的
合约部署合约
这个我理解的就是当我们在某个合约中引入另一个合约,并且这个实例化这个合约,那么我们在部署当前合约时就相当于一块部署引入的合约
部署好合约后,未初始化引入的合约实例时,可以看到,simpleStorage的实例全是0
初始化后
那我们就得到一个实际的地址
合约互相交互
对于一个程序员来说,这真的没啥哈哈,就是函数互相调用
继承和重载
关注一下写法,和两个关键字,可以被修改的标识是virtual,覆盖的标识是override
FundMe合约
通过一个简单的交易合约,我们再来学习一些新的内容
-
payable
payable
是一个函数修饰符,用于指示函数可以接收以太币。在Solidity中,如果你想让一个函数接收以太币(即在交易中有ether被发送到这个函数),那么这个函数需要被标记为payable
-
require
require
函数是一种用于条件检查的控制结构,常用于验证函数调用的前提条件。如果require
的条件返回false
,则当前函数执行会立即终止,所有状态更改都会回滚,且未花费的Gas会被退回。此外,require
函数可以接受第二个参数作为错误信息,当条件不满足时,这个错误信息会被返回,便于调试。 -
msg.value
的含义在Solidity中,每个交易都有一个全局变量
msg
,它包含了交易的一些重要信息。msg.value
是其中的一个字段,表示随交易发送的以太币(ETH)数量,以wei为单位(1 ETH = 10^18 wei)。msg.value
常用于处理接收以太币的函数中,以确保正确的金额被发送。
设定的最小交易量是Usd,但是Eth的单位是wei,如何比较?
先来学一个新的概念
data feed
来自GPT
在区块链和智能合约的上下文中,"data feed"通常指的是从区块链外部世界(off-chain)到区块链内部(on-chain)的数据传输机制。因为智能合约运行在封闭的、去中心化的区块链网络上,它们无法直接访问或验证外部世界的数据(如股票价格、天气信息、货币汇率等)。数据馈送提供了一种解决方案,使得智能合约能够依据外部世界的真实信息来执行逻辑。
我们在Remix里面打开一下这段代码,这是最新的BTC和USD的转化,没找到ETH
看起来没问题,Solidity不支持浮点数或实数类型,这里的小数位数应该是8位
区块链是一个确定的系统,如果我们想要一些实时的、随机的东西,就需要预言机,chainLink是预言机网络
像我们刚刚实现的就是data Feed 获取外部数据
调用外部API
来自GPT
Chainlink允许智能合约安全地访问链下(off-chain)数据,包括通过HTTP请求从外部API获取数据。由于智能合约本身无法直接进行HTTP请求或访问外部服务器,Chainlink通过预言机节点(Oracles)提供了一种机制,使智能合约能够间接地发送HTTP请求并接收响应。这一功能极大地扩展了智能合约的应用场景,使其能够利用外部的世界数据,如天气信息、股票价格、飞行数据等。
Single Word Response | Chainlink Documentation
我们找到这个合约,然后在remix里面打开。这段Solidity代码定义了一个名为APIConsumer
的智能合约,利用Chainlink网络从外部API(例如CryptoCompare)获取数据。
在部署这个合约之前,先学习一下Link和ETH之间的区别
LINK:LINK是Chainlink网络的原生代币。Chainlink是一个去中心化的预言机网络,它允许智能合约安全地访问链下数据、支付API调用和执行链下计算。LINK代币用于支付Chainlink网络中的节点操作员,这些操作员为智能合约提供外部数据和计算服务。
ETH:ETH是以太坊区块链的原生货币。以太坊是一个广泛使用的智能合约平台,允许开发者部署去中心化应用(DApps)和智能合约。ETH主要用于支付交易费用和计算服务费(称为gas),这是在以太坊网络上执行操作(如执行智能合约)的必要成本。
然后我们去Sepolia网络上获取一些link
我们需要去找到这个地址,然后导入我们的钱包中,这样就可以使用刚刚获取到的link币
拿到了
然后如果要运行这个合约,需要从钱包给这个合约发送一点link币,
fee = (1 * LINK_DIVISIBILITY) / 10;
这段代码表明我们每次执行任务需要0.1Link
我们给部署好的合约发送0.2 Link
调用API查看一下,发现有结果了
requestVolumeData
是一个公共函数,任何人都可以调用它来触发一个Chainlink请求,从指定的URL获取ETH的24小时交易量。
调用外部接口
直接粘贴版
获取ABI代码 github.com/smartcontra…
获取部署在当前网络的合约的地址
切换到测试网部署运行函数,成功了
GitHub引入版
Solidity中的浮点数
// 定义一个public的函数getPrice,这个函数不接受任何参数,返回一个uint256类型的值,表示资产的价格。
// 由于使用了view修饰符,这个函数不会修改合约状态,仅仅是读取数据。
function getPrice() public view returns(uint256) {
// 创建一个AggregatorV3Interface接口的实例,指向Chainlink预言机合约的地址。
// 这个地址是Chainlink网络中特定资产价格预言机的地址。
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306);
// 调用priceFeed实例的latestRoundData函数获取最新的价格信息。
// latestRoundData函数返回多个值,但这里我们只关心第二个返回值,即当前的价格(price)。
// Chainlink预言机返回的价格是一个int256类型的值,可以表示负值,虽然价格通常不会是负的。
(,int256 price,,,) = priceFeed.latestRoundData();
// 将获取到的价格price转换为uint256类型,并且由于Chainlink返回的价格精度是8位小数,
// 而这里我们希望返回的价格精度是18位小数(符合以太坊的习惯),所以将价格乘以10的10次方进行转换。
// 最后返回调整精度后的价格。
return uint256(price * 1e10);
}
// 定义一个public的view函数getConversionRate,接受一个参数ethAmount(以太坊的数量),
// 并返回一个uint256类型的值,表示按当前ETH到USD的汇率计算出的ethAmount的美元价值。
// 由于使用了view修饰符,这个函数不会修改合约状态,仅仅是读取数据。
function getConversionRate(uint256 ethAmount) public view returns (uint256){
// 调用getPrice函数获取当前1 ETH等于多少美元(USD)。
// getPrice函数返回的价格已经根据Chainlink预言机调整为18位小数的格式。
uint256 ethPrice = getPrice();
// 计算提供的ethAmount按当前ETH到USD的汇率转换后的美元价值。
// 首先将ethPrice乘以ethAmount,结果是以wei为单位的ETH的美元价值(因为ethAmount和ethPrice都是以18位小数表示的)。
// 然后,将结果除以1e18来转换回标准的美元价值(不带小数)。
// 这个操作实质上是将wei单位的ETH转换为标准单位的ETH,并计算其USD价值。
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1e18;
// 返回计算出的美元价值。
return ethAmountInUsd;
}
我们设定了需要返回的最小美元数是50,1ETH大概是3000美元,50/3000差不多等于0.016是我们所需要的eth数,然后再转化成Wei。为了保证交易顺利进行,我们在这里设定value值为20000000000000000,也就是0.021e18
Library
在Solidity中,
using A for B;
语句是一种特殊的语法,它允许你将库A
中的函数附加到任何类型B
的变量上。这意味着,一旦声明了这种使用方式,类型B
的每个实例就能调用库A
中为它定义的函数,就好像这些函数是它自己的方法一样。这使得库的函数可以写得像是作用于这个类型的实例方法。
我们新建一个priceConverter的合约,将前面写的函数迁移过来,封装成一个库。
函数的关键词要改成internal
将priceConverter这个函数附加到uint256这个类型上,
msg.value就是
uint256类型,所以它可以使用priceConverter,并且
msg.value作为第一个参数隐式地传递给了
getConversionRate函数。
transfer和send
这两段代码展示了在Solidity中将以太币(Ether)从智能合约转移给调用者(
msg.sender
)的两种不同方法:transfer
和send
。
- 安全性:
transfer
和send
都通过限制gas的使用来提高安全性,防止在资金转移操作中可能发生的重入攻击。 - 错误处理:
transfer
在失败时自动回滚,不需要额外的错误处理;而send
在失败时返回false
,需要开发者检查这个返回值并手动处理失败情况。 - 选择使用哪一个:选择
transfer
还是send
取决于你是否想在资金发送失败时让整个交易回滚(使用transfer
),还是想手动处理这种失败情况(使用send
)。
使用
call
来发送以太币是Solidity 0.6.x版本之后推荐的做法,因为它相较于send
和transfer
提供了更高的灵活性。
修饰器
在Solidity中,修饰器(Modifiers)是一种特殊的声明,用于修改智能合约函数的行为。通过预先定义一些条件,修饰器可以在函数执行前或执行后添加自定义逻辑,例如验证条件、修改状态或事件记录等。这使得代码更加模块化、可重用,同时提高了智能合约的安全性。