Merge branch 'master' into refactor/info-md-updates

pull/684/head
Alejandro Santander 7 years ago committed by GitHub
commit 42553ec0c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      README.md
  2. 2
      contracts/lifecycle/TokenDestructible.sol
  3. 2
      contracts/mocks/DetailedERC20Mock.sol
  4. 13
      contracts/mocks/ERC223TokenMock.sol
  5. 15
      contracts/mocks/ERC827TokenMock.sol
  6. 23
      contracts/mocks/MessageHelper.sol
  7. 4
      contracts/mocks/SafeERC20Helper.sol
  8. 4
      contracts/ownership/CanReclaimToken.sol
  9. 4
      contracts/ownership/HasNoTokens.sol
  10. 2
      contracts/token/BasicToken.sol
  11. 0
      contracts/token/ERC20/DetailedERC20.sol
  12. 0
      contracts/token/ERC20/ERC20.sol
  13. 0
      contracts/token/ERC20/ERC20Basic.sol
  14. 0
      contracts/token/ERC20/SafeERC20.sol
  15. 20
      contracts/token/ERC827/ERC827.sol
  16. 126
      contracts/token/ERC827/ERC827Token.sol
  17. 2
      contracts/token/StandardToken.sol
  18. 3
      contracts/token/TokenTimelock.sol
  19. 4
      contracts/token/TokenVesting.sol
  20. 3
      package.json
  21. 6
      test/examples/SimpleToken.test.js
  22. 6
      test/library/ECRecovery.test.js
  23. 2
      test/library/Math.test.js
  24. 4
      test/library/MerkleProof.test.js
  25. 8
      test/ownership/HasNoTokens.test.js
  26. 2
      test/token/ERC20/DetailedERC20.test.js
  27. 4
      test/token/ERC20/SafeERC20.test.js
  28. 374
      test/token/ERC827/ERC827Token.js

@ -21,7 +21,7 @@ mkdir myproject && cd myproject
truffle init
```
To install the OpenZeppelin library, run:
To install the OpenZeppelin library, run the following in your Solidity project root directory:
```sh
npm init
npm install zeppelin-solidity

