Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
O
openzeppelin-contracts-upgradeable
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
俞永鹏
openzeppelin-contracts-upgradeable
Commits
94d3c447
Commit
94d3c447
authored
Mar 23, 2017
by
Remco Bloemen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add HasNoTokens
parent
9ff82aec
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
108 additions
and
1 deletions
+108
-1
HasNoTokens.sol
contracts/ownership/HasNoTokens.sol
+26
-0
HasNoTokens.js
test/HasNoTokens.js
+40
-0
ERC23TokenMock.sol
test/helpers/ERC23TokenMock.sol
+33
-0
expectThrow.js
test/helpers/expectThrow.js
+9
-1
No files found.
contracts/ownership/HasNoTokens.sol
0 → 100644
View file @
94d3c447
pragma solidity ^0.4.8;
import "./Ownable.sol";
import "../token/ERC20Basic.sol";
/// @title Contracts that should not own Tokens
/// @author Remco Bloemen <remco@2π.com>
///
/// This blocks incoming ERC23 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 Ownable {
/// Reject all ERC23 compatible tokens
function tokenFallback(address from_, uint value_, bytes data_) external {
throw;
}
/// Reclaim all ERC20Basic compatible tokens
function reclaimToken(address tokenAddr) external onlyOwner {
ERC20Basic tokenInst = ERC20Basic(tokenAddr);
uint256 balance = tokenInst.balanceOf(this);
tokenInst.transfer(owner, balance);
}
}
test/HasNoTokens.js
0 → 100644
View file @
94d3c447
'use strict'
;
import
expectThrow
from
'./helpers/expectThrow'
;
import
toPromise
from
'./helpers/toPromise'
;
const
HasNoTokens
=
artifacts
.
require
(
'../contracts/lifecycle/HasNoTokens.sol'
);
const
ERC23TokenMock
=
artifacts
.
require
(
'./helpers/ERC23TokenMock.sol'
);
contract
(
'HasNoTokens'
,
function
(
accounts
)
{
let
hasNoTokens
=
null
;
let
token
=
null
;
beforeEach
(
async
()
=>
{
// Create contract and token
hasNoTokens
=
await
HasNoTokens
.
new
();
token
=
await
ERC23TokenMock
.
new
(
accounts
[
0
],
100
);
// Force token into contract
await
token
.
transfer
(
hasNoTokens
.
address
,
10
);
const
startBalance
=
await
token
.
balanceOf
(
hasNoTokens
.
address
);
assert
.
equal
(
startBalance
,
10
);
});
it
(
'should not accept ERC23 tokens'
,
async
function
()
{
await
expectThrow
(
token
.
transferERC23
(
hasNoTokens
.
address
,
10
,
''
));
});
it
(
'should allow owner to reclaim tokens'
,
async
function
()
{
const
ownerStartBalance
=
await
token
.
balanceOf
(
accounts
[
0
]);
await
hasNoTokens
.
reclaimToken
(
token
.
address
);
const
ownerFinalBalance
=
await
token
.
balanceOf
(
accounts
[
0
]);
const
finalBalance
=
await
token
.
balanceOf
(
hasNoTokens
.
address
);
assert
.
equal
(
finalBalance
,
0
);
assert
.
equal
(
ownerFinalBalance
-
ownerStartBalance
,
10
);
});
it
(
'should allow only owner to reclaim tokens'
,
async
function
()
{
await
expectThrow
(
hasNoTokens
.
reclaimToken
(
token
.
address
,
{
from
:
accounts
[
1
]}),
);
});
});
test/helpers/ERC23TokenMock.sol
0 → 100644
View file @
94d3c447
pragma solidity ^0.4.8;
import '../../contracts/token/BasicToken.sol';
contract ERC23ContractInterface {
function tokenFallback(address _from, uint _value, bytes _data) external;
}
contract ERC23TokenMock is BasicToken {
function ERC23TokenMock(address initialAccount, uint initialBalance) {
balances[initialAccount] = initialBalance;
totalSupply = initialBalance;
}
// ERC23 compatible transfer function (except the name)
function transferERC23(address _to, uint _value, bytes _data)
returns (bool success)
{
transfer(_to, _value);
bool is_contract = false;
assembly {
is_contract := not(iszero(extcodesize(_to)))
}
if(is_contract) {
ERC23ContractInterface receiver = ERC23ContractInterface(_to);
receiver.tokenFallback(msg.sender, _value, _data);
}
return true;
}
}
test/helpers/expectThrow.js
View file @
94d3c447
...
...
@@ -5,7 +5,15 @@ export default async promise => {
// TODO: Check jump destination to destinguish between a throw
// and an actual invalid jump.
const
invalidJump
=
error
.
message
.
search
(
'invalid JUMP'
)
>=
0
;
assert
(
invalidJump
,
"Expected throw, got '"
+
error
+
"' instead"
);
// TODO: When we contract A calls contract B, and B throws, instead
// of an 'invalid jump', we get an 'out of gas' error. How do
// we distinguish this from an actual out of gas event? (The
// testrpc log actually show an 'invalid jump' event.)
const
outOfGas
=
error
.
message
.
search
(
'out of gas'
)
>=
0
;
assert
(
invalidJump
||
outOfGas
,
"Expected throw, got '"
+
error
+
"' instead"
,
);
return
;
}
assert
.
fail
(
'Expected throw not received'
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment