Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions contracts/TrueUSD.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pragma solidity ^0.4.23;

import "./modularERC20/ModularPausableToken.sol";
import "openzeppelin-solidity/contracts/ownership/NoOwner.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./CanDelegate.sol";
import "./BurnableTokenWithBounds.sol";
import "./CompliantToken.sol";
Expand All @@ -12,9 +13,12 @@ import "./WithdrawalToken.sol";
// This is the top-level ERC20 contract, but most of the interesting functionality is
// inherited - see the documentation on the corresponding contracts.
contract TrueUSD is ModularPausableToken, NoOwner, BurnableTokenWithBounds, CompliantToken, TokenWithFees, WithdrawalToken, StandardDelegate, CanDelegate {
using SafeMath for *;

string public name = "TrueUSD";
string public symbol = "TUSD";
uint8 public constant decimals = 18;
uint8 public constant rounding = 2;

event ChangeTokenName(string newName, string newSymbol);

Expand Down Expand Up @@ -80,6 +84,12 @@ contract TrueUSD is ModularPausableToken, NoOwner, BurnableTokenWithBounds, Comp
);
}

/* function burnAllArgs(address _burner, uint256 _value) internal {
uint burnAmount = _value.div(10**uint256(decimals.sub(rounding))).mul(10**uint256(decimals.sub(rounding)));
super.burnAllArgs(_burner, burnAmount);
} */


// Alternatives to the normal NoOwner functions in case this contract's owner
// can't own ether or tokens.
// Note that we *do* inherit reclaimContract from NoOwner: This contract
Expand All @@ -92,4 +102,5 @@ contract TrueUSD is ModularPausableToken, NoOwner, BurnableTokenWithBounds, Comp
uint256 balance = token.balanceOf(this);
token.safeTransfer(_to, balance);
}

}
2 changes: 1 addition & 1 deletion contracts/modularERC20/ModularBurnableToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ contract ModularBurnableToken is ModularStandardToken {
require(_value <= balances.balanceOf(_burner),"not enough balance to burn");
// no need to require value <= totalSupply, since that would imply the
// sender's balance is greater than the totalSupply, which *should* be an assertion failure

uint burnAmount = _value / (10 **16) * (10 **16);
balances.subBalance(_burner, _value);
totalSupply_ = totalSupply_.sub(_value);
emit Burn(_burner, _value);
Expand Down
42 changes: 21 additions & 21 deletions test/BurnableTokenWithBounds.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,40 @@ function burnableTokenWithBoundsTests([owner, oneHundred, anotherAccount], trans

describe('setBurnBounds', function () {
it('sets the bounds', async function () {
await this.token.setBurnBounds(10, 20, { from: owner })
await this.token.setBurnBounds(10*10**18, 20*10**18, { from: owner })

const min = await this.token.burnMin()
assert.equal(min, 10)
assert.equal(min, 10*10**18)
const max = await this.token.burnMax()
assert.equal(max, 20)
assert.equal(max, 20*10**18)
})

it('emits an event', async function () {
const { logs } = await this.token.setBurnBounds(10, 20, { from: owner })
const { logs } = await this.token.setBurnBounds(10*10**18, 20*10**18, { from: owner })

assert.equal(logs.length, 1)
assert.equal(logs[0].event, 'SetBurnBounds')
assert.equal(logs[0].args.newMin, 10)
assert.equal(logs[0].args.newMax, 20)
assert.equal(logs[0].args.newMin, 10*10**18)
assert.equal(logs[0].args.newMax, 20*10**18)
})

it('cannot set max less than min', async function () {
await assertRevert(this.token.setBurnBounds(20, 10, { from: owner }))
await assertRevert(this.token.setBurnBounds(20*10**18, 10*10**18, { from: owner }))
})

it('cannot be called by non-owner', async function () {
await assertRevert(this.token.setBurnBounds(10, 20, { from: anotherAccount }))
await assertRevert(this.token.setBurnBounds(10*10**18, 20*10**18, { from: anotherAccount }))
})
})

describe('restrictive burn bounds', function () {
it("allows burns within bounds and reverts others", async function () {
await this.token.setBurnBounds(10, 20, { from: owner })
await assertRevert(this.token.burn(9, { from: oneHundred }))
await assertRevert(this.token.burn(21, { from: oneHundred }))
await this.token.burn(10, { from: oneHundred })
await this.token.burn(15, { from: oneHundred })
await this.token.burn(20, { from: oneHundred })
await this.token.setBurnBounds(10*10**18, 20*10**18, { from: owner })
await assertRevert(this.token.burn(9*10**18, { from: oneHundred }))
await assertRevert(this.token.burn(21*10**18, { from: oneHundred }))
await this.token.burn(10*10**18, { from: oneHundred })
await this.token.burn(15*10**18, { from: oneHundred })
await this.token.burn(20*10**18, { from: oneHundred })
})
})

Expand All @@ -55,17 +55,17 @@ function burnableTokenWithBoundsTests([owner, oneHundred, anotherAccount], trans
describe('transfers to 0x0 become burns', function () {
describe('restrictive burn bounds', function () {
it("allows burns within bounds and reverts others", async function () {
await this.token.setBurnBounds(10, 20, { from: owner })
await assertRevert(this.token.transfer(ZERO_ADDRESS, 9, { from: oneHundred }))
await assertRevert(this.token.transfer(ZERO_ADDRESS, 21, { from: oneHundred }))
await this.token.transfer(ZERO_ADDRESS, 10, { from: oneHundred })
await this.token.transfer(ZERO_ADDRESS, 15, { from: oneHundred })
await this.token.transfer(ZERO_ADDRESS, 20, { from: oneHundred })
await this.token.setBurnBounds(10*10**18, 20*10**18, { from: owner })
await assertRevert(this.token.transfer(ZERO_ADDRESS, 9*10**18, { from: oneHundred }))
await assertRevert(this.token.transfer(ZERO_ADDRESS, 21*10**18, { from: oneHundred }))
await this.token.transfer(ZERO_ADDRESS, 10*10**18, { from: oneHundred })
await this.token.transfer(ZERO_ADDRESS, 15*10**18, { from: oneHundred })
await this.token.transfer(ZERO_ADDRESS, 20*10**18, { from: oneHundred })
})
})
})
}
})
}

