Skip to content

Commit

Permalink
Changing the tax behavior
Browse files Browse the repository at this point in the history
This commit changes a bit the tax behavior in order to simplify backend calculations. Now it works like Ethereum transfer GAS tax, adding the tax amount in the transfer amount.
  • Loading branch information
gabrielbiga committed Mar 3, 2019
1 parent ce53950 commit 97a3825
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 58 deletions.
12 changes: 0 additions & 12 deletions wibx/contracts/TaxLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,4 @@ library TaxLib

return value.mul(10 ** shift);
}

/**
* @dev Calculates the NET value of the transaction
*
* @param taxValue All tax value paid
* @param value The transaction value
* @return The NET price
*/
function netValue(uint256 taxValue, uint256 value) internal pure returns (uint256)
{
return value.sub(taxValue);
}
}
8 changes: 8 additions & 0 deletions wibx/contracts/Taxable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ contract Taxable is Ownable
changeTax(9, 1);
}

/**
* Returns the tax recipient account
*/
function taxRecipientAddr() public view returns (address)
{
return _taxRecipientAddr;
}

/**
* @dev Get the current tax amount.
*/
Expand Down
12 changes: 6 additions & 6 deletions wibx/contracts/WibxToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ contract WibxToken is ERC20Pausable, ERC20Detailed, Taxable, BCHHandled
/*
* Exempting the tax account to avoid an infinite loop in transferring values from this wallet.
*/
if (from == _taxRecipientAddr)
if (from == taxRecipientAddr() || to == taxRecipientAddr())
{
super.transferFrom(from, to, value);

Expand All @@ -72,10 +72,10 @@ contract WibxToken is ERC20Pausable, ERC20Detailed, Taxable, BCHHandled
uint256 taxValue = _applyTax(value);

// Transfer the tax to the recipient
super.transferFrom(from, _taxRecipientAddr, taxValue);
super.transferFrom(from, taxRecipientAddr(), taxValue);

// Transfer user's tokens
super.transferFrom(from, to, TaxLib.netValue(taxValue, value));
super.transferFrom(from, to, value);

return true;
}
Expand Down Expand Up @@ -159,7 +159,7 @@ contract WibxToken is ERC20Pausable, ERC20Detailed, Taxable, BCHHandled
/*
* Exempting the tax account to avoid an infinite loop in transferring values from this wallet.
*/
if (from == _taxRecipientAddr)
if (from == taxRecipientAddr() || to == taxRecipientAddr())
{
_transfer(from, to, value);

Expand All @@ -169,10 +169,10 @@ contract WibxToken is ERC20Pausable, ERC20Detailed, Taxable, BCHHandled
uint256 taxValue = _applyTax(value);

// Transfer the tax to the recipient
_transfer(from, _taxRecipientAddr, taxValue);
_transfer(from, taxRecipientAddr(), taxValue);

// Transfer user's tokens
_transfer(from, to, TaxLib.netValue(taxValue, value));
_transfer(from, to, value);

return true;
}
Expand Down
2 changes: 1 addition & 1 deletion wibx/contracts/WibxTokenVesting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ contract WibxTokenVesting is Ownable

if (totalWibxVestingSupply() > 0)
{
_wibxToken.transfer(owner(), totalWibxVestingSupply());
_wibxToken.transfer(_wibxToken.taxRecipientAddr(), totalWibxVestingSupply());
}

