hardhat示例工程,Lock.sol代码解析。
笔者目前正在学习智能合约开发,正好将日常积累的整理出来,以供后续朋友一起进步、学习,欢迎一起探讨。
在开始本章节之前,建议先去阅读 <a>Hardhat 入门(一)</a>,前文中记录了如何初始化一个“hardhat的demo工程”,此文也是基于上一工程讲解的。
示例工程中,包含了一个Lock合约,文件位于contracts文件夹下,如图所示:
合约功能:
总结该合约主要功能:该合约是一个简单的示例合约,在部署合约的时候,存入任意资金并设置解锁时间(解锁时间必须大于当前时间),合约中提供了“withdraw”方法,部署者可在时间到达后通过该方法取走之前存入的资金。
代码示例,笔者在每一行代码中添加了注释,只要是为了方便理解:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24; // 定义版本号,代表必须要此版本以上的编译器才可
// Uncomment this line to use console.log
// import "hardhat/console.sol";
contract Lock { // 定义合约名称
uint public unlockTime; // 定义变量,保存解锁时间的时间戳,uint表示无符号整型,public表示公开可见,会自动生成public的get方法。
address payable public owner; // 定义地址变量,保存管理员地址也就是部署者的地址。当一个函数或合约被标记为payable时,它就可以接收以太币(原生代币)的转账。
event Withdrawal(uint amount, uint when); // 定义事件,可以理解为js中的console.log, 只不是会记录在交易中。
constructor(uint _unlockTime) payable { // 定义有参构造方法,需要传入解锁时间_unlockTime,并且该方法被payable标记,意味着在部署时,可以向该合约转账,在该合约中就代表存入的资金
require(
block.timestamp < _unlockTime,
"Unlock time should be in the future"
); // 判断语句,可以理解为其它语言中的if,然后throw异常。当require语句的条件为false时,会触发异常并导致当前交易被回滚。
unlockTime = _unlockTime; // 入参赋值
owner = payable(msg.sender); // 保存部署者即管理员的地址。msg.sender代表部署者的地址,注意此处将其转换为payable类型了,因为后面需要向该地址转账。
}
function withdraw() public { // 提现方法
// Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal
// console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp);
require(block.timestamp >= unlockTime, "You can't withdraw yet"); // 判断时间
require(msg.sender == owner, "You aren't the owner"); // 判断调用者地址是不是管理员地址
emit Withdrawal(address(this).balance, block.timestamp); // 输出日志
owner.transfer(address(this).balance); // 调用转账方法将合约的钱,发送给调用方法者的地址。
}
}
在Solidity智能合约中,有一些特殊的全局变量可以提供有关区块链和当前交易的信息。这些全局变量可以在智能合约的任何地方访问,用于获取有关当前上下文的信息。以下是一些常用的全局变量:
msg.sender
:表示当前调用合约的地址,即交易发起者的地址。
msg.value
:表示当前交易发送的以太币数量(单位为wei)。
msg.data
:表示交易调用数据。
block.number
:表示当前区块的区块号。
block.timestamp
:表示当前区块的时间戳(以秒为单位)。
block.difficulty
:表示当前区块的难度。
block.coinbase
:表示当前区块的矿工地址。
tx.origin
:表示交易的原始发送者地址,即最初发起交易的地址,而不是当前合约调用者的地址。
这些全局变量提供了智能合约所需的关键信息,以便合约可以根据当前的上下文执行逻辑或验证操作。开发人员可以利用这些全局变量来编写更加智能和灵活的智能合约。
在Solidity智能合约中,有一些特殊的函数类型具有特定的目的和行为。这些函数类型包括构造函数、接收函数、回退函数和纯函数。以下是这些特殊函数的简要说明:
constructor
关键字声明。pragma solidity ^0.8.0;
contract MyContract {
constructor() {
// 构造函数初始化逻辑
}
}
receive
关键字声明。pragma solidity ^0.8.0;
contract MyContract {
receive() external payable {
// 接收函数逻辑
}
}
pure
或view
。fallback
关键字声明。pragma solidity ^0.8.0;
contract MyContract {
fallback() external {
// 回退函数逻辑
}
}
pure
关键字。pragma solidity ^0.8.0;
contract MyContract {
function add(uint a, uint b) public pure returns (uint) {
return a + b;
}
}
这些特殊函数类型在Solidity合约中具有重要的作用,开发人员可以利用它们来实现不同的逻辑和功能。
在Solidity智能合约中,可以使用一些内置的函数来实现以太币的转账操作。以下是一些常用的函数用于在智能合约中进行以太币的转账:
address.transfer(amount)
函数用于将指定数量的以太币发送到另一个地址。address payable recipient = 0x1234567890123456789012345678901234567890;
function sendEther() public {
recipient.transfer(1 ether);
}
address.send(amount)
函数与transfer
函数类似,用于将指定数量的以太币发送到另一个地址。send
函数在发送失败时不会抛出异常,而是返回一个布尔值来指示是否发送成功。address payable recipient = 0x1234567890123456789012345678901234567890;
function sendEther() public {
bool success = recipient.send(1 ether);
require(success, "Transfer failed");
}
address.call.value(amount).gas(gasLimit)()
函数是一种更底层的方式来发送以太币,并且可以指定 gas 的限制。address payable recipient = 0x1234567890123456789012345678901234567890;
function sendEther() public {
(bool success, ) = recipient.call{value: 1 ether}("");
require(success, "Transfer failed");
}
这些函数可以帮助您在智能合约中实现以太币的转账操作。在进行转账时,务必谨慎处理错误情况,以确保资金安全并避免潜在的漏洞。
以上便是对示例工程中的合约代码讲解,并且也针对用到的知识点做出相应的扩展。希望能与大家共同进步。
若过程有错误,还望海涵,请多指教。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!