ERC720 开发实例
本教程是技术大牛 luofei614 的DApp开发学习笔记,编成教程分享给开发者。
ERC20代币
ERC20是以太坊流行的代币协议,ERC20名称的由来是:以太坊有个需求提案的地方叫ERC,GitHub自动分配20的编号,所以大家习惯叫ERC20
协议结构:
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
contract ERC20Interface {
//总发行量
function totalSupply() public constant returns (uint);
//账户余额
function balanceOf(address tokenOwner) public constant returns (uint balance);
//配额带支付, 一般是设置合约地址待支付的权限
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
//转账
function transfer(address to, uint tokens) public returns (bool success);
//审批, 设置合约地址的allowance配额数量
function approve(address spender, uint tokens) public returns (bool success);
//从其他账户转账,通常与approve一起用
function transferFrom(address from, address to, uint tokens) public returns (bool success);
//转账事件
event Transfer(address indexed from, address indexed to, uint tokens);
//审批事件
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
合约中实际是有两个mapping来记录余额和配合的
mapping(adress => uint256) balances; //记录地址有多少代币余额
mapping(address => mapping(address => unit256)) public allowed;//记录配额
转账有两个方法
  • transfer, 是当前用户(msg.sender) 转账给指定地址, 改变的是balances的状态结构。
  • transferFrom,是from参数地址向to参数地址转账, from不一定是msg.sender ,所以需要from地址向授权给合约地址配额, 合约地址才能实现转账。 设置配额改变的是allowed状态,这个是个二级结构,第一级的address是对应了转出账号地址(from) , 第二级的address对应的是智能合约地址,被授权的智能合约才能转账,等会儿会做个水龙头的合约作为演示。
实现合约可以借助 openzeppelin , 它已经封装好了父类, 子类继承它即可
新建一个项目:
truffle init
安装依赖:
yarn add @openzeppelin/contracts
创建合约: contracts/MTK.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MTK is ERC20 {
//发行一个币的名称叫MyToken, 简称MTK
constructor() ERC20("MyToken", "MTK") {
_mint(msg.sender, 1000);//发现总量,TODO还没有找到怎么设置小数位数
}
}
先用remix调试, 这时候因为import导入多文件, 不方便把代码复制到remix上调试。 所以要建立remix的本地服务,让remix调试本地文件
安装remixd
npm install -g @remix-project/remixd
在项目根目录下启动服务:
sudo remixd -s `pwd` --remix-ide https://remix.ethereum.org
此时在remix文件的wordspaces选择为localhost即可。
编译和部署好合约后,可以用remix界面调试合约函数:
图片
下面重点说一下用truflle console 命令行调试合约。
在migrate文件夹下建立2_MTK.js文件:
const MTK = artifacts.require("MTK");
module.exports = function (deployer) {
deployer.deploy(MTK);
};
编辑truffle-config.js 修改编译器版本为 0.8.4
编译:truffle compile , 并部署合约 truffle migrate
进入命令行:
truflle console
>MTK.address //获得部署合约地址
>let instance=await MTK.deployed() //获得合约实例
>let accounts = await web3.eth.getAccounts() //获得账户
>instance.totalSupply() //获得总发行量
>instance.balanceOf(accounts[0]) //获得账户余额
>instance.transfer(accounts[1],web3.utils.toBN(100)) //向第二个账户打100MTK
>instance.balanceOf(accounts[0]) //获得第二个账户余额
下面在说下建立MTK的水龙头合约,演示approve和transferFrom的使用。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./MTK.sol";
contract MTKFaucet {
MTK public MTKInstance;
address public MTKOwner;
constructor(MTK _MTKInstance, address _MTKOwner) {
MTKInstance=_MTKInstance;
MTKOwner=_MTKOwner;
}
function (uint withdraw_amount) public{
require(withdraw_amount<=1000);
MTKInstance.transferFrom(MTKOwner,msg.sender,withdraw_amount);
}
}
创建上面合约时需要传递已经部署好的MTK合约地址和部署账户的地址。
建立migrate/3_MTKFaucet.js文件
const MTKFaucet = artifacts.require("MTKFaucet");
const MTK = artifacts.require("MTK");//前一步MTK已经部署好,这里可以用MTK.address获得部署地址
module.exports = function (deployer,network,accounts) {
deployer.deploy(MTKFaucet,MTK.address,accounts[0]);
};
调试MTKFaucet合约:
truffle console
>let instance=await MTKFaucet.deployed()
>let accounts=await web3.eth.getAccounts();
>instance.withdraw(1,{from:accounts[1]}) //这会报错 revert ERC20: transfer amount exceeds allowance , 是因为没有分配限额
>let MTKInstance=await MTK.deployed()
>MTKInstance.approve(MTKFaucet.address,10) //对合约分配限额为10
>instance.withdraw(1,{from:accounts[1]}) //这时候管用了
>MTKFaucetInstances.withdraw(11,{from:accounts[1]}) //超过限额还会报错
代币的转账和以太坊的转账是有区别的, 太坊的转账是改变的目标地址的状态。 而代币的转账是改变的合约的状态。
大多数交易所的账号地址是合约地址, 要判断交易所合约是否支持代币,如果向不支持代币的合约转账代币, 这个代币将永远卡住取不出来。
PS: ERC721就是NFT的协议。https://docs.openzeppelin.com/contracts/4.x/erc721
Copy link