/**
Expand Down
10 changes: 5 additions & 5 deletions wibx/test/WibxToken-BCH.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const { applyTax } = require('./helpers/tax');
const expectEvent = require('./helpers/expectEvent');
const {
INITIAL_SUPPLY,
TRANSFER_TEST_AMOUNT,
ALL_TAXES_SHIFT
} = require('./helpers/constants');

Expand Down Expand Up @@ -54,9 +55,8 @@ contract('WibxToken: BCH Management', ([owner, recipient, anotherAccount, bchAdd
describe('should transfer value from a authorized BCH manipulated address', async () =>
{
const to = anotherAccount;
const amount = INITIAL_SUPPLY;
const amount = TRANSFER_TEST_AMOUNT;
const taxes = applyTax(amount, ALL_TAXES_SHIFT);
const valueWithoutTaxes = amount.sub(taxes);

beforeEach(async () =>
{
Expand All @@ -67,9 +67,9 @@ contract('WibxToken: BCH Management', ([owner, recipient, anotherAccount, bchAdd
{
await tokenInstance.transferFrom(owner, to, amount, { from: bchAddr });

(await tokenInstance.balanceOf(owner)).should.be.bignumber.equal(new BN(0));
(await tokenInstance.balanceOf(owner)).should.be.bignumber.equal(INITIAL_SUPPLY.sub(amount).sub(taxes));

(await tokenInstance.balanceOf(to)).should.be.bignumber.equal(valueWithoutTaxes);
(await tokenInstance.balanceOf(to)).should.be.bignumber.equal(amount);
});

it('emits the transfer events', async () =>
Expand All @@ -91,7 +91,7 @@ contract('WibxToken: BCH Management', ([owner, recipient, anotherAccount, bchAdd
expectEvent.inLogs(logs, 'Transfer', {
from: owner,
to: to,
value: valueWithoutTaxes
value: amount
});
});
});
Expand Down
16 changes: 8 additions & 8 deletions wibx/test/WibxToken-Batch.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const WibxToken = artifacts.require('WibxToken');
const { applyTax } = require('./helpers/tax');
const {
INITIAL_SUPPLY,
TRANSFER_TEST_AMOUNT,
ALL_TAXES_SHIFT
} = require('./helpers/constants');

Expand Down Expand Up @@ -37,7 +38,7 @@ contract('WibxToken: BCH batch transfer', ([owner, recipient, anotherAccount, bc

it('should fail with a different and unauthorized sender', async () =>
{
const halfAmount = INITIAL_SUPPLY.div(new BN(2));
const halfAmount = TRANSFER_TEST_AMOUNT;

await shouldFail.reverting(tokenInstance.sendBatch(
[recipient, anotherAccount],
Expand Down Expand Up @@ -80,12 +81,11 @@ contract('WibxToken: BCH batch transfer', ([owner, recipient, anotherAccount, bc
*/
async function transfer (from)
{
const amount = INITIAL_SUPPLY;
const amount = TRANSFER_TEST_AMOUNT;
const halfAmount = amount.div(new BN(2));
const taxes = applyTax(halfAmount, ALL_TAXES_SHIFT);
const valueWithoutTaxes = halfAmount.sub(taxes);
const taxes = applyTax(amount, ALL_TAXES_SHIFT);

(await tokenInstance.balanceOf(owner)).should.be.bignumber.equal(amount);
(await tokenInstance.balanceOf(owner)).should.be.bignumber.least(amount);

await tokenInstance.sendBatch(
[recipient, anotherAccount],
Expand All @@ -94,9 +94,9 @@ contract('WibxToken: BCH batch transfer', ([owner, recipient, anotherAccount, bc
{ from }
);

(await tokenInstance.balanceOf(owner)).should.be.bignumber.equal(new BN(0));
(await tokenInstance.balanceOf(recipient)).should.be.bignumber.equal(valueWithoutTaxes);
(await tokenInstance.balanceOf(anotherAccount)).should.be.bignumber.equal(valueWithoutTaxes);
(await tokenInstance.balanceOf(owner)).should.be.bignumber.equal(INITIAL_SUPPLY.sub(amount).sub(taxes));
(await tokenInstance.balanceOf(recipient)).should.be.bignumber.equal(halfAmount);
(await tokenInstance.balanceOf(anotherAccount)).should.be.bignumber.equal(halfAmount);
}

/**
Expand Down
21 changes: 10 additions & 11 deletions wibx/test/WibxToken-Common.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const expectEvent = require('./helpers/expectEvent');
const {
ZERO_ADDRESS,
INITIAL_SUPPLY,
TRANSFER_TEST_AMOUNT,
UNAVAILABLE_AMOUNT,
ALL_TAXES_SHIFT
} = require('./helpers/constants');
Expand Down Expand Up @@ -75,17 +76,16 @@ contract('WibxToken: Common ERC20 Functionalities', ([owner, recipient, anotherA

describe('when the sender has enough balance', () =>
{
const amount = INITIAL_SUPPLY;
const amount = TRANSFER_TEST_AMOUNT;
const taxes = applyTax(amount, ALL_TAXES_SHIFT);
const valueWithoutTaxes = amount.sub(taxes);

it('transfers the requested amount', async () =>
{
await tokenInstance.transfer(to, amount, { from: owner });

(await tokenInstance.balanceOf(owner)).should.be.bignumber.equal(new BN(0));
(await tokenInstance.balanceOf(owner)).should.be.bignumber.equal(INITIAL_SUPPLY.sub(amount).sub(taxes));

(await tokenInstance.balanceOf(to)).should.be.bignumber.equal(valueWithoutTaxes);
(await tokenInstance.balanceOf(to)).should.be.bignumber.equal(amount);
});

it('should transfer the full value from the tax recipient address', async () =>
Expand Down Expand Up @@ -123,7 +123,7 @@ contract('WibxToken: Common ERC20 Functionalities', ([owner, recipient, anotherA
expectEvent.inLogs(logs, 'Transfer', {
from: owner,
to: to,
value: valueWithoutTaxes
value: amount
});
});
});
Expand Down Expand Up @@ -258,24 +258,23 @@ contract('WibxToken: Common ERC20 Functionalities', ([owner, recipient, anotherA

describe('when the owner has enough balance', () =>
{
const amount = INITIAL_SUPPLY;
const amount = TRANSFER_TEST_AMOUNT;
const taxes = applyTax(amount, ALL_TAXES_SHIFT);
const valueWithoutTaxes = amount.sub(taxes);

it('transfers the requested amount', async () =>
{
await tokenInstance.transferFrom(owner, to, amount, { from: spender });

(await tokenInstance.balanceOf(owner)).should.be.bignumber.equal(new BN(0));
(await tokenInstance.balanceOf(owner)).should.be.bignumber.equal(INITIAL_SUPPLY.sub(amount).sub(taxes));

(await tokenInstance.balanceOf(to)).should.be.bignumber.equal(valueWithoutTaxes);
(await tokenInstance.balanceOf(to)).should.be.bignumber.equal(amount);
});

it('decreases the spender allowance', async () =>
{
await tokenInstance.transferFrom(owner, to, amount, { from: spender });

(await tokenInstance.allowance(owner, spender)).should.be.bignumber.equal(new BN(0));
(await tokenInstance.allowance(owner, spender)).should.be.bignumber.equal(INITIAL_SUPPLY.sub(amount).sub(taxes));
});

it('should transfer the full value from the tax recipient address', async () =>
Expand Down Expand Up @@ -316,7 +315,7 @@ contract('WibxToken: Common ERC20 Functionalities', ([owner, recipient, anotherA
expectEvent.inLogs(logs, 'Transfer', {
from: owner,
to: to,
value: valueWithoutTaxes
value: amount
});
});
});
Expand Down
10 changes: 6 additions & 4 deletions wibx/test/WibxToken-Taxable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const { applyTax } = require('./helpers/tax');
const expectEvent = require('./helpers/expectEvent');
const {
INITIAL_SUPPLY,
TRANSFER_TEST_AMOUNT,
ALL_TAXES,
ALL_TAXES_SHIFT
} = require('./helpers/constants');
Expand Down Expand Up @@ -94,8 +95,9 @@ contract('WibxToken: Taxable', ([owner, recipient, anotherAccount, bchAddr, taxR

it('emits a transfer event with the default tax value', async () =>
{
const amount = TRANSFER_TEST_AMOUNT;
const taxes = applyTax(amount, ALL_TAXES_SHIFT);
const valueWithoutTaxes = amount.sub(taxes);

const { logs } = await tokenInstance.transfer(to, amount, { from: owner });

/**
Expand All @@ -113,7 +115,7 @@ contract('WibxToken: Taxable', ([owner, recipient, anotherAccount, bchAddr, taxR
expectEvent.inLogs(logs, 'Transfer', {
from: owner,
to: to,
value: valueWithoutTaxes
value: amount
});
});

Expand All @@ -123,8 +125,8 @@ contract('WibxToken: Taxable', ([owner, recipient, anotherAccount, bchAddr, taxR
amount: new BN(3),
shift: new BN(0)
};
const amount = TRANSFER_TEST_AMOUNT;
const taxes = applyTax(amount, taxContainer.shift, taxContainer.amount);
const valueWithoutTaxes = amount.sub(taxes);

await changeTax(taxContainer.amount, taxContainer.shift);
const { logs } = await tokenInstance.transfer(to, amount, { from: owner });
Expand All @@ -144,7 +146,7 @@ contract('WibxToken: Taxable', ([owner, recipient, anotherAccount, bchAddr, taxR
expectEvent.inLogs(logs, 'Transfer', {
from: owner,
to: to,
value: valueWithoutTaxes
value: amount
});
});
});
Expand Down
24 changes: 13 additions & 11 deletions wibx/test/WibxTokenVesting-Common.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ contract('WibxTokenVesting: Common Functionalities', ([owner, recipient, another
'There is no more tokens to transfer to this wallet'
);

(await wibxInstance.balanceOf(anotherAccount)).should.be.bignumber.equal(amountWithoutTaxes(defaultAmount));
(await wibxInstance.balanceOf(anotherAccount)).should.be.bignumber.equal(defaultAmount);
(await vestingInstance.remainingTokenAmount(anotherAccount)).should.be.bignumber.equal(new BN('0'));
(await vestingInstance.totalWibxVestingSupply()).should.be.bignumber.equal(new BN('0'));
});
Expand All @@ -123,7 +123,7 @@ contract('WibxTokenVesting: Common Functionalities', ([owner, recipient, another
'There is no more tokens to transfer to this wallet'
);

(await wibxInstance.balanceOf(anotherAccount)).should.be.bignumber.equal(amountWithoutTaxes(defaultAmount));
(await wibxInstance.balanceOf(anotherAccount)).should.be.bignumber.equal(defaultAmount);
(await vestingInstance.remainingTokenAmount(anotherAccount)).should.be.bignumber.equal(new BN('0'));
(await vestingInstance.totalWibxVestingSupply()).should.be.bignumber.equal(new BN('0'));
});
Expand Down Expand Up @@ -164,11 +164,12 @@ contract('WibxTokenVesting: Common Functionalities', ([owner, recipient, another
{
await transferTokensToVestingContract(defaultAmount);

const ownerBalanceAfterVesting = await wibxInstance.balanceOf(owner);
const taxBalanceAfterVesting = await wibxInstance.balanceOf(taxRecipientAddr);

await vestingInstance.terminateTokenVesting();

(await wibxInstance.balanceOf(owner)).should.be.bignumber.greaterThan(ownerBalanceAfterVesting);
(await wibxInstance.balanceOf(taxRecipientAddr)).should.be.bignumber.greaterThan(taxBalanceAfterVesting);
(await wibxInstance.balanceOf(vestingInstance.address)).should.be.bignumber.equal(new BN('0'));
});

it('should contract be not available after its destruction', async () =>
Expand All @@ -192,13 +193,13 @@ contract('WibxTokenVesting: Common Functionalities', ([owner, recipient, another

await transferTokensToVestingContract(defaultAmount);

(await vestingInstance.totalWibxVestingSupply()).should.be.bignumber.equal(defaultAmount);
(await vestingInstance.totalWibxVestingSupply()).should.be.bignumber.equal(amountWithTaxes(defaultAmount));

await vestingInstance.addTeamMember(wallet, defaultAmount);

await vestingInstance.withdrawal(wallet);

(await wibxInstance.balanceOf(wallet)).should.be.bignumber.equal(amountWithoutTaxes('9000000000000000000000000'));
(await wibxInstance.balanceOf(wallet)).should.be.bignumber.equal('9000000000000000000000000');

await shouldFail.reverting.withMessage(
vestingInstance.withdrawal(wallet),
Expand All @@ -216,21 +217,22 @@ contract('WibxTokenVesting: Common Functionalities', ([owner, recipient, another
*/
async function transferTokensToVestingContract (amount)
{
await wibxInstance.transfer(taxRecipientAddr, amount);
const amountBN = amountWithTaxes(amount);

await wibxInstance.transfer(vestingInstance.address, amount, { from: taxRecipientAddr });
await wibxInstance.transfer(taxRecipientAddr, amountBN);

await wibxInstance.transfer(vestingInstance.address, amountBN, { from: taxRecipientAddr });
}

/**
* Calculate the amount without taxes
*
* @param {BN | string} amount
*/
function amountWithoutTaxes (amount)
function amountWithTaxes (amount)
{
const amountBN = new BN(amount);
const taxes = applyTax(amountBN, ALL_TAXES_SHIFT);

return amountBN.sub(taxes);
return amountBN.add(applyTax(amountBN, ALL_TAXES_SHIFT));
}
});
8 changes: 8 additions & 0 deletions wibx/test/helpers/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ module.exports = class
return new BN(TOTAL_TOKENS.toString());
}

/**
* A big number that will be used to transfers in tests
*/
static get TRANSFER_TEST_AMOUNT ()
{
return this.INITIAL_SUPPLY.div(new BN('2'));
}

/**
* Some amount that no one can have.
*/
Expand Down

0 comments on commit 97a3825

Please sign in to comment.