区块链 - 铸币、转账实例介绍solidity

目录

一、代码

二、代码解读

三、实操

3.1编译

3.2部署

3.3给自己发10000元

3.4给小弟转7000元

3.5小弟给对象转4000元


下面讲的,是最基础、最纯净的 ERC-20 代币雏形。

几乎所有代币合约(USDT、UNI、SHIB...)都是在这个基础上加了更多功能(名字、符号、小数位、授权、黑名单等)演变来的。学完这个,就掌握了"发币 + 转账"两大核心机制!

一、代码

javascript 复制代码
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;

contract Coin {
    // 关键字 "public" 使变量可以从其他合约中访问。
    address public minter;
    mapping(address => uint) public balances;

    // 事件允许客户端对您声明的特定合约变化做出反应
    event Sent(address from, address to, uint amount);

    // 构造函数代码只有在合约创建时运行
    constructor() {
        minter = msg.sender;
    }

    // 向一个地址发送一定数量的新创建的代币
    // 但只能由合约创建者调用
    function mint(address receiver, uint amount) public {
        require(msg.sender == minter);
        balances[receiver] += amount;
    }

    // 错误类型变量允许您提供关于操作失败原因的信息。
    // 它们会返回给函数的调用者。
    error InsufficientBalance(uint requested, uint available);

    // 从任何调用者那里发送一定数量的代币到一个地址
    function send(address receiver, uint amount) public {
        if (amount > balances[msg.sender])
            revert InsufficientBalance({
                requested: amount,
                available: balances[msg.sender]
            });

        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        emit Sent(msg.sender, receiver, amount);
    }
}

二、代码解读

上面的代码实现了:

  • 只能由创建者"铸造"(凭空发币)

  • 任何人可以互相转账

  • 有余额检查、错误提示、事件通知

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.4;

^ 是 Solidity 版本锁定符号,意思是:可以使用 0.8.4 及以上的 0.8.x 版本来编译,但不能使用 0.9.0 及以上版本。

复制代码
contract Coin {

定义一个叫 Coin 的代币合约。

复制代码
    address public minter;                    // 谁部署的合约,谁就是"央行"
    mapping(address => uint) public balances; // 记录每个地址的代币余额
  • minter:记录合约创建者(只有他能发币)

  • balances:一个映射(类似 Python 的 dict),key 是地址,value 是余额,而且是 public,外部直接能查

    复制代码
      event Sent(address from, address to, uint amount);

定义一个事件叫 Sent。

每次有人转账成功,就会"发射"这个事件,前端(网页、MetaMask、ethers.js)可以监听它,实时显示"某人转了多少币给谁"。

复制代码
    constructor() {
        minter = msg.sender;   // 部署合约的那个人自动成为 minter(央行)
    }

构造函数,只在部署时运行一次,把部署者的地址设为 minter。

复制代码
    function mint(address receiver, uint amount) public {
        require(msg.sender == minter);           // 只有央行能调用!
        balances[receiver] += amount;            // 给 receiver 发 amount 个币
    }

铸币函数(央行专属)

  • 比如你部署了合约,你就是 minter

  • 你可以调用 mint("某个地址", 1000),就凭空给那个人发 1000 个币

    复制代码
      error InsufficientBalance(uint requested, uint available);

自定义错误类型(0.8.4+ 新特性,比 revert 字符串省 gas)

当余额不足时,会返回"想要转多少"和"实际只有多少"两个数字。

复制代码
    function send(address receiver, uint amount) public {
        if (amount > balances[msg.sender])
            revert InsufficientBalance({   // 余额不足就报错并回滚
                requested: amount,
                available: balances[msg.sender]
            });

        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        emit Sent(msg.sender, receiver, amount);  // 发射转账事件
    }

普通转账函数(任何人都能调用)

  1. 检查你有没有足够的币,没有就报错
  2. 扣除发送者余额
  3. 增加接收者余额
  4. 发射 Sent 事件(前端可以看到)

三、实操

打开Remix平台

3.1编译

3.2部署

3.3给自己发10000元

因为是我们自己部署的,所以自己就是央行,可以给自己印钱,爽!

复制自己的钱包地址:

左侧拉到最下面,部署的合约部分,展开,在MINT处前面复制的地址,和10000元,点击transact按钮,如下:

完成之后,在balances按钮右侧输入地址,查询余额:

发现已经增加了10000元,成功!

3.4给小弟转7000元

小弟不容易,给他转7000。我们选择账户ACCOUNT的第二个钱包,然后复制地址,再切换回去到自己的钱包(第一个),然后就可以去转账了。

我们还是拉到最下面,这回选择SEND部分,输入小弟账户地址,金额7000【金额不能超过我们自己的总金额】。(这里不要忘了切换回自己的钱包,因为只有我们有钱)

如果下面的日志是绿色✅,则说明成功。

再把小弟的地址输入到balances那边,看看是否已经到账:

发现已经到账,nice!

3.5小弟给对象转4000元

类似的,小弟对象是第三个钱包。要切换到第二个钱包给第三个转账:

原来第三个钱包是0元,第二个为7000,现在转走4000,看看结果如何:

上图可知,4000已经到账。

再看看小弟自己的余额:

还是3000,没错~

到此,基本的发币、转账功能就完成啦!

相关推荐
桧***攮2 小时前
区块链在金融中的数字货币
金融·区块链
0***R5152 小时前
Web3.0在去中心化应用中的事件监听
web3·去中心化·区块链
许强0xq2 小时前
Q19: fallback 和 receive 有什么区别?
面试·web3·区块链·solidity·以太坊·evm
9***Y483 小时前
区块链在政务中的数字档案
区块链·政务
S***q1923 小时前
区块链共识机制
区块链
6***x5453 小时前
区块链状态通道技术
区块链
D***t1313 小时前
区块链在电子发票中的防伪验证
区块链
wangchenggong19883 小时前
使用 Foundry 进行高效、可靠的测试
区块链
芒果量化6 小时前
区块链 - 智能合约入门solidity
区块链·智能合约