to be
a problem slover

solidity function to method id

Give any solidity function like transfer(address to, uint256 value) returns(bool) convert it to 0xa9059cbb .

In golang:

func fnToSig(fn string) (string, error) {
    f, err := toNormalized(fn)
    if err != nil {
        return "", err
    }
    hash := sha3.NewLegacyKeccak256()
    hash.Write([]byte(f))
    sig := "0x" + fmt.Sprintf("%x\n", hash.Sum(nil))[:8]
    return sig, nil
}

/*
transfer(address to, uint256 value) returns(bool)
transfer(address to, uint256 value)
transfer(address to, uint256 amt)
transfer(address to, uint value)
transfer(address , uint256)

should convert to:
transfer(address,uint256)

step1: truncate the char after the first ')'
step2: get the string inside the (), for example: str := "address to, uint256 value"
step3: split the string by ',' and trim the space in prefix & suffix, for example: params = ["address to", "uint256 value"]
step4: split the params by ' ' and delete all spaces, for example: param0 = ["address", "to"], param1 = ["uint256", "value"]
step5: replace uint to uint256, for example: ["address", "uint"] -> ["address", "uint256"]
step6: join the params by ',' and add '(', ')', for example: ["address", "uint256"] -> "(address,uint256)"
step7: return transfer(address,uint256)
*/
func toNormalized(fn string) (string, error) {
    fnName := fn[:strings.Index(fn, "(")]
    // step1: truncate the char after the first ')'
    fn = fn[:strings.Index(fn, ")")+1]
    // step2: get the string inside the ()
    originParams := fn[strings.Index(fn, "(")+1 : strings.Index(fn, ")")]
    // step3: split the string by ',' and trim the space in prefix & suffix
    paramSlice := strings.Split(originParams, ",")
    paramTypes := make([]string, 0)
    for i, param := range paramSlice {
        paramSlice[i] = strings.TrimSpace(param)
        // step4: split the originParams by ' ', get the variable type
        typ := strings.Split(paramSlice[i], " ")[0]
        // step5: replace uint to uint256
        if typ == "uint" {
            typ = "uint256"
        }
        paramTypes = append(paramTypes, typ)
    }
    // step6: rejoin the params by ','
    normalized := fmt.Sprintf("%s(%s)", fnName, strings.Join(paramTypes, ","))
    return normalized, nil
}

It’s interesting that solidity can return it’s selector by itself(refer https://etherscan.io/address/0xef1c6e67703c7bd7107eed8303fbe6ec2554bf6b#code Callbacks.sol).

    function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata)
        external
        pure
        returns (bytes4)
    {
        return this.onERC1155BatchReceived.selector;
    }
赞(4) 打赏
欢迎转载,注明出处:刘世明的博客 » solidity function to method id

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下作者

支付宝扫一扫打赏

微信扫一扫打赏