@ -1,7 +1,7 @@
pragma solidity ^0.4.18;
import "../ownership/Ownable.sol";
import "../token/ERC20Basic.sol";
import "../token/ERC20/ERC20Basic.sol";
/**

@ -1,7 +1,7 @@
pragma solidity ^0.4.18;
import "../token/StandardToken.sol";
import "../token/DetailedERC20.sol";
import "../token/ERC20/DetailedERC20.sol";
contract DetailedERC20Mock is StandardToken, DetailedERC20 {

@ -4,20 +4,19 @@ pragma solidity ^0.4.18;
import "../token/BasicToken.sol";
contract ERC23ContractInterface {
contract ERC223ContractInterface {
function tokenFallback(address _from, uint256 _value, bytes _data) external;
}
contract ERC223TokenMock is BasicToken {
contract ERC23TokenMock is BasicToken {
function ERC23TokenMock(address initialAccount, uint256 initialBalance) public {
function ERC223TokenMock(address initialAccount, uint256 initialBalance) public {
balances[initialAccount] = initialBalance;
totalSupply = initialBalance;
}
// ERC23 compatible transfer function (except the name)
function transferERC23(address _to, uint256 _value, bytes _data) public
// ERC223 compatible transfer function (except the name)
function transferERC223(address _to, uint256 _value, bytes _data) public
returns (bool success)
{
transfer(_to, _value);
@ -26,7 +25,7 @@ contract ERC23TokenMock is BasicToken {
is_contract := not(iszero(extcodesize(_to)))
}
if (is_contract) {
ERC23ContractInterface receiver = ERC23ContractInterface(_to);
ERC223ContractInterface receiver = ERC223ContractInterface(_to);
receiver.tokenFallback(msg.sender, _value, _data);
}
return true;

@ -0,0 +1,15 @@
pragma solidity ^0.4.13;
import "../token/ERC827/ERC827Token.sol";
// mock class using ERC827 Token
contract ERC827TokenMock is ERC827Token {
function ERC827TokenMock(address initialAccount, uint256 initialBalance) public {
balances[initialAccount] = initialBalance;
totalSupply = initialBalance;
}
}

@ -0,0 +1,23 @@
pragma solidity ^0.4.11;
contract MessageHelper {
event Show(bytes32 b32, uint256 number, string text);
function showMessage( bytes32 message, uint256 number, string text ) public returns (bool) {
Show(message, number, text);
return true;
}
function fail() public {
require(false);
}
function call(address to, bytes data) public returns (bool) {
if (to.call(data))
return true;
else
return false;
}
}

@ -1,7 +1,7 @@
pragma solidity ^0.4.18;
import "../token/ERC20.sol";
import "../token/SafeERC20.sol";
import "../token/ERC20/ERC20.sol";
import "../token/ERC20/SafeERC20.sol";
contract ERC20FailingMock is ERC20 {

@ -1,8 +1,8 @@
pragma solidity ^0.4.18;
import "./Ownable.sol";
import "../token/ERC20Basic.sol";
import "../token/SafeERC20.sol";
import "../token/ERC20/ERC20Basic.sol";
import "../token/ERC20/SafeERC20.sol";
/**

@ -6,14 +6,14 @@ import "./CanReclaimToken.sol";
/**
* @title Contracts that should not own Tokens
* @author Remco Bloemen <remco@2π.com>
* @dev This blocks incoming ERC23 tokens to prevent accidental loss of tokens.
* @dev This blocks incoming ERC223 tokens to prevent accidental loss of tokens.
* Should tokens (any ERC20Basic compatible) end up in the contract, it allows the
* owner to reclaim the tokens.
*/
contract HasNoTokens is CanReclaimToken {
/**
* @dev Reject all ERC23 compatible tokens
* @dev Reject all ERC223 compatible tokens
* @param from_ address The address that is transferring the tokens
* @param value_ uint256 the amount of the specified token
* @param data_ Bytes The data passed from the caller.

@ -1,7 +1,7 @@
pragma solidity ^0.4.18;
import "./ERC20Basic.sol";
import "./ERC20/ERC20Basic.sol";
import "../math/SafeMath.sol";

@ -0,0 +1,20 @@
pragma solidity ^0.4.13;
import "../ERC20/ERC20.sol";
/**
@title ERC827 interface, an extension of ERC20 token standard
Interface of a ERC827 token, following the ERC20 standard with extra
methods to transfer value and data and execute calls in transfers and
approvals.
*/
contract ERC827 is ERC20 {
function approve( address _spender, uint256 _value, bytes _data ) public returns (bool);
function transfer( address _to, uint256 _value, bytes _data ) public returns (bool);
function transferFrom( address _from, address _to, uint256 _value, bytes _data ) public returns (bool);
}

@ -0,0 +1,126 @@
pragma solidity ^0.4.13;
import "./ERC827.sol";
import "../StandardToken.sol";
/**
@title ERC827, an extension of ERC20 token standard
Implementation the ERC827, following the ERC20 standard with extra
methods to transfer value and data and execute calls in transfers and
approvals.
Uses OpenZeppelin StandardToken.
*/
contract ERC827Token is ERC827, StandardToken {
/**
@dev Addition to ERC20 token methods. It allows to
approve the transfer of value and execute a call with the sent data.
Beware that changing an allowance with this method brings the risk that
someone may use both the old and the new allowance by unfortunate
transaction ordering. One possible solution to mitigate this race condition
is to first reduce the spender's allowance to 0 and set the desired value
afterwards:
https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
@param _spender The address that will spend the funds.
@param _value The amount of tokens to be spent.
@param _data ABI-encoded contract call to call `_to` address.
@return true if the call function was executed successfully
*/
function approve(address _spender, uint256 _value, bytes _data) public returns (bool) {
require(_spender != address(this));
super.approve(_spender, _value);
require(_spender.call(_data));
return true;
}
/**
@dev Addition to ERC20 token methods. Transfer tokens to a specified
address and execute a call with the sent data on the same transaction
@param _to address The address which you want to transfer to
@param _value uint256 the amout of tokens to be transfered
@param _data ABI-encoded contract call to call `_to` address.
@return true if the call function was executed successfully
*/
function transfer(address _to, uint256 _value, bytes _data) public returns (bool) {
require(_to != address(this));
super.transfer(_to, _value);
require(_to.call(_data));
return true;
}
/**
@dev Addition to ERC20 token methods. Transfer tokens from one address to
another and make a contract call on the same transaction
@param _from The address which you want to send tokens from
@param _to The address which you want to transfer to
@param _value The amout of tokens to be transferred
@param _data ABI-encoded contract call to call `_to` address.
@return true if the call function was executed successfully
*/
function transferFrom(address _from, address _to, uint256 _value, bytes _data) public returns (bool) {
require(_to != address(this));
super.transferFrom(_from, _to, _value);
require(_to.call(_data));
return true;
}
/**
* @dev Addition to StandardToken methods. Increase the amount of tokens that
* an owner allowed to a spender and execute a call with the sent data.
*
* approve should be called when allowed[_spender] == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* @param _spender The address which will spend the funds.
* @param _addedValue The amount of tokens to increase the allowance by.
* @param _data ABI-encoded contract call to call `_spender` address.
*/
function increaseApproval(address _spender, uint _addedValue, bytes _data) public returns (bool) {
require(_spender != address(this));
super.increaseApproval(_spender, _addedValue);
require(_spender.call(_data));
return true;
}
/**
* @dev Addition to StandardToken methods. Decrease the amount of tokens that
* an owner allowed to a spender and execute a call with the sent data.
*
* approve should be called when allowed[_spender] == 0. To decrement
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* @param _spender The address which will spend the funds.
* @param _subtractedValue The amount of tokens to decrease the allowance by.
* @param _data ABI-encoded contract call to call `_spender` address.
*/
function decreaseApproval(address _spender, uint _subtractedValue, bytes _data) public returns (bool) {
require(_spender != address(this));
super.decreaseApproval(_spender, _subtractedValue);
require(_spender.call(_data));
return true;
}
}

@ -2,7 +2,7 @@ pragma solidity ^0.4.18;
import "./BasicToken.sol";
import "./ERC20.sol";
import "./ERC20/ERC20.sol";
/**

@ -1,7 +1,6 @@
pragma solidity ^0.4.18;
import "./ERC20Basic.sol";
import "../token/SafeERC20.sol";
import "./ERC20/SafeERC20.sol";
/**

@ -1,7 +1,7 @@
pragma solidity ^0.4.18;
import "./ERC20Basic.sol";
import "./SafeERC20.sol";
import "./ERC20/ERC20Basic.sol";
import "./ERC20/SafeERC20.sol";
import "../ownership/Ownable.sol";
import "../math/SafeMath.sol";

@ -56,6 +56,7 @@
"truffle-hdwallet-provider": "0.0.3"
},
"dependencies": {
"dotenv": "^4.0.0"
"dotenv": "^4.0.0",
"ethjs-abi": "^0.2.1"
}
}

@ -1,5 +1,5 @@
import decodeLogs from './helpers/decodeLogs';
const SimpleToken = artifacts.require('examples/SimpleToken.sol');
import decodeLogs from '../helpers/decodeLogs';
const SimpleToken = artifacts.require('SimpleToken.sol');
contract('SimpleToken', accounts => {
let token;
@ -23,7 +23,7 @@ contract('SimpleToken', accounts => {
const decimals = await token.decimals();
assert(decimals.eq(18));
});
it('assigns the initial total supply to the creator', async function () {
const totalSupply = await token.totalSupply();
const creatorBalance = await token.balanceOf(creator);

@ -1,7 +1,7 @@
var ECRecoveryMock = artifacts.require('../contracts/mocks/ECRecoveryMock.sol');
var ECRecoveryLib = artifacts.require('../contracts/ECRecovery.sol');
var ECRecoveryMock = artifacts.require('ECRecoveryMock.sol');
var ECRecoveryLib = artifacts.require('ECRecovery.sol');
var hashMessage = require('./helpers/hashMessage.js');
var hashMessage = require('../helpers/hashMessage.js');
contract('ECRecovery', function (accounts) {
let ecrecovery;

@ -1,4 +1,4 @@
var MathMock = artifacts.require('./mocks/MathMock.sol');
var MathMock = artifacts.require('../mocks/MathMock.sol');
contract('Math', function (accounts) {
let math;

@ -1,8 +1,8 @@
import MerkleTree from './helpers/merkleTree.js';
import MerkleTree from '../helpers/merkleTree.js';
import { sha3, bufferToHex } from 'ethereumjs-util';
var MerkleProof = artifacts.require('./MerkleProof.sol');
var MerkleProof = artifacts.require('MerkleProof.sol');
contract('MerkleProof', function (accounts) {
let merkleProof;

@ -2,7 +2,7 @@
import expectThrow from '../helpers/expectThrow';
const HasNoTokens = artifacts.require('../contracts/lifecycle/HasNoTokens.sol');
const ERC23TokenMock = artifacts.require('mocks/ERC23TokenMock.sol');
const ERC223TokenMock = artifacts.require('mocks/ERC223TokenMock.sol');
contract('HasNoTokens', function (accounts) {
let hasNoTokens = null;
@ -11,7 +11,7 @@ contract('HasNoTokens', function (accounts) {
beforeEach(async () => {
// Create contract and token
hasNoTokens = await HasNoTokens.new();
token = await ERC23TokenMock.new(accounts[0], 100);
token = await ERC223TokenMock.new(accounts[0], 100);
// Force token into contract
await token.transfer(hasNoTokens.address, 10);
@ -19,8 +19,8 @@ contract('HasNoTokens', function (accounts) {
assert.equal(startBalance, 10);
});
it('should not accept ERC23 tokens', async function () {
await expectThrow(token.transferERC23(hasNoTokens.address, 10, ''));
it('should not accept ERC223 tokens', async function () {
await expectThrow(token.transferERC223(hasNoTokens.address, 10, ''));
});
it('should allow owner to reclaim tokens', async function () {

@ -5,7 +5,7 @@ require('chai')
.use(require('chai-bignumber')(BigNumber))
.should();
const DetailedERC20Mock = artifacts.require('mocks/DetailedERC20Mock.sol');
const DetailedERC20Mock = artifacts.require('DetailedERC20Mock.sol');
contract('DetailedERC20', accounts => {
let detailedERC20 = null;

@ -1,10 +1,10 @@
import EVMThrow from '../helpers/EVMThrow';
import EVMThrow from '../../helpers/EVMThrow';
require('chai')
.use(require('chai-as-promised'))
.should();
const SafeERC20Helper = artifacts.require('mocks/SafeERC20Helper.sol');
const SafeERC20Helper = artifacts.require('SafeERC20Helper.sol');
contract('SafeERC20', function () {
beforeEach(async function () {

@ -0,0 +1,374 @@
import EVMRevert from '../../helpers/EVMRevert';
var Message = artifacts.require('MessageHelper.sol');
var ERC827TokenMock = artifacts.require('ERC827TokenMock.sol');
var BigNumber = web3.BigNumber;
var _ = require('lodash');
var ethjsABI = require('ethjs-abi');
require('chai')
.use(require('chai-as-promised'))
.use(require('chai-bignumber')(BigNumber))
.should();
contract('ERC827 Token', function (accounts) {
let token;
function findMethod (abi, name, args) {
for (var i = 0; i < abi.length; i++) {
const methodArgs = _.map(abi[i].inputs, 'type').join(',');
if ((abi[i].name === name) && (methodArgs === args)) {
return abi[i];
}
}
}
beforeEach(async function () {
token = await ERC827TokenMock.new(accounts[0], 100);
});
it('should return the correct totalSupply after construction', async function () {
let totalSupply = await token.totalSupply();
assert.equal(totalSupply, 100);
});
it('should return the correct allowance amount after approval', async function () {
let token = await ERC827TokenMock.new();
await token.approve(accounts[1], 100);
let allowance = await token.allowance(accounts[0], accounts[1]);
assert.equal(allowance, 100);
});
it('should return correct balances after transfer', async function () {
await token.transfer(accounts[1], 100);
let balance0 = await token.balanceOf(accounts[0]);
assert.equal(balance0, 0);
let balance1 = await token.balanceOf(accounts[1]);
assert.equal(balance1, 100);
});
it('should throw an error when trying to transfer more than balance', async function () {
await token.transfer(accounts[1], 101).should.be.rejectedWith(EVMRevert);
});
it('should return correct balances after transfering from another account', async function () {
await token.approve(accounts[1], 100);
await token.transferFrom(accounts[0], accounts[2], 100, { from: accounts[1] });
let balance0 = await token.balanceOf(accounts[0]);
assert.equal(balance0, 0);
let balance1 = await token.balanceOf(accounts[2]);
assert.equal(balance1, 100);
let balance2 = await token.balanceOf(accounts[1]);
assert.equal(balance2, 0);
});
it('should throw an error when trying to transfer more than allowed', async function () {
await token.approve(accounts[1], 99);
await token.transferFrom(
accounts[0], accounts[2], 100,
{ from: accounts[1] }
).should.be.rejectedWith(EVMRevert);
});
it('should throw an error when trying to transferFrom more than _from has', async function () {
let balance0 = await token.balanceOf(accounts[0]);
await token.approve(accounts[1], 99);
await token.transferFrom(
accounts[0], accounts[2], balance0 + 1,
{ from: accounts[1] }
).should.be.rejectedWith(EVMRevert);
});
describe('validating allowance updates to spender', function () {
let preApproved;
it('should start with zero', async function () {
preApproved = await token.allowance(accounts[0], accounts[1]);
assert.equal(preApproved, 0);
});
it('should increase by 50 then decrease by 10', async function () {
const abiMethod = findMethod(token.abi, 'increaseApproval', 'address,uint256');
const increaseApprovalData = ethjsABI.encodeMethod(abiMethod,
[accounts[1], 50]
);
await token.sendTransaction(
{ from: accounts[0], data: increaseApprovalData }
);
let postIncrease = await token.allowance(accounts[0], accounts[1]);
preApproved.plus(50).should.be.bignumber.equal(postIncrease);
await token.decreaseApproval(accounts[1], 10);
let postDecrease = await token.allowance(accounts[0], accounts[1]);
postIncrease.minus(10).should.be.bignumber.equal(postDecrease);
});
});
it('should increase by 50 then set to 0 when decreasing by more than 50', async function () {
await token.approve(accounts[1], 50);
await token.decreaseApproval(accounts[1], 60);
let postDecrease = await token.allowance(accounts[0], accounts[1]);
postDecrease.should.be.bignumber.equal(0);
});
it('should throw an error when trying to transfer to 0x0', async function () {
await token.transfer(0x0, 100).should.be.rejectedWith(EVMRevert);
});
it('should throw an error when trying to transferFrom to 0x0', async function () {
await token.approve(accounts[1], 100);
await token.transferFrom(accounts[0], 0x0, 100, { from: accounts[1] })
.should.be.rejectedWith(EVMRevert);
});
describe('Test ERC827 methods', function () {
it(
'should return correct balances after transfer (with data) and show the event on receiver contract'
, async function () {
const message = await Message.new();
const extraData = message.contract.showMessage.getData(
web3.toHex(123456), 666, 'Transfer Done'
);
const abiMethod = findMethod(token.abi, 'transfer', 'address,uint256,bytes');
const transferData = ethjsABI.encodeMethod(abiMethod,
[message.contract.address, 100, extraData]
);
const transaction = await token.sendTransaction(
{ from: accounts[0], data: transferData }
);
assert.equal(2, transaction.receipt.logs.length);
new BigNumber(100).should.be.bignumber.equal(
await token.balanceOf(message.contract.address)
);
});
it(
'should return correct allowance after approve (with data) and show the event on receiver contract'
, async function () {
const message = await Message.new();
const extraData = message.contract.showMessage.getData(
web3.toHex(123456), 666, 'Transfer Done'
);
const abiMethod = findMethod(token.abi, 'approve', 'address,uint256,bytes');
const approveData = ethjsABI.encodeMethod(abiMethod,
[message.contract.address, 100, extraData]
);
const transaction = await token.sendTransaction(
{ from: accounts[0], data: approveData }
);
assert.equal(2, transaction.receipt.logs.length);
new BigNumber(100).should.be.bignumber.equal(
await token.allowance(accounts[0], message.contract.address)
);
});
it(
'should return correct allowance after increaseApproval (with data) and show the event on receiver contract'
, async function () {
const message = await Message.new();
const extraData = message.contract.showMessage.getData(
web3.toHex(123456), 666, 'Transfer Done'
);
await token.approve(message.contract.address, 10);
new BigNumber(10).should.be.bignumber.equal(
await token.allowance(accounts[0], message.contract.address)
);
const abiMethod = findMethod(token.abi, 'increaseApproval', 'address,uint256,bytes');
const increaseApprovalData = ethjsABI.encodeMethod(abiMethod,
[message.contract.address, 50, extraData]
);
const transaction = await token.sendTransaction(
{ from: accounts[0], data: increaseApprovalData }
);
assert.equal(2, transaction.receipt.logs.length);
new BigNumber(60).should.be.bignumber.equal(
await token.allowance(accounts[0], message.contract.address)
);
});
it(
'should return correct allowance after decreaseApproval (with data) and show the event on receiver contract'
, async function () {
const message = await Message.new();
await token.approve(message.contract.address, 100);
new BigNumber(100).should.be.bignumber.equal(
await token.allowance(accounts[0], message.contract.address)
);
const extraData = message.contract.showMessage.getData(
web3.toHex(123456), 666, 'Transfer Done'
);
const abiMethod = findMethod(token.abi, 'decreaseApproval', 'address,uint256,bytes');
const decreaseApprovalData = ethjsABI.encodeMethod(abiMethod,
[message.contract.address, 60, extraData]
);
const transaction = await token.sendTransaction(
{ from: accounts[0], data: decreaseApprovalData }
);
assert.equal(2, transaction.receipt.logs.length);
new BigNumber(40).should.be.bignumber.equal(
await token.allowance(accounts[0], message.contract.address)
);
});
it(
'should return correct balances after transferFrom (with data) and show the event on receiver contract'
, async function () {
const message = await Message.new();
const extraData = message.contract.showMessage.getData(
web3.toHex(123456), 666, 'Transfer Done'
);
await token.approve(accounts[1], 100, { from: accounts[0] });
new BigNumber(100).should.be.bignumber.equal(
await token.allowance(accounts[0], accounts[1])
);
const abiMethod = findMethod(token.abi, 'transferFrom', 'address,address,uint256,bytes');
const transferFromData = ethjsABI.encodeMethod(abiMethod,
[accounts[0], message.contract.address, 100, extraData]
);
const transaction = await token.sendTransaction(
{ from: accounts[1], data: transferFromData }
);
assert.equal(2, transaction.receipt.logs.length);
new BigNumber(100).should.be.bignumber.equal(
await token.balanceOf(message.contract.address)
);
});
it('should fail inside approve (with data)', async function () {
const message = await Message.new();
const extraData = message.contract.fail.getData();
const abiMethod = findMethod(token.abi, 'approve', 'address,uint256,bytes');
const approveData = ethjsABI.encodeMethod(abiMethod,
[message.contract.address, 10, extraData]
);
await token.sendTransaction(
{ from: accounts[0], data: approveData }
).should.be.rejectedWith(EVMRevert);
// approval should not have gone through so allowance is still 0
new BigNumber(0).should.be.bignumber
.equal(await token.allowance(accounts[1], message.contract.address));
});
it('should fail inside transfer (with data)', async function () {
const message = await Message.new();
const extraData = message.contract.fail.getData();
const abiMethod = findMethod(token.abi, 'transfer', 'address,uint256,bytes');
const transferData = ethjsABI.encodeMethod(abiMethod,
[message.contract.address, 10, extraData]
);
await token.sendTransaction(
{ from: accounts[0], data: transferData }
).should.be.rejectedWith(EVMRevert);
// transfer should not have gone through, so balance is still 0
new BigNumber(0).should.be.bignumber
.equal(await token.balanceOf(message.contract.address));
});
it('should fail inside transferFrom (with data)', async function () {
const message = await Message.new();
const extraData = message.contract.fail.getData();
await token.approve(accounts[1], 10, { from: accounts[2] });
const abiMethod = findMethod(token.abi, 'transferFrom', 'address,address,uint256,bytes');
const transferFromData = ethjsABI.encodeMethod(abiMethod,
[accounts[2], message.contract.address, 10, extraData]
);
await token.sendTransaction(
{ from: accounts[1], data: transferFromData }
).should.be.rejectedWith(EVMRevert);
// transferFrom should have failed so balance is still 0 but allowance is 10
new BigNumber(10).should.be.bignumber
.equal(await token.allowance(accounts[2], accounts[1]));
new BigNumber(0).should.be.bignumber
.equal(await token.balanceOf(message.contract.address));
});
it('should fail approve (with data) when using token contract address as receiver', async function () {
const message = await Message.new();
const extraData = message.contract.showMessage.getData(
web3.toHex(123456), 666, 'Transfer Done'
);
const abiMethod = findMethod(token.abi, 'approve', 'address,uint256,bytes');
const approveData = ethjsABI.encodeMethod(abiMethod,
[token.contract.address, 100, extraData]
);
await token.sendTransaction(
{ from: accounts[0], data: approveData }
).should.be.rejectedWith(EVMRevert);
});
it('should fail transfer (with data) when using token contract address as receiver', async function () {
const message = await Message.new();
const extraData = message.contract.showMessage.getData(
web3.toHex(123456), 666, 'Transfer Done'
);
const abiMethod = findMethod(token.abi, 'transfer', 'address,uint256,bytes');
const transferData = ethjsABI.encodeMethod(abiMethod,
[token.contract.address, 100, extraData]
);
await token.sendTransaction(
{ from: accounts[0], data: transferData }
).should.be.rejectedWith(EVMRevert);
});
it('should fail transferFrom (with data) when using token contract address as receiver', async function () {
const message = await Message.new();
const extraData = message.contract.showMessage.getData(
web3.toHex(123456), 666, 'Transfer Done'
);
await token.approve(accounts[1], 1, { from: accounts[0] });
const abiMethod = findMethod(token.abi, 'transferFrom', 'address,address,uint256,bytes');
const transferFromData = ethjsABI.encodeMethod(abiMethod,
[accounts[0], token.contract.address, 1, extraData]
);
await token.sendTransaction(
{ from: accounts[1], data: transferFromData }
).should.be.rejectedWith(EVMRevert);
});
});
});
Loading…
Cancel
Save