Solidity
如何在松露測試中使用大數字?
我正在使用 Truffle V5 測試智能合約。如果我不使用所有小數,一切都會很好。如果我設置 18 位小數,所有這些都會爆炸。測試程式碼是這樣的(來自 truffle docs):
const MetaCoin = artifacts.require("MetaCoin"); contract("2nd MetaCoin test", async accounts => { it("should put 10000 MetaCoin in the first account", async () => { let instance = await MetaCoin.deployed(); let balance = await instance.getBalance.call(accounts[0]); assert.equal(balance.valueOf(), 10000); }); it("should call a function that depends on a linked library", async () => { let meta = await MetaCoin.deployed(); let outCoinBalance = await meta.getBalance.call(accounts[0]); let metaCoinBalance = outCoinBalance.toNumber(); let outCoinBalanceEth = await meta.getBalanceInEth.call(accounts[0]); let metaCoinEthBalance = outCoinBalanceEth.toNumber(); assert.equal(metaCoinEthBalance, 2 * metaCoinBalance); }); it("should send coin correctly", async () => { // Get initial balances of first and second account. let account_one = accounts[0]; let account_two = accounts[1]; let amount = 10; let instance = await MetaCoin.deployed(); let meta = instance; let balance = await meta.getBalance.call(account_one); let account_one_starting_balance = balance.toNumber(); balance = await meta.getBalance.call(account_two); let account_two_starting_balance = balance.toNumber(); await meta.sendCoin(account_two, amount, { from: account_one }); balance = await meta.getBalance.call(account_one); let account_one_ending_balance = balance.toNumber(); balance = await meta.getBalance.call(account_two); let account_two_ending_balance = balance.toNumber(); assert.equal( account_one_ending_balance, account_one_starting_balance - amount, "Amount wasn't correctly taken from the sender" ); assert.equal( account_two_ending_balance, account_two_starting_balance + amount, "Amount wasn't correctly sent to the receiver" ); }); });
這是我需要測試的智能合約(來自 MetaCoin.sol 文件,為了使用最新的編譯器而修改(目前我使用 0.5.2)等等)。原文可以在這裡找到:
pragma solidity >=0.4.25 <0.6.0; import "./ConvertLib.sol"; // This is just a simple example of a coin-like contract. // It is not standards compatible and cannot be expected to talk to other // coin/token contracts. If you want to create a standards-compliant // token, see: https://github.com/ConsenSys/Tokens. Cheers! contract MetaCoin { // I add this section in EIP20 style string public symbol; string public name; uint8 public decimals; uint _totalSupply mapping (address => uint) balances; event Transfer(address indexed _from, address indexed _to, uint256 _value); constructor() public { // I modified constructor to introduce symbol, name, decimals and totalSupply symbol = "MTC"; name = "MetaCoin Example Token"; decimals = 18; _totalSupply = 10000 * 10**uint(decimals); balances[tx.origin] = _totalSupply; } function sendCoin(address receiver, uint amount) public returns(bool sufficient) { if (balances[msg.sender] < amount) return false; balances[msg.sender] -= amount; balances[receiver] += amount; emit Transfer(msg.sender, receiver, amount); return true; } function getBalanceInEth(address addr) public view returns(uint){ return ConvertLib.convert(getBalance(addr),2); } function getBalance(address addr) public view returns(uint) { return balances[addr]; } }
如果小數是,一切都可以,例如“1”或“2”,但是當我使用“18”時,我失去了控制。如何在 javascript 測試中實現 bignumbers 處理?我試過了,但它不起作用。
由於 所施加的限制
Number.MAX_SAFE_INTEGER
,請盡量遵守以下規則:規則1:
避免使用
toNumber()
從返回值類型為以下之一的合約函式返回的任何值:
uint64
uint128
uint256
這也適用於公共變數(因為編譯器會為它們生成隱式 getter 函式)。
規則#2:
保持返回值的原始類型(
BigNumber
在 Truffle 4.x / web3 0.x上,BN
在 Truffle 5.x / web3 1.x 上),並且只使用這種類型的函式(例如,plus
、minus
、mul
、div
、equals
等)。規則#3:
對於列印輸出,最好不要使用
toFixed()
,以避免由於科學記數法(例如123.456e78
)而導致精度損失。請注意,規則 #1 也適用於返回
address
值的鏈上函式(string
在鏈外端轉換為)。