20 web3合约中token的单位与wei的关系

PancakeSwap Token (Cake) Token Tracker | BscScan

比如cake的合约,从合约中取得的余额要通过fromWei 或者toWei来换算, 也就是10^18

但是我发现某些代币,换算单位却是10^6,比如这里有个token叫DAR,合约地址是下面这个 Dalarnia (DAR) Token Tracker | BscScan

这种用什么函数来转换呢? 比如我要转账 send=20.123456,如果直接用 send*10**6,那么这个结果还是float,不能直接丢给transfer函数。 虽然可以用math.floor来处理,我猜想应该是有对应的函数的,但是看文档没有找到。

请先 登录 后评论

最佳答案 2021-11-22 09:05

使用 ethers.js 的话,有相应的函数:

ethers.utils.parseUnits() ethers.utils.formatUnits()

可以参考文档:工具包 — ethers.js 中文文档

当然也可以自己实现:

var BN = require('bn.js');

const unitMap = {
  '0': '1', // eslint-disable-line
  '1': '10', // eslint-disable-line
  '2': '100', // eslint-disable-line
  '3': '1000', // eslint-disable-line
  '4': '10000', // eslint-disable-line
  '5': '100000', // eslint-disable-line
  '6': '1000000', // eslint-disable-line
  '7': '10000000', // eslint-disable-line
  '8': '100000000', // eslint-disable-line
  '9': '1000000000', // eslint-disable-line
  '10': '10000000000', // eslint-disable-line
  '11': '100000000000', // eslint-disable-line
  '12': '1000000000000', // eslint-disable-line
  '13': '10000000000000', // eslint-disable-line
  '14': '100000000000000', // eslint-disable-line
  '15': '1000000000000000', // eslint-disable-line
  '16': '10000000000000000', // eslint-disable-line
  '17': '100000000000000000', // eslint-disable-line
  '18': '1000000000000000000' // eslint-disable-line
};
// 转化为按可视单位位数显示
export function fromDec(weiInput, decimal) {
    var wei = new BN(weiInput); // eslint-disable-line
    const base = new BN(unitMap[decimal], 10);
    const baseLength = unitMap[decimal].length - 1 || 1;

    var fraction = wei.mod(base).toString(10); // eslint-disable-line

    while (fraction.length < baseLength) {
      fraction = `0${fraction}`;
    }

    fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1];

    var whole = wei.div(base).toString(10); // eslint-disable-line
    var value = `${whole}${fraction == '0' ? '' : `.${fraction}`}`; // eslint-disable-line
    return value;
  }

  // 转化为按decimal 位数显示
  export function toDec(etherInput, decimal) {
    var ether = String(etherInput); // eslint-disable-line
    const base = new BN(unitMap[decimal], 10);
    const baseLength = unitMap[decimal].length - 1 || 1;

    // Split it into a whole and fractional part
    var comps = ether.split('.'); // eslint-disable-line
    if (comps.length > 2) { throw new Error(`[ethjs-unit] while converting number ${etherInput} to wei,  too many decimal points`); }

    var whole = comps[0], fraction = comps[1]; // eslint-disable-line

    if (!whole) { whole = '0'; }
    if (!fraction) { fraction = '0'; }
    if (fraction.length > baseLength) { throw new Error(`[ethjs-unit] while converting number ${etherInput} to wei, too many decimal places`); }

    while (fraction.length < baseLength) {
      fraction += '0';
    }

    whole = new BN(whole);
    fraction = new BN(fraction);
    var wei = (whole.mul(base)).add(fraction); // eslint-disable-line

    return new BN(wei.toString(10), 10).toString();
  }
请先 登录 后评论

其它 0 个回答

  • 1 关注
  • 0 收藏,3325 浏览
  • ETH_IS_OK 提出于 2021-11-22 05:15