export default burnableTokenWithBoundsTests
export default burnableTokenWithBoundsTests
4 changes: 2 additions & 2 deletions test/BurnableTokenWithBounds.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ const BurnableTokenWithBoundsMock = artifacts.require('BurnableTokenWithBoundsMo

contract('BurnableTokenWithBounds', function ([_, owner, oneHundred, anotherAccount]) {
beforeEach(async function () {
this.token = await BurnableTokenWithBoundsMock.new(oneHundred, 100, { from: owner })
this.token = await BurnableTokenWithBoundsMock.new(oneHundred, 100*10**18, { from: owner })
})

burnableTokenWithBoundsTests([owner, oneHundred, anotherAccount])
})
})
22 changes: 11 additions & 11 deletions test/CanDelegate.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,23 @@ function canDelegateTests([owner, oneHundred, anotherAccount], transfersToZeroBe
})

it('transfer', async function () {
await assertRevert(this.token.transfer(oneHundred, 50, { from: anotherAccount }))
await assertRevert(this.token.transfer(oneHundred, 50*10**18, { from: anotherAccount }))
})

it('transferFrom', async function () {
await assertRevert(this.token.transferFrom(oneHundred, oneHundred, 50, { from: anotherAccount }))
await assertRevert(this.token.transferFrom(oneHundred, oneHundred, 50*10**18, { from: anotherAccount }))
})

it('approve', async function () {
await assertRevert(this.token.approve(oneHundred, 50, { from: anotherAccount }))
await assertRevert(this.token.approve(oneHundred, 50*10**18, { from: anotherAccount }))
})

it('increaseApproval', async function () {
await assertRevert(this.token.increaseApproval(oneHundred, 50, { from: anotherAccount }))
await assertRevert(this.token.increaseApproval(oneHundred, 50*10**18, { from: anotherAccount }))
})

it('decreaseApproval', async function () {
await assertRevert(this.token.decreaseApproval(oneHundred, 50, { from: anotherAccount }))
await assertRevert(this.token.decreaseApproval(oneHundred, 50*10**18, { from: anotherAccount }))
})
})

Expand All @@ -70,26 +70,26 @@ function canDelegateTests([owner, oneHundred, anotherAccount], transfersToZeroBe
})

it('transfer', async function () {
await this.token.transfer(oneHundred, 50, { from: anotherAccount })
await this.token.transfer(oneHundred, 50*10**18, { from: anotherAccount })
})

it('transferFrom', async function () {
await this.token.transferFrom(oneHundred, oneHundred, 50, { from: anotherAccount })
await this.token.transferFrom(oneHundred, oneHundred, 50*10**18, { from: anotherAccount })
})

