Тестирую контракт нужна помощь, вот сам контракт:
pragma solidity ^0.4.11;
import "./SafeMath.sol";
/**
* IssueID 8
*/
contract ERC20Basic {
uint256 public totalSupply;
function balanceOf(address who) constant returns (uint256);
function transfer(address to, uint256 value) returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
contract ERC20 is ERC20Basic {
function allowance(address owner, address spender) constant returns (uint256);
function transferFrom(address from, address to, uint256 value) returns (bool);
function approve(address spender, uint256 value) returns (bool);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract BasicToken is ERC20Basic {
using SafeMath for uint256;
mapping(address => uint256) balances;
/**
* @dev transfer token for a specified address
* @param _to The address to transfer to.
* @param _value The amount to be transferred.
*/
function transfer(address _to, uint256 _value) returns (bool) {
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value);
return true;
}
/**
* @dev Gets the balance of the specified address.
* @param _owner The address to query the the balance of.
* @return An uint256 representing the amount owned by the passed address.
*/
function balanceOf(address _owner) constant returns (uint256 balance) {
return balances[_owner];
}
}
contract StandardToken is ERC20, BasicToken {
string public standard;
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
function StandardToken( uint256 initialSupply, string _standard, string _name, string _symbol, uint8 _decimals ){
totalSupply = initialSupply;
standard = _standard;
name = _name;
symbol = _symbol;
decimals = _decimals;
balances[msg.sender] = initialSupply;
}
mapping (address => mapping (address => uint256)) allowed;
/**
* @dev Transfer tokens from one address to another
* @param _from address The address which you want to send tokens from
* @param _to address The address which you want to transfer to
* @param _value uint256 the amout of tokens to be transfered
*/
function transferFrom(address _from, address _to, uint256 _value) returns (bool) {
var _allowance = allowed[_from][msg.sender];
// Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
// require (_value <= _allowance);
balances[_to] = balances[_to].add(_value);
balances[_from] = balances[_from].sub(_value);
allowed[_from][msg.sender] = _allowance.sub(_value);
Transfer(_from, _to, _value);
return true;
}
/**
* @dev Aprove the passed address to spend the specified amount of tokens on behalf of msg.sender.
* @param _spender The address which will spend the funds.
* @param _value The amount of tokens to be spent.
*/
function approve(address _spender, uint256 _value) returns (bool) {
// To change the approve amount you first have to reduce the addresses`
// allowance to zero by calling `approve(_spender, 0)` if it is not
// already 0 to mitigate the race condition described here:
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
require((_value == 0) || (allowed[msg.sender][_spender] == 0));
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param _owner address The address which owns the funds.
* @param _spender address The address which will spend the funds.
* @return A uint256 specifing the amount of tokens still available for the spender.
*/
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
}
contract HelpCoin is StandardToken {
string public _standard = "ERC20";
string public _name = "HelpCoin";
string public _symbol = "HLP";
uint8 public _decimail = 8;
uint256 public _initialSupply;
uint256[] public _id;
address[] public FirstOwner;
address public ComissionAccount;
event Commission(address indexed _to, uint256[] _id);
event Debug(uint256 value);
//event CalculateOut(uint256 amount);
function HelpCoin( uint256 _initialSupply ) StandardToken(_initialSupply,_standard,_name,_symbol,_decimail){}
function mintToken(address target, uint256 mintedAmount) {
// setFirstOwner(target);
balances[target] = balances[target].add(mintedAmount);
totalSupply = totalSupply.add(mintedAmount);
Transfer(0, this, mintedAmount);
Transfer(this, target, mintedAmount);
}
function transfer(address _to, uint256 _value) returns (bool) {
if (balances[msg.sender] < _value) { return false; }
uint256 comiss = _value.div(100).mul(3);
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[ComissionAccount] = balances[ComissionAccount].add(comiss);
balances[_to] = balances[_to].add(_value.sub(comiss));
Transfer(msg.sender, _to, _value);
Commission(ComissionAccount, _id);
return true;
}
function setCommissionAccount(address _CommissionAccount) {
ComissionAccount = _CommissionAccount;
}
// function setFirstOwner(address target) {
// FirstOwner = target;
// }
}
Тестируется в частности функция transfer , она должна отчислять при переводе 3% на отдельный счет (контракт):
function transfer(address _to, uint256 _value) returns (bool) {
if (balances[msg.sender] < _value) { return false; }
uint256 comiss = _value.div(100).mul(3);
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[ComissionAccount] = balances[ComissionAccount].add(comiss);
balances[_to] = balances[_to].add(_value.sub(comiss));
Transfer(msg.sender, _to, _value);
Commission(ComissionAccount, _id);
return true;
}
Вот тест которым я это дело тестирую:
var HelpCoin = artifacts.require("HelpCoin");
contract('HelpCoin', function(accounts) {
var hlp;
it("Deploy contract", function(done) {
var totalSupple = 100000000000;
HelpCoin.deployed(totalSupple).then(function(instance){
hlp = instance;
assert.isOk(hlp);
message = "Deployed address :" + hlp.address;
console.log(message);
done();
})
})
it("Перевод токенов с отчислением коммиссии", function(done){
var main_acc = accounts[0];
var target_acc = accounts[1];
var commiss_acc = accounts[2];
var main_bal_s;
var main_bal_e;
var target_bal_s;
var target_bal_e;
var commiss_bal_s;
var commiss_bal_e;
var ammount;
var commiss;
var message;
hlp.setCommissionAccount(commiss_acc).then(function(){
return hlp.balanceOf.call(main_acc);
}).then(function(bal){
main_bal_s = bal.toNumber();
message = "Start balance main account: " + main_bal_s + " HLP";
console.log(message);
return hlp.balanceOf.call(target_acc);
}).then(function(bal){
target_bal_s = bal.toNumber();
message = "Start balance target account: " + target_bal_s + " HLP";
console.log(message);
return hlp.balanceOf.call(commiss_acc);
}).then(function(bal){
commiss_bal_s = bal.toNumber();
message = "Start balance commiss account: " + commiss_bal_s + " HLP";
console.log(message);
ammount = 100;
message = "Transfer " + ammount + " HLP with 3% commission";
console.log(message);
return hlp.transfer(target_acc,ammount);
}).then(function(res){
message = "GasUsed for this transaction: " + res.receipt.gasUsed;
console.log(message);
return hlp.balanceOf.call(commiss_acc);
}).then(function(bal){
commiss_bal_e = bal.toNumber();
commiss = bal.toNumber();
message = "The commssion comprised: " + commiss + " HLP";
console.log(message);
return hlp.balanceOf.call(main_acc);
}).then(function(bal){
main_bal_e = bal.toNumber();
message = "End balance main account: " + main_bal_e + " HLP";
console.log(message);
return hlp.balanceOf.call(target_acc);
}).then(function(bal){
target_bal_e = bal.toNumber();
message = "End balance target account: " + target_bal_e + " HLP";
console.log(message);
message = "End balance commiss account: " + commiss_bal_e + " HLP";
console.log(message);
assert.equal(main_bal_e,main_bal_s - ammount,"Токены не переведены с главного аккаунта");
assert.equal(target_bal_e,target_bal_s + ammount - commiss,"Токены не переведены на принмающий аккаунт");
assert.equal(commiss_bal_e,target_bal_s + commiss,"Коммиссия не переведена");
done();
})
})
})
Согласно теста мы инициализируем 1000 HLP (100000000000 в минмальных единицах) и размещаем их на главном аккаунте, а потом переводим 100 HLP , результат теста:
root@helpcoin:/home/projects/HelpCoin/Testing# truffle test
Using network 'development'.
Compiling ./contracts/HelpCoin.sol...
Compiling ./contracts/SafeMath.sol...
Contract: HelpCoin
Deployed address :0x1b92206f541de5b49a4e7914b0f4454d5ad78078
✓ Deploy contract
Start balance main account: 1000 HLP
Start balance target account: 0 HLP
Start balance commiss account: 0 HLP
Transfer 100 HLP with 3% commission
GasUsed for this transaction: 73839
The commssion comprised: 3 HLP
End balance main account: 900 HLP
End balance target account: 97 HLP
End balance commiss account: 3 HLP
✓ Перевод токенов с отчислением коммиссии (330ms)
2 passing (371ms)
root@helpcoin:/home/projects/HelpCoin/Testing#
Как видно все отработало как надо, и судя из теста функция работает не с минимальными единицами, та как переместилось 100 HLP, но вот если мы уменьшим пересылаемое количество токенов до 10 то получаем проблему:
root@helpcoin:/home/projects/HelpCoin/Testing# truffle test
Using network 'development'.
Compiling ./contracts/HelpCoin.sol...
Compiling ./contracts/SafeMath.sol...
Contract: HelpCoin
Deployed address :0xdb1934157218b2d927135261d72346d17d64c7af
✓ Deploy contract
Start balance main account: 1000 HLP
Start balance target account: 0 HLP
Start balance commiss account: 0 HLP
Transfer 10 HLP with 3% commission
GasUsed for this transaction: 58797
The commssion comprised: 0 HLP
End balance main account: 990 HLP
End balance target account: 10 HLP
End balance commiss account: 0 HLP
✓ Перевод токенов с отчислением коммиссии (353ms)
2 passing (388ms)
root@helpcoin:/home/projects/HelpCoin/Testing#
Как видим трансфер токенов прошел успешно, но комиссия не расчиталась из-за того что в HLP она составляет (0.3 HLP) и по сути мы можем её отнять та как имеем 8 нулей в нашем токене, но перерыл всю документацию и та и не понял как же это сделать? Может очевидного не вижу... Помогите пожалуйста