如何使用Hyperledger Fabric开发ERC20标准的代币
发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,这篇文章给大家分享的是有关如何使用Hyperledger Fabric开发ERC20标准的代币的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。用Hyperledger Fab
千家信息网最后更新 2025年12月01日如何使用Hyperledger Fabric开发ERC20标准的代币
这篇文章给大家分享的是有关如何使用Hyperledger Fabric开发ERC20标准的代币的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
用Hyperledger Fabric开发ERC20标准的代币
利用ca身份用户名作为代币地址(通过stub.GetCreator获取)
实现ERC20的标准的所有方法
直接上chaincode源码
package mainimport ( "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" "encoding/json" "bytes" "encoding/pem" "crypto/x509")const ( TokenId = "MyToken" TokenOwner = TokenId + "-Owner" TokenBalance = TokenId + "-%s-Balance" TokenFreeze = TokenId + "-%s-Freeze" TokenApprove = TokenId + "-%s-Approve-%s")type TokenChaincode struct {}type ERC20Token struct { Name string `json:"name"` //名称 Symbol string `json:"symbol"` //符号 Decimals uint8 `json:"decimals"` //小数位 TotalSupply float64 `json:"totalSupply"` //总数}func (t *TokenChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { fcn, args := stub.GetFunctionAndParameters() fmt.Printf("方法: %s 参数 : %s \n", fcn, args) if len(args) != 1 { return shim.Error("参数个数不是1") } tokenBts := []byte(args[0]) var token ERC20Token err := json.Unmarshal(tokenBts, &token) if err != nil { return shim.Error(err.Error()) } //检查 err = checkToken(token) if err != nil { return shim.Error(err.Error()) } //添加代币 err = stub.PutState(TokenId, tokenBts) if err != nil { return shim.Error(err.Error()) } //创建人 creator := initiator(stub) err = stub.PutState(TokenOwner, []byte(creator)) if err != nil { return shim.Error(err.Error()) } //拥有者初始化拥有所有代币 err = stub.PutState(balanceKey(creator), parseDecimals(token.Decimals, token.TotalSupply)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil)}func (t *TokenChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { //获取要调用的方法名和方法参数 fn, args := stub.GetFunctionAndParameters() fmt.Printf("方法: %s 参数 : %s \n", fn, args) if fn == "tokenInfo" { return t.tokenInfo(stub) } else if fn == "balanceOf" { return t.balanceOf(stub, args) } else if fn == "minter" { return t.minter(stub, args) } else if fn == "transfer" { return t.transfer(stub, args) } else if fn == "freezeAccount" { return t.freezeAccount(stub, args) } else if fn == "approve" { return t.approve(stub, args) } else if fn == "transferFrom" { return t.transferFrom(stub, args) } else if fn == "allowance" { return t.allowance(stub, args) } else if fn == "transferOwner" { return t.transferOwner(stub, args) } else if fn == "increaseAllowance" { return t.increaseAllowance(stub, args) } else if fn == "decreaseAllowance" { return t.decreaseAllowance(stub, args) } else if fn == "burn" { return t.burn(stub, args) } return shim.Error("方法不存在")}//获取token信息func (t *TokenChaincode) tokenInfo(stub shim.ChaincodeStubInterface) pb.Response { token, err := stub.GetState(TokenId) if err != nil { return shim.Error(err.Error()) } return shim.Success(token)}//输入地址,可以获取该地址代币的余额func (t *TokenChaincode) balanceOf(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("参数个数不为1") } name := args[0] balance, err := stub.GetState(balanceKey(name)) if err != nil { return shim.Error(err.Error()) } return shim.Success(balance)}//挖矿func (t *TokenChaincode) minter(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("参数个数不为2") } to := args[0] v, err := strconv.ParseFloat(args[1], 64) //v不能小于零 if v < 0 { return shim.Error("v less than 0") } //检查是否是创建人 err = checkOwner(stub) if err != nil { return shim.Error(err.Error()) } //获取to的balance a, err := getBalance(stub, to) if err != nil { return shim.Error(err.Error()) } a += v if a < 0 { return shim.Error("a balance less than 0") } //代币总数增加 tks, err := stub.GetState(TokenId) if err != nil { return shim.Error(err.Error()) } var token ERC20Token err = json.Unmarshal(tks, &token) if err != nil { return shim.Error(err.Error()) } token.TotalSupply += v tks, err = json.Marshal(token) if err != nil { return shim.Error(err.Error()) } //跟新代币 err = stub.PutState(TokenId, tks) if err != nil { return shim.Error(err.Error()) } // 重新写回账本 err = stub.PutState(balanceKey(to), parseDecimals(token.Decimals, a)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil)}//调用transfer函数将自己的token转账给to地址,value为转账个数func (t *TokenChaincode) transfer(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("参数个数不为2") } //to to := args[0] //交易数量 val := args[1] //from from := initiator(stub) //保留获取小数位 decimals, err := getDecimals(stub) if err != nil { return shim.Error(err.Error()) } //交易 err = deal(stub, from, to, val, decimals) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil)}//实现账户的冻结和解冻 (true 冻结,false 解冻)func (t *TokenChaincode) freezeAccount(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("参数个数不为2") } to := args[0] isFreeze := args[1] if isFreeze != "true" && isFreeze != "false" { return shim.Error("isFreeze is true or false") } //检查是否是创建人 err := checkOwner(stub) if err != nil { return shim.Error(err.Error()) } //账户冻结和解冻 err = stub.PutState(freezeKey(to), []byte(isFreeze)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil)}//转移拥有者func (t *TokenChaincode) transferOwner(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("参数个数不为1") } toOwner := args[0] //检查是否是创建人 err := checkOwner(stub) if err != nil { return shim.Error(err.Error()) } //改变owner err = stub.PutState(TokenOwner, []byte(toOwner)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil)}//批准spender账户从自己的账户转移value个token。可以分多次转移func (t *TokenChaincode) approve(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { return shim.Error("参数个数不为2") } //授权人 spender := args[0] val := args[1] _, err := strconv.ParseFloat(val, 64) if err != nil { return shim.Error("Invalid transaction amount") } //发起人 sponsor := initiator(stub) //批准 err = stub.PutState(approveKey(sponsor, spender), []byte(val)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil)}//与approve搭配使用,approve批准之后,调用transferFrom函数来转移token。func (t *TokenChaincode) transferFrom(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 3 { return shim.Error("参数个数不为3") } //from sponsor := args[0] //to to := args[1] //val val := args[2] valf, err := strconv.ParseFloat(val, 64) if err != nil { return shim.Error("Invalid transaction amount") } //spender spender := initiator(stub) //授权数量 v, err := getApprove(stub, sponsor, spender) if err != nil { return shim.Error(err.Error()) } //超出授权 if valf > v { return shim.Error("approve not enough") } //保留获取小数位 decimals, err := getDecimals(stub) if err != nil { return shim.Error(err.Error()) } //交易 err = deal(stub, sponsor, to, val, decimals) if err != nil { return shim.Error(err.Error()) } //计算approve剩余 v -= valf //跟新授权数量 err = stub.PutState(approveKey(sponsor, spender), parseDecimals(decimals, v)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil)}//返回spender还能提取sponsor的token的个数func (t *TokenChaincode) allowance(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("参数个数不为1") } //批准人 sponsor := args[0] //发起人 spender := initiator(stub) val, err := stub.GetState(approveKey(sponsor, spender)) if err != nil { return shim.Error(err.Error()) } return shim.Success(val)}//增加spender账户从自己的账户转移value个token。可以分多次转移func (t *TokenChaincode) increaseAllowance(stub shim.ChaincodeStubInterface, args []string) pb.Response { return changeAllowance(stub, args, "+")}//减少spender账户从自己的账户转移value个token。可以分多次转移func (t *TokenChaincode) decreaseAllowance(stub shim.ChaincodeStubInterface, args []string) pb.Response { return changeAllowance(stub, args, "-")}//改变spender账户从自己的账户转移value个token。可以分多次转移func changeAllowance(stub shim.ChaincodeStubInterface, args []string, operation string) pb.Response { if len(args) != 2 { return shim.Error("参数个数不为2") } //授权人 spender := args[0] v, err := strconv.ParseFloat(args[1], 64) if err != nil { return shim.Error("Invalid transaction amount") } //v不能小于零 if v < 0 { return shim.Error("v less than 0") } //发起人 sponsor := initiator(stub) //获取当前allowanceval, err := stub.GetState(approveKey(sponsor, spender)) if err != nil { return shim.Error(err.Error()) } a, err := strconv.ParseFloat(string(val), 64) if err != nil { return shim.Error(err.Error()) } if operation == "+" { //增加 a += v } if operation == "-" { //减少 a -= v } //不能溢出 if a < 0 { return shim.Error("a less than 0") } decimals, err := getDecimals(stub) if err != nil { return shim.Error(err.Error()) } //批准 err = stub.PutState(approveKey(sponsor, spender), parseDecimals(decimals, a)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil)}//销毁代币func (t *TokenChaincode) burn(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("参数个数不为1") } v, err := strconv.ParseFloat(args[0], 64) //v不能小于零 if v < 0 { return shim.Error("v less than 0") } from := initiator(stub) //获取from的balance a, err := getBalance(stub, from) if err != nil { return shim.Error(err.Error()) } a -= v if a < 0 { return shim.Error("a balance less than 0") } //代币总数减少 tks, err := stub.GetState(TokenId) if err != nil { return shim.Error(err.Error()) } var token ERC20Token err = json.Unmarshal(tks, &token) if err != nil { return shim.Error(err.Error()) } token.TotalSupply -= v tks, err = json.Marshal(token) if err != nil { return shim.Error(err.Error()) } //跟新代币 err = stub.PutState(TokenId, tks) if err != nil { return shim.Error(err.Error()) } // 重新写回账本 err = stub.PutState(balanceKey(from), parseDecimals(token.Decimals, a)) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil)}//交易处理 from to val decimalsfunc deal(stub shim.ChaincodeStubInterface, from, to, val string, decimals uint8) (error) { v, err := strconv.ParseFloat(val, 64) if err != nil { return err } //v不能小于零 if v < 0 { return fmt.Errorf("v less than 0") } //获取from的balance a, err := getBalance(stub, from) if err != nil { return err } //判断两个帐号不能相同 if from == to { return fmt.Errorf("from and to is the same address") } //获取to的balance b, err := getBalance(stub, to) if err != nil { return err } //execution a b v 交易 a -= v if a < 0 { return fmt.Errorf("from balance not enough") } b += v if b < 0 { return fmt.Errorf("to balance less than 0") } fmt.Println(" a: ", a, " b: ", b) // 重新写回账本 err = stub.PutState(balanceKey(from), parseDecimals(decimals, a)) if err != nil { return err } err = stub.PutState(balanceKey(to), parseDecimals(decimals, b)) if err != nil { return err } return nil}//获取批准数量func getApprove(stub shim.ChaincodeStubInterface, sponsor, spender string) (float64, error) { //批准数量 val, err := stub.GetState(approveKey(sponsor, spender)) if err != nil { return 0, err } b, err := strconv.ParseFloat(string(val), 64) if err != nil { return 0, err } return b, nil}//获取balancefunc getBalance(stub shim.ChaincodeStubInterface, addr string) (float64, error) { //检查帐号是否冻结 isFreeze, err := stub.GetState(freezeKey(addr)) if err != nil { return 0, err } if isFreeze != nil && bytes.Equal(isFreeze, []byte("true")) { return 0, fmt.Errorf("addr is freeze") } //查询balance addrVal, err := stub.GetState(balanceKey(addr)) if err != nil { return 0, err } //为空返回0 if addrVal == nil { return 0, nil } b, err := strconv.ParseFloat(string(addrVal), 64) if err != nil { return 0, err } return b, nil}//校验创建人func checkOwner(stub shim.ChaincodeStubInterface) error { creator := initiator(stub) owner, err := stub.GetState(TokenOwner) if err != nil { return err } if !bytes.Equal([]byte(creator), owner) { return fmt.Errorf("is not owner") } return nil}//校验tokenfunc checkToken(token ERC20Token) error { if token.Name == "" { return fmt.Errorf("name不能为空") } if token.Symbol == "" { return fmt.Errorf("symbol不能为空") } if token.TotalSupply <= 0 { return fmt.Errorf("totalSupply要大于0") } return nil}//转换为token decimalsfunc parseDecimals(decimals uint8, value float64) []byte { val := strconv.FormatFloat(value, 'f', int(decimals), 64) return []byte(val)}//获取token decimalsfunc getDecimals(stub shim.ChaincodeStubInterface) (uint8, error) { tokenBts, err := stub.GetState(TokenId) if err != nil { return 0, err } var token ERC20Token err = json.Unmarshal(tokenBts, &token) if err != nil { return 0, err } return token.Decimals, nil}//交易发起人func initiator(stub shim.ChaincodeStubInterface) string { //获取当前用户 creatorByte, _ := stub.GetCreator() certStart := bytes.IndexAny(creatorByte, "-----BEGIN") if certStart == -1 { fmt.Println("No certificate found") } certText := creatorByte[certStart:] bl, _ := pem.Decode(certText) if bl == nil { fmt.Println("Could not decode the PEM structure") } cert, err := x509.ParseCertificate(bl.Bytes) if err != nil { fmt.Println("ParseCertificate failed") } name := cert.Subject.CommonName fmt.Println("initiator:" + name) return name}//封装balance keyfunc balanceKey(name string) string { return fmt.Sprintf(TokenBalance, name)}//封装freeze keyfunc freezeKey(name string) string { return fmt.Sprintf(TokenFreeze, name)}//封装approve keyfunc approveKey(from, to string) string { return fmt.Sprintf(TokenApprove, from, to)}func main() { err := shim.Start(new(TokenChaincode)) if err != nil { fmt.Printf("Error starting Token chaincode: %s", err) }}感谢各位的阅读!关于"如何使用Hyperledger Fabric开发ERC20标准的代币"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
代币
参数
个数
方法
账户
标准
交易
开发
创建人
发起人
数量
封装
检查
内容
地址
小数
小数位
总数
更多
用户
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
软件开发+无码化
广东金融软件开发公司
电脑服务器蓝屏找不到系统
大专计算机网络技术前景如何
高级网络安全师考证多少钱
如何备份ifx数据库
etl数据库设计
服务器矿车消失解决方法
pdf保存到数据库后再读取
有线电视服务器信号中断
小学网络安全的黑板报图片
pad用的数据库软件
服务器hmc管理
湖南时间同步数显钟服务器云空间
网络安全的相关说明
数据库怎么查看一张表的建表语句
网络技术案例分享
python从数据库取值
华为数据库在卫生系统的应用
数据新闻网络安全
搜索数据库和方法
双线服务器怎么合并
计算机网络技术主要课题
大专计算机网络技术前景如何
职高可以选软件开发专业吗
什么是pang网络技术
诚立网络技术有限公司
贵阳数据库培训多少钱
60数据库 邪恶使者
联想服务器的管理口地址