-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added script for disabling tokens (#101)
* Added support for crippling tokens * Added test for DisableToken's upgrade method
- Loading branch information
1 parent
e06c05d
commit 58a6e00
Showing
6 changed files
with
327 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
pragma solidity ^0.4.24; | ||
|
||
import "./IETokenProxy.sol"; | ||
|
||
/** | ||
* @title A token that doesn't work | ||
* @dev Implements a proxy interface which always reverts. Used for | ||
* testing if upgraded tokens actually forwards calls to the proxy. | ||
*/ | ||
contract DisableToken is IETokenProxy { | ||
|
||
/* solium-disable zeppelin/missing-natspec-comments */ | ||
|
||
function upgrade(IETokenProxy upgradedToken) public pure { | ||
// Silence warnings | ||
upgradedToken; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function finalizeUpgrade() public { | ||
} | ||
|
||
function nameProxy(address sender) | ||
public | ||
view | ||
returns(string) | ||
{ | ||
sender; | ||
return "DO NOT USE - Disabled"; | ||
} | ||
|
||
function symbolProxy(address sender) | ||
public | ||
view | ||
returns(string) | ||
{ | ||
sender; | ||
return "DEAD"; | ||
} | ||
|
||
function decimalsProxy(address sender) | ||
public | ||
view | ||
returns(uint8) | ||
{ | ||
// Silence warnings | ||
sender; | ||
return 0; | ||
} | ||
|
||
function totalSupplyProxy(address sender) | ||
public | ||
view | ||
returns(uint256) | ||
{ | ||
// Silence warnings | ||
sender; | ||
return 0; | ||
} | ||
|
||
function balanceOfProxy(address sender, address who) | ||
public | ||
view | ||
returns(uint256) | ||
{ | ||
// Silence warnings | ||
sender; | ||
who; | ||
return 0; | ||
} | ||
|
||
function allowanceProxy(address sender, address owner, address spender) | ||
public | ||
view | ||
returns(uint256) | ||
{ | ||
// Silence warnings | ||
sender; | ||
owner; | ||
spender; | ||
return 0; | ||
} | ||
|
||
function transferProxy(address sender, address to, uint256 value) | ||
public | ||
returns (bool) | ||
{ | ||
sender; | ||
to; | ||
value; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function approveProxy(address sender, address spender, uint256 value) | ||
public | ||
returns (bool) | ||
{ | ||
sender; | ||
spender; | ||
value; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function transferFromProxy( | ||
address sender, | ||
address from, | ||
address to, | ||
uint256 value | ||
) | ||
public | ||
returns (bool) | ||
{ | ||
sender; | ||
from; | ||
to; | ||
value; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function increaseAllowanceProxy( | ||
address sender, | ||
address spender, | ||
uint256 addedValue | ||
) | ||
public | ||
returns (bool) | ||
{ | ||
sender; | ||
spender; | ||
addedValue; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function decreaseAllowanceProxy(address sender, | ||
address spender, | ||
uint256 subtractedValue) | ||
public | ||
returns (bool) { | ||
sender; | ||
spender; | ||
subtractedValue; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function burnProxy(address sender, uint256 value) | ||
public | ||
{ | ||
sender; | ||
value; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function burnFromProxy(address sender, | ||
address from, | ||
uint256 value) | ||
public | ||
{ | ||
sender; | ||
from; | ||
value; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function mintProxy(address sender, address to, uint256 value) | ||
public | ||
returns (bool) | ||
{ | ||
sender; | ||
to; | ||
value; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function changeMintingRecipientProxy(address sender, address mintingRecip) | ||
public | ||
{ | ||
sender; | ||
mintingRecip; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function pauseProxy(address sender) external { | ||
sender; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function unpauseProxy(address sender) external { | ||
sender; | ||
revert("Token is disabled"); | ||
} | ||
|
||
function pausedProxy(address sender) external view returns (bool) { | ||
sender; | ||
revert("Token is disabled"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
'use strict'; | ||
|
||
const oneAddress = '0x1111111111111111111111111111111111111111'; | ||
|
||
async function disableToken (DisableTokenArtifact, token, tokenOwner) { | ||
const disableToken = await DisableTokenArtifact.new({ from: tokenOwner }); | ||
|
||
await token.pause({ from: tokenOwner }); | ||
await token.upgrade(disableToken.address, { from: tokenOwner }); | ||
await token.transferOwnership(oneAddress, { from: tokenOwner }); | ||
} | ||
|
||
module.exports = disableToken; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* global artifacts */ | ||
|
||
'use strict'; | ||
|
||
const DisableToken = artifacts.require('DisableToken.sol'); | ||
const EToken = artifacts.require('EToken.sol'); | ||
|
||
const readlineSync = require('readline-sync'); | ||
|
||
const argv = require('optimist') | ||
.usage('Usage: --network [name] --token [address] --tokenOwner [address]') | ||
.describe('network', 'truffle network configuration name') | ||
.string(['token', 'tokenOwner']) | ||
.demand(['token', 'tokenOwner']) | ||
.argv; | ||
|
||
const disableToken = require('./disableToken'); | ||
|
||
async function disableTokenWrapper () { | ||
const token = EToken.at(argv.token); | ||
const tokenOwner = argv.tokenOwner.toLowerCase(); | ||
|
||
if ((await token.owner()) !== tokenOwner) { | ||
throw Error('tokenOwner is not correct'); | ||
} | ||
|
||
const answer = readlineSync.question( | ||
'WARNING: This will permentaly disable your token. Enter \'I understand\' to proceed...\n'); | ||
|
||
if (answer !== 'I understand') { | ||
throw Error('You do not understand'); | ||
} | ||
|
||
await disableToken(DisableToken, token, tokenOwner); | ||
} | ||
|
||
module.exports = (callback, test) => { | ||
disableTokenWrapper().then( | ||
() => callback(), | ||
(err) => callback(err) | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* global artifacts, web3, contract */ | ||
/* eslint-env mocha */ | ||
|
||
'use strict'; | ||
|
||
const Accesslist = artifacts.require('Accesslist'); | ||
const ETokenMock = artifacts.require('ETokenMock'); | ||
const DisableToken = artifacts.require('DisableToken'); | ||
|
||
const utils = require('./utils.js'); | ||
const disableTokenAction = require('../scripts/disableToken/disableToken.js'); | ||
|
||
const BigNumber = web3.BigNumber; | ||
|
||
require('chai') | ||
.use(require('chai-bignumber')(BigNumber)) | ||
.should(); | ||
|
||
contract('Disable Token', async function ([_, owner, otherAccount]) { | ||
it('Should properly disable token', | ||
async function () { | ||
const tokenName = 'test'; | ||
const tokenSymbol = 'test'; | ||
const tokenDecimals = 4; | ||
|
||
const accesslist = await Accesslist.new(); | ||
|
||
const token = await ETokenMock.new( | ||
tokenName, tokenSymbol, tokenDecimals, | ||
accesslist.address, false, utils.ZERO_ADDRESS, owner, 0, true, | ||
owner, 10000, | ||
{ from: owner } | ||
); | ||
|
||
await token.approve(otherAccount, 100, { from: owner }); | ||
|
||
(await token.name()).should.be.equal(tokenName); | ||
(await token.symbol()).should.be.equal(tokenSymbol); | ||
(await token.decimals()).should.be.bignumber.equal(tokenDecimals); | ||
(await token.totalSupply()).should.be.bignumber.equal(10000); | ||
(await token.balanceOf(owner)).should.be.bignumber.equal(10000); | ||
(await token.allowance(owner, otherAccount)).should.be.bignumber.equal(100); | ||
|
||
await disableTokenAction(DisableToken, token, owner); | ||
|
||
(await token.name()).should.be.equal('DO NOT USE - Disabled'); | ||
(await token.symbol()).should.be.equal('DEAD'); | ||
(await token.decimals()).should.be.bignumber.equal(0); | ||
(await token.totalSupply()).should.be.bignumber.equal(0); | ||
(await token.balanceOf(owner)).should.be.bignumber.equal(0); | ||
(await token.allowance(owner, otherAccount)).should.be.bignumber.equal(0); | ||
|
||
const crippledText = 'Token is disabled'; | ||
await utils.assertRevertsReason(token.transfer(owner, 100), crippledText); | ||
await utils.assertRevertsReason(token.approve(owner, 100), crippledText); | ||
await utils.assertRevertsReason(token.transferFrom(owner, owner, 100), crippledText); | ||
await utils.assertRevertsReason(token.increaseAllowance(owner, 100), crippledText); | ||
await utils.assertRevertsReason(token.decreaseAllowance(owner, 100), crippledText); | ||
await utils.assertRevertsReason(token.burn(100), crippledText); | ||
await utils.assertRevertsReason(token.burnFrom(owner, 100), crippledText); | ||
await utils.assertRevertsReason(token.mint(owner, 100), crippledText); | ||
await utils.assertRevertsReason(token.changeMintingRecipient(owner), crippledText); | ||
await utils.assertRevertsReason(token.pause(), crippledText); | ||
await utils.assertRevertsReason(token.unpause(), crippledText); | ||
await utils.assertRevertsReason(token.paused(), crippledText); | ||
|
||
const disabledToken = DisableToken.at(await token.getUpgradedToken()); | ||
await utils.assertRevertsReason(disabledToken.upgrade(utils.ZERO_ADDRESS), crippledText); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters