智能合约 学习记录 1

Posted by 叉叉敌 on September 11, 2024

初识 智能合约

各位区块链世界的冒险者们,今天我们来聊聊一个既神奇又有点”笨笨”的东西——智能合约。想象一下,如果自动售货机突然学会了编程,还能自动执行各种复杂的任务,那会是什么样子?没错,这就是智能合约的魔力所在!

首先,让我们来认识一下这个神奇的发明。智能合约是以太坊的一大创新,本质上就是运行在区块链上的程序。它就像是一个被严格管教的乖孩子,永远按照预设的规则行事,不会耍小聪明,也不会偷懒。

为了确保所有的”孩子”都表现一致,以太坊还专门设立了一个超级严格的”老师”——以太坊虚拟机(EVM)。在 EVM 的监督下,所有的节点都必须得到一模一样的答案,就像是一群小学生在做一道数学题,每个人的答案都必须一致,否则就要被”罚站”。

不过,这个”魔法自动售货机”也有它的局限性。比如,它不支持浮点运算,也不能生成真正的随机数。这就好比给程序员系上了手铐脚镣,让他们在写代码时束手束脚。但是,耍小聪明的开发者们总想找到办法绕过这些限制,就像是在玩一场智力游戏。

说到开发,Solidity 是智能合约世界的”普通话”。如果你想在这个世界里畅通无阻,学好 Solidity 就像是学好普通话一样重要。

有趣的是,智能合约部署后会获得一个地址,但这个地址就像是一个没有钥匙的保险箱,只能通过特定的方式打开。它没有私钥,只能通过调用公共函数来操作。这种设计确保了合约的安全性和透明度。

智能合约还是个多面手,它不仅可以接收和发送以太币,还能存储数据。你可以把它想象成一个多功能的电子钱包,既能存钱,又能记账,简直是区块链世界的瑞士军刀!

更厉害的是,合约还能调用其他合约,实现更复杂的功能。这就像是在玩积木游戏,通过组合不同的积木,我们可以搭建出令人惊叹的复杂结构。

各位冒险者要注意了,使用智能合约也有一些需要特别小心的地方:

  1. 合约的执行结果必须在所有节点上保持一致,这是保证其可信性的关键。就像是一群人在玩”传话游戏”,如果最后的结果不一致,那这个游戏就失去了意义。
  2. 编写合约时要时刻记住它的特殊限制,比如不支持浮点运算等。这就像是在玩一个特殊的拼图游戏,有些形状的拼图是不存在的,你得想办法用其他的拼图来代替。
  3. 合约不能主动执行,需要外部触发。这就像是一个沉睡的巨人,需要有人去推一把才能醒来。有时候,我们可能需要额外的线下服务来定期”叫醒”这个巨人。
  4. 合约间的嵌套调用虽然强大,但也增加了出错和被攻击的风险。这就像是在搭建一个复杂的多米诺骨牌,一不小心可能就会全盘崩溃。所以,编写时需要格外谨慎。

智能合约就像是区块链世界的”自动售货机”,一旦部署好,就能按照预设的规则自动运行。

这个”售货机”比普通的要复杂得多,既能存钱、付款,还能和其他”售货机”互动。不过,千万别把它想得太聪明,它还是需要我们这些人类来精心设计和小心使用的!

如何写一个简单的智能合约

教程我是按照廖雪峰老师的教程,自己的操作了,写了一个vote投票的合约。

1. 首先申请测试网的Ether

部署合约也是一个交易,需要一个外部账户,花费一定的Gas,就可以把合约部署到链上。

测试环境不能用在真金白银, 就用测试环境的。

如何申请? 我是申请的这个网络的Ether。SepoliaETH

以太坊有多个测试网,开发前请在Etherscan确认使用哪个活动的测试网。

有些钱包不支持,比如我的okx的就不行,用的metamask。

https://faucets.chain.link/sepolia

alt text

alt text

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,这里选择钱包。 alt text

时间戳:设置为如图。

alt text

点击 transact。

alt text

部署好之后,链上就可以看到了。

交易tx的信息。从to里面可以看到一个contract的地址。和这个就是合约地址。 https://sepolia.etherscan.io/tx/0x98bd4157fefbd11bbb70cf808ddcd9fb7a031069f8581d080556883d7bd91c48

合约: https://sepolia.etherscan.io/address/0xd139e60592f4d7fd7177edd9f4d49a9f67608617

alt text

可以查看历史,钱包里面的活动页面,可以看到历史的。点开就可以看到了 alt text

3. 调用和这个合约

调用之前,需要publish,发布的网址也是需要加一个二级域名的标识。

我用的测试网络对应的是:verifyContract

按照提示,添加一些field即可。

alt text

提交之后,这个合约的:sepolia.etherscan

这里contract有一个confirm的标识,绿色勾勾。 alt text

访问合约的只读函数时,无需消耗Gas,也无需连接钱包,直接切换到“Read”面板,即可看到只读函数的返回值。

最后一个voted,输入地址,query。

alt text

4. 写入合约

当我们要写入合约时,就必须提交一个签名的交易,并消耗一定的Gas。我们在Etherscan的合约页选择“Write”,会出现一个“Connect to Web3”的链接。

alt text

然后查看交易链接: sepolia.etherscan

然后查看,这个地方的值就被修改为1.

alt text

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/