初识 智能合约
各位区块链世界的冒险者们,今天我们来聊聊一个既神奇又有点”笨笨”的东西——智能合约。想象一下,如果自动售货机突然学会了编程,还能自动执行各种复杂的任务,那会是什么样子?没错,这就是智能合约的魔力所在!
首先,让我们来认识一下这个神奇的发明。智能合约是以太坊的一大创新,本质上就是运行在区块链上的程序。它就像是一个被严格管教的乖孩子,永远按照预设的规则行事,不会耍小聪明,也不会偷懒。
为了确保所有的”孩子”都表现一致,以太坊还专门设立了一个超级严格的”老师”——以太坊虚拟机(EVM)。在 EVM 的监督下,所有的节点都必须得到一模一样的答案,就像是一群小学生在做一道数学题,每个人的答案都必须一致,否则就要被”罚站”。
不过,这个”魔法自动售货机”也有它的局限性。比如,它不支持浮点运算,也不能生成真正的随机数。这就好比给程序员系上了手铐脚镣,让他们在写代码时束手束脚。但是,耍小聪明的开发者们总想找到办法绕过这些限制,就像是在玩一场智力游戏。
说到开发,Solidity 是智能合约世界的”普通话”。如果你想在这个世界里畅通无阻,学好 Solidity 就像是学好普通话一样重要。
有趣的是,智能合约部署后会获得一个地址,但这个地址就像是一个没有钥匙的保险箱,只能通过特定的方式打开。它没有私钥,只能通过调用公共函数来操作。这种设计确保了合约的安全性和透明度。
智能合约还是个多面手,它不仅可以接收和发送以太币,还能存储数据。你可以把它想象成一个多功能的电子钱包,既能存钱,又能记账,简直是区块链世界的瑞士军刀!
更厉害的是,合约还能调用其他合约,实现更复杂的功能。这就像是在玩积木游戏,通过组合不同的积木,我们可以搭建出令人惊叹的复杂结构。
各位冒险者要注意了,使用智能合约也有一些需要特别小心的地方:
- 合约的执行结果必须在所有节点上保持一致,这是保证其可信性的关键。就像是一群人在玩”传话游戏”,如果最后的结果不一致,那这个游戏就失去了意义。
- 编写合约时要时刻记住它的特殊限制,比如不支持浮点运算等。这就像是在玩一个特殊的拼图游戏,有些形状的拼图是不存在的,你得想办法用其他的拼图来代替。
- 合约不能主动执行,需要外部触发。这就像是一个沉睡的巨人,需要有人去推一把才能醒来。有时候,我们可能需要额外的线下服务来定期”叫醒”这个巨人。
- 合约间的嵌套调用虽然强大,但也增加了出错和被攻击的风险。这就像是在搭建一个复杂的多米诺骨牌,一不小心可能就会全盘崩溃。所以,编写时需要格外谨慎。
智能合约就像是区块链世界的”自动售货机”,一旦部署好,就能按照预设的规则自动运行。
这个”售货机”比普通的要复杂得多,既能存钱、付款,还能和其他”售货机”互动。不过,千万别把它想得太聪明,它还是需要我们这些人类来精心设计和小心使用的!
如何写一个简单的智能合约
教程我是按照廖雪峰老师的教程,自己的操作了,写了一个vote投票的合约。
1. 首先申请测试网的Ether
部署合约也是一个交易,需要一个外部账户,花费一定的Gas,就可以把合约部署到链上。
测试环境不能用在真金白银, 就用测试环境的。
如何申请? 我是申请的这个网络的Ether。SepoliaETH
以太坊有多个测试网,开发前请在Etherscan确认使用哪个活动的测试网。
有些钱包不支持,比如我的okx的就不行,用的metamask。
https://faucets.chain.link/sepolia
2. 部署合约
访问Remix(注意:要部署合约,只能通过http访问,不能使用https),在左侧选择“File explorers”,在默认的Workspace的contracts目录下新建文件Vote.sol,然后贴入上一节我们编写的代码。
// SPDX-License-Identifier: GPL-3.0
pragma solidity =0.8.28;
contract Vote {
event Voted(address indexed voter, uint8 proposal);
mapping(address => bool) public voted;
uint256 public endTime;
uint256 public startTime;
uint256 public proposalA;
uint256 public proposalB;
uint256 public proposalC;
constructor(uint256 _startTime, uint256 _endTime) {
startTime = _startTime;
endTime = _endTime;
}
function vote(uint8 _proposal) public {
require(block.timestamp < endTime, "Vote expired..");
require(_proposal >= 1 && _proposal <= 3, "Invalid proposal.");
require(!voted[msg.sender], "Can not vote again.");
voted[msg.sender] = true;
if (_proposal == 1) {
proposalA ++;
}
else if (_proposal == 2) {
proposalB ++;
}
else if (_proposal == 3) {
proposalC ++;
}
emit Voted(msg.sender, _proposal);
}
function votes() public view returns (uint256) {
return proposalA + proposalB + proposalC;
}
}
关于代码解释,看不懂的,可以直接丢给GPT分析下即可。
合约只能有一个构造函数, 这里的函数,设置2个入参。
ENVIRONMENT,这里选择钱包。
时间戳:设置为如图。
点击 transact。
部署好之后,链上就可以看到了。
交易tx的信息。从to里面可以看到一个contract的地址。和这个就是合约地址。 https://sepolia.etherscan.io/tx/0x98bd4157fefbd11bbb70cf808ddcd9fb7a031069f8581d080556883d7bd91c48
合约: https://sepolia.etherscan.io/address/0xd139e60592f4d7fd7177edd9f4d49a9f67608617
可以查看历史,钱包里面的活动页面,可以看到历史的。点开就可以看到了
3. 调用和这个合约
调用之前,需要publish,发布的网址也是需要加一个二级域名的标识。
我用的测试网络对应的是:verifyContract
按照提示,添加一些field即可。
提交之后,这个合约的:sepolia.etherscan
这里contract有一个confirm的标识,绿色勾勾。
访问合约的只读函数时,无需消耗Gas,也无需连接钱包
,直接切换到“Read”面板,即可看到只读函数的返回值。
最后一个voted,输入地址,query。
4. 写入合约
当我们要写入合约时,就必须提交一个签名的交易,并消耗一定的Gas。我们在Etherscan的合约页选择“Write”,会出现一个“Connect to Web3”的链接。
然后查看交易链接: sepolia.etherscan
然后查看,这个地方的值就被修改为1.
read more
- https://liaoxuefeng.com/books/blockchain/ethereum/smart-contract/index.html
- https://github.com/chaseSpace/learn_blockchain/blob/main/smart_contract_dev_guide.md
- https://web3py.readthedocs.io/en/stable/