it('approve', async function () {
await this.token.approve(oneHundred, 50, { from: anotherAccount })
await this.token.approve(oneHundred, 50*10**18, { from: anotherAccount })
})

it('increaseApproval', async function () {
await this.token.increaseApproval(oneHundred, 50, { from: anotherAccount })
await this.token.increaseApproval(oneHundred, 50*10**18, { from: anotherAccount })
})

it('decreaseApproval', async function () {
await this.token.decreaseApproval(oneHundred, 50, { from: anotherAccount })
await this.token.decreaseApproval(oneHundred, 50*10**18, { from: anotherAccount })
})
})
})
}

export default canDelegateTests
export default canDelegateTests
8 changes: 4 additions & 4 deletions test/CanDelegate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ contract('CanDelegate', function (accounts) {
const anotherAccounts = [accounts[7], accounts[8], accounts[9]]

beforeEach(async function () {
this.token = await CanDelegateMock.new(oneHundreds[0], 100, { from: owners[0] })
this.token = await CanDelegateMock.new(oneHundreds[0], 100*10**18, { from: owners[0] })
})

canDelegateTests([owners[0], oneHundreds[0], anotherAccounts[0]])

it('other test', async function () {
const delegate = await StandardDelegateMock.new(oneHundreds[0], 100, { from: owners[0] })
const delegate = await StandardDelegateMock.new(oneHundreds[0], 100*10**18, { from: owners[0] })
await delegate.setDelegatedFrom(anotherAccounts[0], { from: owners[0] })
await assertRevert(delegate.delegateTransfer(anotherAccounts[0], 10, 0x0, { from: anotherAccounts[0] }))
await assertRevert(delegate.delegateTransfer(anotherAccounts[0], 10*10**18, 0x0, { from: anotherAccounts[0] }))
})
})
})
40 changes: 20 additions & 20 deletions test/CompliantToken.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ function compliantTokenTests([owner, oneHundred, anotherAccount], transfersToZer
})

it('rejects mint when user is not on mint whitelist', async function () {
await assertRevert(this.token.mint(anotherAccount, 100, { from: owner }))
await assertRevert(this.token.mint(anotherAccount, 100*10**18, { from: owner }))
})

it('rejects mint when user is blacklisted', async function () {
await this.registry.setAttribute(anotherAccount, "hasPassedKYC/AML", 1, notes, { from: owner })
await this.registry.setAttribute(anotherAccount, "isBlacklisted", 1, notes, { from: owner })
await assertRevert(this.token.mint(anotherAccount, 100, { from: owner }))
await assertRevert(this.token.mint(anotherAccount, 100*10**18, { from: owner }))
})
})

Expand All @@ -39,12 +39,12 @@ function compliantTokenTests([owner, oneHundred, anotherAccount], transfersToZer

it('rejects burn when user is on blacklist', async function () {
await this.registry.setAttribute(oneHundred, "isBlacklisted", 1, notes, { from: owner })
await assertRevert(this.token.burn(20, { from: oneHundred }))
await assertRevert(this.token.burn(20*10**18, { from: oneHundred }))
})
})

it('rejects burn when user is not on burn whitelist', async function () {
await assertRevert(this.token.burn(20, { from: oneHundred }))
await assertRevert(this.token.burn(20*10**18, { from: oneHundred }))
})
})

Expand All @@ -61,12 +61,12 @@ function compliantTokenTests([owner, oneHundred, anotherAccount], transfersToZer

it('rejects burn when user is on blacklist', async function () {
await this.registry.setAttribute(oneHundred, "isBlacklisted", 1, notes, { from: owner })
await assertRevert(this.token.transfer(ZERO_ADDRESS, 20, { from: oneHundred }))
await assertRevert(this.token.transfer(ZERO_ADDRESS, 20*10**18, { from: oneHundred }))
})
})

