diff --git a/contracts/DataToken.sol b/contracts/DataToken.sol index a39abda0f..5db873e09 100644 --- a/contracts/DataToken.sol +++ b/contracts/DataToken.sol @@ -23,7 +23,16 @@ contract DataToken is Initializable, ERC20, Fees, Ownable { bool public initialized = false; - event Initialized(address indexed thisAddress); + event Initialized( + address indexed thisAddress + ); + + event TokenMinted( + address indexed to, + uint256 amount, + uint256 fee, + uint256 cashBack + ); /** * @notice initializer @@ -65,18 +74,26 @@ contract DataToken is Initializable, ERC20, Fees, Ownable { { uint256 startGas = gasleft(); address payable beneficiary = factory.getBeneficiary(); + address payable sender = msg.sender; //mint tokens _mint(address(this), _amount); + uint256 fee = _getFee(startGas); + uint256 cashback = _getCashback(fee, msg.value); + // discuss: change to "==" - require(msg.value >= _getFee(startGas), + require(msg.value >= fee, "fee amount is not enough"); //transfer fee to beneficiary - beneficiary.transfer(msg.value); + beneficiary.transfer(fee); + // return cashback + sender.transfer(cashback); _transfer(address(this), _to, _amount); + + emit TokenMinted(_to, _amount, fee, cashback); } /** diff --git a/contracts/Fees.sol b/contracts/Fees.sol index 9f874beba..19684ab2d 100644 --- a/contracts/Fees.sol +++ b/contracts/Fees.sol @@ -17,4 +17,14 @@ contract Fees { return usedGas.mul(tx.gasprice); } + function _getCashback( + uint256 _fee, + uint256 _payed + ) + public + view + returns(uint256) + { + return _payed.sub(_fee); + } } \ No newline at end of file diff --git a/contracts/TokenFactory.sol b/contracts/TokenFactory.sol index d62522bd2..94635520c 100644 --- a/contracts/TokenFactory.sol +++ b/contracts/TokenFactory.sol @@ -50,21 +50,26 @@ contract TokenFactory is ProxyFactory, Ownable, Fees { payable returns(address) { - uint256 startGas = gasleft(); + uint256 startGas = gasleft(); - bytes memory _payload = abi.encodeWithSignature("initialize(string,address)", _metadata, msg.sender); - address token = deployMinimal(template, _payload); + bytes memory _payload = abi.encodeWithSignature("initialize(string,address)", _metadata, msg.sender); + address token = deployMinimal(template, _payload); + address payable sender = msg.sender; - tokenCount = tokenCount.add(1); - idToToken[tokenCount] = token; - tokenToId[token] = tokenCount; + tokenCount = tokenCount.add(1); + idToToken[tokenCount] = token; + tokenToId[token] = tokenCount; + uint256 fee = _getFee(startGas); + // discuss: change to "==" - require(msg.value >= _getFee(startGas), + require(msg.value >= fee, "fee amount is not enough"); //transfer fee to beneficiary - beneficiary.transfer(msg.value); + beneficiary.transfer(fee); + // return cashback + sender.transfer(_getCashback(fee, msg.value)); return token; } diff --git a/test/DataToken.test.js b/test/DataToken.test.js index e69de29bb..889bfff70 100644 --- a/test/DataToken.test.js +++ b/test/DataToken.test.js @@ -0,0 +1,70 @@ +// Load dependencies +const { accounts, contract } = require('@openzeppelin/test-environment'); +const { expect } = require('chai'); + +// Load test helpers +const { + BN, // Big Number support + balance, + constants, // Common constants, like the zero address and largest integers + expectEvent, // Assertions for emitted events + expectRevert, // Assertions for transactions that should fail +} = require('@openzeppelin/test-helpers'); + + +// Load compiled artifacts +const TokenFactory = contract.fromArtifact('TokenFactory'); +const DataToken = contract.fromArtifact('DataToken'); + +// Start test block +describe('DataToken', function () { + const [ owner ] = accounts; + + beforeEach(async function () { + + // Deploy a new contract for each test + let template = await DataToken.new({ from: owner }); + this.beneficiary = accounts[1]; + this.factory = await TokenFactory.new(template.address, this.beneficiary, { from: owner }); + this.value = new BN("100000000000000000"); + this.notValue = new BN("100"); + + this.factory.createToken('metadata', {value:this.value, from: owner}); + + this.beneficiary = await this.factory.getBeneficiary(); + + this.token = await DataToken.at( + await this.factory.getTokenAddress( + await this.factory.getTokenCount() + )); + }); + + it('.. should mint one token', async function () { + let beneficiaryStartBalance = await balance.current(this.beneficiary); + + let receipt = await this.token.mint(owner, 1, {value:this.value, from: owner}); + let cashBack = receipt['logs'][2]['args']['cashBack'] + let fee = receipt['logs'][2]['args']['fee']; + + let beneficiaryEndBalance = await balance.current(this.beneficiary); + + // check that mint token event was emitted + expectEvent(receipt, 'TokenMinted'); + + // check token balance + expect((await this.token.balanceOf(owner)).toString()).to.equal('1'); + + // check that cashback is greater than zero + expect (await cashBack.gt(await new BN("0"))); + + // check that fee is greater than zero + expect (await fee.gt(await new BN("0"))); + + // check that beneficiary have recieved the fee + expect (await beneficiaryStartBalance.lt(beneficiaryEndBalance)); + + }); + + +}); + diff --git a/test/TokenFactory.test.js b/test/TokenFactory.test.js index 59c9d2f6c..028545188 100644 --- a/test/TokenFactory.test.js +++ b/test/TokenFactory.test.js @@ -24,8 +24,8 @@ describe('TokenFactory', function () { // Deploy a new contract for each test let template = await DataToken.new({ from: owner }); this.contract = await TokenFactory.new(template.address, owner, { from: owner }); - this.value = new BN("10000000000000000");; - this.notValue = new BN("100");; + this.value = new BN("10000000000000000"); + this.notValue = new BN("100"); }); it('.. should revert a token proxy deployment due to low fee', async function () {