As the error states, .add()
on line 94 is not defined anywhere.
You'll have other errors for .sub()
on lines 106 and 112.
You have included safeAdd()
and safeSub()
, so you will need to use those.
Edit:
Your safe maths functions have no return statements.
Edit#2:
For the sake of time, this compiles:
pragma solidity ^0.5.0;
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
//
// ----------------------------------------------------------------------------
contract IBEP20 {
function totalSupply() public view returns (uint);
function balanceOf(address tokenOwner) public view returns (uint balance);
function allowance(address tokenOwner, address spender) public view returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
// ----------------------------------------------------------------------------
// Safe Math Library
// ----------------------------------------------------------------------------
contract SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
if (a == 0) {
return 0;
}
c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
}
contract MONK is IBEP20, SafeMath {
string public name;
string public symbol;
uint8 public decimals; // 18 decimals is the strongly suggested default, avoid changing it
uint256 public _totalSupply;
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;
/**
* Constrctor function
*
* Initializes contract with initial supply tokens to the creator of the contract
*/
constructor() public {
name = "MY";
symbol = "My";
decimals = 18;
_totalSupply = 1000000000;
balances[msg.sender] = _totalSupply;
emit Transfer(address(0), msg.sender, _totalSupply);
}
function totalSupply() public view returns (uint) {
return _totalSupply - balances[address(0)];
}
function balanceOf(address tokenOwner) public view returns (uint balance) {
return balances[tokenOwner];
}
function allowance(address tokenOwner, address spender) public view returns (uint remaining) {
return allowed[tokenOwner][spender];
}
function approve(address spender, uint tokens) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
function transfer(address to, uint tokens) public returns (bool success) {
balances[msg.sender] = sub(balances[msg.sender], tokens);
balances[to] = add(balances[to], tokens);
emit Transfer(msg.sender, to, tokens);
return true;
}
function transferFrom(address from, address to, uint tokens) public returns (bool success) {
balances[from] = sub(balances[from], tokens);
allowed[from][msg.sender] = sub(allowed[from][msg.sender], tokens);
balances[to] = add(balances[to], tokens);
emit Transfer(from, to, tokens);
return true;
}
function _mint(address account, uint256 amount) internal {
require(amount != 0);
balances[account] = add(balances[account], amount);
emit Transfer(address(0), account, amount);
}
function burn(uint256 amount) external {
_burn(msg.sender, amount);
}
function _burn(address account, uint256 amount) internal {
require(amount != 0);
require(amount <= balances[account]);
_totalSupply = sub(_totalSupply, amount);
balances[account] = sub(balances[account], amount);
emit Transfer(account, address(0), amount);
}
function burnFrom(address account, uint256 amount) external {
require(amount <= allowed[account][msg.sender]);
allowed[account][msg.sender] = sub(allowed[account][msg.sender], amount);
_burn(account, amount);
}
}
Proper approach to the unit testing is test contract with external calls, in this way you can see the call parameters and return values then decide what structure you should be using. If you want to test internal/private functions, make them public just for unit testing, after verifying your code make them internal/private. I think you'll create confusion for yourself when inheriting your tester code from your tested code, it'll be hard to maintain in future. I'm not speaking just for Solidity, but this holds for other languages too.
I have tried to recreate your scenario below
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
// TESTED Contract
contract Bet{
// For convenience
event Hello(
address acc0, address acc1, address acc2,
address acc3,address acc4, address acc5);
constructor(
address acc0,
address acc1,
address acc2,
address acc3,
address acc4,
address acc5
) payable {
emit Hello(acc0, acc1, acc2, acc3, acc4,acc5);
}
function totalSupply() public pure returns (uint256)
{
return 250000000 * 10 ** 8;
}
}
The tester contract is:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.9.0;
// This import is automatically injected by Remix
import "remix_tests.sol";
// This import is required to use custom transaction context
// Although it may fail compilation in 'Solidity Compiler' plugin
// But it will work fine in 'Solidity Unit Testing' plugin
import "remix_accounts.sol";
import "./Bet.sol";
// File name has to end with '_test.sol', this file can contain more than one testSuite contracts
contract testSuite {
// Instance of the tested contract
Bet bet = new Bet( 0x92154D3Ca6b7E34aC0F824c42a7cC18A495cabaB,
0x92154D3Ca6b7E34aC0F824c42a7cC18A495cabaB,
0x92154D3Ca6b7E34aC0F824c42a7cC18A495cabaB,
0x92154D3Ca6b7E34aC0F824c42a7cC18A495cabaB,
0x92154D3Ca6b7E34aC0F824c42a7cC18A495cabaB,
0x92154D3Ca6b7E34aC0F824c42a7cC18A495cabaB
);
function beforeAll() public {
Assert.equal(bet.totalSupply(), 250000000 * 10 ** 8, "Total supply should be 250 million");
}
function checkFailure() public {
Assert.notEqual(bet.totalSupply(), 250000000 * 10 ** 7, "Total supply should not be 250 thousand");
}
}
Best Answer
This will allow you to call
decimals
on every token which implements this method (either explicitly, or implicitly as a public variable):Be aware that
decimals
is primarily designated for off-chain use (typically in order to achieve nicer display of huge values).Using it on-chain is rather unorthodox, so you might wanna consider that very carefully (i.e., think about your goal, and ask yourself why you need to use this value in order to achieve that goal).