it('rejects burn when user is not on burn whitelist', async function () {
await assertRevert(this.token.transfer(ZERO_ADDRESS, 20, { from: oneHundred }))
await assertRevert(this.token.transfer(ZERO_ADDRESS, 20*10**18, { from: oneHundred }))
})
})
})
Expand All @@ -81,24 +81,24 @@ function compliantTokenTests([owner, oneHundred, anotherAccount], transfersToZer
describe('when user is on blacklist', function () {
it('rejects transfer from blacklisted account', async function () {
await this.registry.setAttribute(oneHundred, "isBlacklisted", 1, notes, { from: owner })
await assertRevert(this.token.transfer(anotherAccount, 100, { from: oneHundred }))
await assertRevert(this.token.transfer(anotherAccount, 100*10**18, { from: oneHundred }))
})

it('rejects transfer to blacklisted account', async function () {
await this.registry.setAttribute(anotherAccount, "isBlacklisted", 1, notes, { from: owner })
await assertRevert(this.token.transfer(anotherAccount, 100, { from: oneHundred }))
await assertRevert(this.token.transfer(anotherAccount, 100*10**18, { from: oneHundred }))
})

it('rejects transferFrom to blacklisted account', async function () {
await this.registry.setAttribute(oneHundred, "isBlacklisted", 1, notes, { from: owner })
await this.token.approve(anotherAccount, 100, { from: oneHundred })
await assertRevert(this.token.transferFrom(oneHundred, owner, 100, { from: anotherAccount }))
await this.token.approve(anotherAccount, 100*10**18, { from: oneHundred })
await assertRevert(this.token.transferFrom(oneHundred, owner, 100*10**18, { from: anotherAccount }))
})

it('rejects transferFrom by blacklisted spender', async function () {
await this.registry.setAttribute(anotherAccount, "isBlacklisted", 1, notes, { from: owner })
await this.token.approve(anotherAccount, 100, { from: oneHundred })
await assertRevert(this.token.transferFrom(oneHundred, owner, 100, { from: anotherAccount }))
await this.token.approve(anotherAccount, 100*10**18, { from: oneHundred })
await assertRevert(this.token.transferFrom(oneHundred, owner, 100*10**18, { from: anotherAccount }))
})
})

Expand All @@ -111,24 +111,24 @@ function compliantTokenTests([owner, oneHundred, anotherAccount], transfersToZer
const checkPermutation = function(a, b, c) {
describe('another permutation', function () {
beforeEach(async function () {
await this.token.approve(spender, 100, { from: from })
await this.token.approve(spender, 100*10**18, { from: from })
await this.registry.setAttribute(a, "isRestrictedExchange", 1, notes, { from: owner })
})

it('rejects if one is not KYC/AMLed', async function () {
await this.registry.setAttribute(b, "hasPassedKYC/AML", 1, notes, { from: owner })
await assertRevert(this.token.transferFrom(from, to, 100, { from: spender }))
await assertRevert(this.token.transferFrom(from, to, 100*10**18, { from: spender }))
})

it('rejects if another is not KYC/AMLed', async function () {
await this.registry.setAttribute(c, "hasPassedKYC/AML", 1, notes, { from: owner })
await assertRevert(this.token.transferFrom(from, to, 100, { from: spender }))
await assertRevert(this.token.transferFrom(from, to, 100*10**18, { from: spender }))
})

it('allows if all are KYC/AMLed', async function () {
await this.registry.setAttribute(b, "hasPassedKYC/AML", 1, notes, { from: owner })
await this.registry.setAttribute(c, "hasPassedKYC/AML", 1, notes, { from: owner })
await this.token.transferFrom(from, to, 100, { from: spender })
await this.token.transferFrom(from, to, 100*10**18, { from: spender })
})
})
}
Expand All @@ -149,12 +149,12 @@ function compliantTokenTests([owner, oneHundred, anotherAccount], transfersToZer
})

it('rejects if other is not KYC/AMLed', async function () {
await assertRevert(this.token.transfer(to, 100, { from: from }))
await assertRevert(this.token.transfer(to, 100*10**18, { from: from }))
})

it('allows if other is KYC/AMLed', async function () {
await this.registry.setAttribute(b, "hasPassedKYC/AML", 1, notes, { from: owner })
await this.token.transfer(to, 100, { from: from })
await this.token.transfer(to, 100*10**18, { from: from })
})
})
}
Expand Down Expand Up @@ -187,7 +187,7 @@ function compliantTokenTests([owner, oneHundred, anotherAccount], transfersToZer
assert.equal(logs.length, 1)
assert.equal(logs[0].event, 'WipeBlacklistedAccount')
assert.equal(logs[0].args.account, oneHundred)
assert.equal(logs[0].args.balance, 100)
assert.equal(logs[0].args.balance, 100*10**18)
})

it('cannot be called by non-owner', async function () {
Expand All @@ -198,4 +198,4 @@ function compliantTokenTests([owner, oneHundred, anotherAccount], transfersToZer

}

export default compliantTokenTests
export default compliantTokenTests
Loading