千家信息网

如何使用Hyperledger Fabric开发ERC20标准的代币

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,这篇文章给大家分享的是有关如何使用Hyperledger Fabric开发ERC20标准的代币的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。用Hyperledger Fab
千家信息网最后更新 2025年01月23日如何使用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标准的代币"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

0