Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4a10f727c4 | |||
| e79dc645e4 | |||
| 0e5799c93b | |||
| 90413e75f1 | |||
| 9c262571ae | |||
| 76fe1548ae | |||
| 8f2a4785cb | |||
| 16535fbb87 | |||
| 77cc33fc5c | |||
| 0b33d29e41 | |||
| 61dfdde6c4 | |||
| e8be9a7bd0 | |||
| dd8758fedf | |||
| c63b203c1d | |||
| c191757c6e | |||
| f4bdaf49a1 | |||
| 6a7114fdb4 | |||
| 0926729c8f | |||
| 9e1c934ffd | |||
| a7e91856f3 | |||
| 06666be93a | |||
| 915f74c5f6 | |||
| 3d3f20f7e3 | |||
| 03a3302abd | |||
| bd5f7f5774 | |||
| a6bef44790 | |||
| a9c777faa6 | |||
| 44a404aae5 | |||
| 1d2d18f9da | |||
| 82ce197e44 | |||
| 42787e2a75 | |||
| 9bc43c8d0f | |||
| cacf03641c | |||
| e96164feea | |||
| 9f52e94339 | |||
| c9936e231d | |||
| e299a7950e | |||
| b33260ac44 | |||
| 3fb8ecad76 | |||
| c3cbdb4599 | |||
| 7586e383c2 | |||
| d1146e8c8b | |||
| 8d4eee412d | |||
| 903751ce0d | |||
| 9fd61177c3 | |||
| 3c48912730 | |||
| b3a8602928 | |||
| 5ef8554727 | |||
| 9ea4bae313 | |||
| c05918c3cc | |||
| 108d5f3b4a | |||
| 61b6a733c8 | |||
| 6ad275befb | |||
| 7a0bfdfbb4 | |||
| f4228f1b49 | |||
| a5d5867092 | |||
| 4d7c3cca75 |
10
.github/ISSUE_TEMPLATE.md
vendored
10
.github/ISSUE_TEMPLATE.md
vendored
@ -1,17 +1,18 @@
|
||||
## 🎉 Description
|
||||
|
||||
<!-- Briefly describe the issue you are experiencing (or the feature you want to see added to OpenZeppelin). Tell us what you were trying to do and what happened instead. **Remember, this is _not_ a place to ask for help debugging code; for that, we welcome you in the [OpenZeppelin Slack Channel](https://slack.openzeppelin.org/).** -->
|
||||
|
||||
- [ ] 🐛 This is a bug report.
|
||||
- [ ] 📈 This is a feature request.
|
||||
|
||||
<!-- Please check one of the above by placing an x in the box. -->
|
||||
|
||||
Briefly describe the issue you are experiencing (or the feature you want to see added to OpenZeppelin). Tell us what you were trying to do and what happened instead. **Remember, this is _not_ a place to ask for help debugging code; for that, we welcome you in the [OpenZeppelin Slack Channel](https://slack.openzeppelin.org/).**
|
||||
|
||||
## 💻 Environment
|
||||
|
||||
First, we need to know what your environment looks like.
|
||||
Next, we need to know what your environment looks like.
|
||||
|
||||
- Which version of OpenZeppelin are you using?
|
||||
- What network are you deploying to? testrpc? Ganache? Ropsten?
|
||||
- What network are you deploying to? Ganache? Ropsten?
|
||||
- How are you deploying your OpenZeppelin-backed contracts? truffle? Remix? Let us know!
|
||||
|
||||
## 📝 Details
|
||||
@ -29,4 +30,5 @@ insert short code snippets here
|
||||
<!-- If your code is larger, consider linking us to a repo illustrating your issue. -->
|
||||
|
||||
## 👍 Other Information
|
||||
|
||||
<!-- List any other information that is relevant to your issue. Error logs, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc. -->
|
||||
|
||||
22
.github/PULL_REQUEST_TEMPLATE.md
vendored
22
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,17 +1,17 @@
|
||||
<!-- 🎉 Thank you for submitting a PR! Before submitting, please review the following checklist: -->
|
||||
<!-- 0. 🎉 Thank you for submitting a PR! -->
|
||||
|
||||
- [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](/docs/CONTRIBUTING.md)
|
||||
- [ ] ✅ I've added tests where applicable to test my new functionality.
|
||||
- [ ] 📖 I've made sure that my contracts are well-documented.
|
||||
- [ ] 🎨 I've run the JS/Solidity linters (`npm run lint:all:fix`) and fixed any issues.
|
||||
|
||||
<!-- **Does this close any open issues?** If so, list them here. -->
|
||||
<!-- 1. **Does this close any open issues?** If so, list them here. If not, remove the `Fixes #` line. -->
|
||||
|
||||
Fixes #
|
||||
|
||||
---
|
||||
|
||||
# 🚀 Description
|
||||
|
||||
<!-- Describe the changes introduced in this pull request -->
|
||||
<!-- Include any context necessary for understanding the PR's purpose. -->
|
||||
<!-- 2. Describe the changes introduced in this pull request -->
|
||||
<!-- Include any context necessary for understanding the PR's purpose. -->
|
||||
|
||||
<!-- 3. Before submitting, please review the following checklist: -->
|
||||
|
||||
- [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](../blob/master/CONTRIBUTING.md)
|
||||
- [ ] ✅ I've added tests where applicable to test my new functionality.
|
||||
- [ ] 📖 I've made sure that my contracts are well-documented.
|
||||
- [ ] 🎨 I've run the JS/Solidity linters and fixed any issues (`npm run lint:all:fix`).
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
"plugins": ["security"],
|
||||
"rules": {
|
||||
"quotes": ["error", "double"],
|
||||
"no-empty-blocks": "off",
|
||||
"indentation": ["error", 2],
|
||||
"arg-overflow": ["warning", 3],
|
||||
"security/enforce-explicit-visibility": ["error"],
|
||||
|
||||
@ -10,10 +10,12 @@ cache:
|
||||
env:
|
||||
-
|
||||
- SOLIDITY_COVERAGE=true
|
||||
- SOLC_NIGHTLY=true
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- env: SOLIDITY_COVERAGE=true
|
||||
- env: SOLC_NIGHTLY=true
|
||||
before_script:
|
||||
- truffle version
|
||||
script:
|
||||
|
||||
@ -5,27 +5,26 @@ We really appreciate and value contributions to OpenZeppelin. Please take 5' to
|
||||
|
||||
## Contribution guidelines
|
||||
|
||||
Smart contracts manage value and are highly vulnerable to errors and attacks. We have very strict guidelines, please make sure to review them: ["Contribution guidelines wiki entry"](https://github.com/OpenZeppelin/zeppelin-solidity/wiki/Contrbuting-guidelines).
|
||||
Smart contracts manage value and are highly vulnerable to errors and attacks. We have very strict guidelines, please make sure to review them: ["Contribution guidelines wiki entry"](https://github.com/OpenZeppelin/openzeppelin-solidity/wiki/Contribution-guidelines).
|
||||
|
||||
## Creating Pull Requests (PRs)
|
||||
|
||||
As a contributor, you are expected to fork this repository, work on your own fork and then submit pull requests. The pull requests will be reviewed and eventually merged into the main repo. See ["Fork-a-Repo"](https://help.github.com/articles/fork-a-repo/) for how this works.
|
||||
|
||||
*IMPORTANT*
|
||||
* Please use `rebase` instead of `merge` when updating your fork.
|
||||
* Please see ["Git flow wiki entry"](https://github.com/OpenZeppelin/zeppelin-solidity/wiki/Git-flow) for understanding how to use branches in this repository.
|
||||
* Please see ["Git flow wiki entry"](https://github.com/OpenZeppelin/openzeppelin-solidity/wiki/Git-flow) for understanding how to use branches in this repository.
|
||||
|
||||
## A typical workflow
|
||||
|
||||
1) Make sure your fork is up to date with the main repository:
|
||||
|
||||
```
|
||||
cd zeppelin-solidity
|
||||
cd openzeppelin-solidity
|
||||
git fetch upstream
|
||||
git checkout development
|
||||
git pull --rebase upstream development
|
||||
```
|
||||
NOTE: The directory `zeppelin-solidity` represents your fork's local copy.
|
||||
NOTE: The directory `openzeppelin-solidity` represents your fork's local copy.
|
||||
|
||||
2) Branch out from `development` into `fix/some-bug-#123`:
|
||||
(Postfixing #123 will associate your PR with the issue #123 and make everyone's life easier =D)
|
||||
@ -41,7 +40,7 @@ git commit "Fix some bug #123"
|
||||
git push origin fix/some-bug-#123
|
||||
```
|
||||
|
||||
4) Go to [github.com/OpenZeppelin/zeppelin-solidity](https://github.com/OpenZeppelin/zeppelin-solidity) in your web browser and issue a new pull request.
|
||||
4) Go to [github.com/OpenZeppelin/openzeppelin-solidity](https://github.com/OpenZeppelin/zeppelin-solidity) in your web browser and issue a new pull request.
|
||||
|
||||
*IMPORTANT* Read the PR template very carefully and make sure to follow all the instructions. These instructions
|
||||
refer to some very important conditions that your PR must meet in order to be accepted, such as making sure that all tests pass, JS linting tests pass, solidity linting tests pass, etc.
|
||||
@ -52,8 +51,8 @@ refer to some very important conditions that your PR must meet in order to be ac
|
||||
|
||||
## All set!
|
||||
|
||||
If you have any questions feel free to post them to github.com/OpenZeppelin/zeppelin-solidity/issues.
|
||||
If you have any questions feel free to post them to github.com/OpenZeppelin/openzeppelin-solidity/issues.
|
||||
|
||||
Finally, if you're looking to collaborate and want to find easy tasks to start, look at the issues we marked as ["Good first issue"](https://github.com/OpenZeppelin/zeppelin-solidity/labels/good%20first%20issue).
|
||||
Finally, if you're looking to collaborate and want to find easy tasks to start, look at the issues we marked as ["Good first issue"](https://github.com/OpenZeppelin/openzeppelin-solidity/labels/good%20first%20issue).
|
||||
|
||||
Thanks for your time and code!
|
||||
|
||||
44
README.md
44
README.md
@ -1,7 +1,7 @@
|
||||
# Zeppelin Solidity
|
||||
[](https://www.npmjs.org/package/zeppelin-solidity)
|
||||
[](https://travis-ci.org/OpenZeppelin/zeppelin-solidity)
|
||||
[](https://coveralls.io/github/OpenZeppelin/zeppelin-solidity?branch=master)
|
||||
# OpenZeppelin Solidity
|
||||
[](https://www.npmjs.org/package/openzeppelin-solidity)
|
||||
[](https://travis-ci.org/OpenZeppelin/openzeppelin-solidity)
|
||||
[](https://coveralls.io/github/OpenZeppelin/openzeppelin-solidity?branch=master)
|
||||
|
||||
OpenZeppelin is a library for writing secure [Smart Contracts](https://en.wikipedia.org/wiki/Smart_contract) on Ethereum.
|
||||
|
||||
@ -24,15 +24,15 @@ truffle init
|
||||
To install the OpenZeppelin library, run the following in your Solidity project root directory:
|
||||
```sh
|
||||
npm init -y
|
||||
npm install -E zeppelin-solidity
|
||||
npm install -E openzeppelin-solidity
|
||||
```
|
||||
|
||||
**Note that OpenZeppelin does not currently follow semantic versioning.** You may encounter breaking changes upon a minor version bump. We recommend pinning the version of OpenZeppelin you use, as done by the `-E` (`--save-exact`) option.
|
||||
|
||||
After that, you'll get all the library's contracts in the `node_modules/zeppelin-solidity/contracts` folder. You can use the contracts in the library like so:
|
||||
After that, you'll get all the library's contracts in the `node_modules/openzeppelin-solidity/contracts` folder. You can use the contracts in the library like so:
|
||||
|
||||
```js
|
||||
import 'zeppelin-solidity/contracts/ownership/Ownable.sol';
|
||||
```solidity
|
||||
import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';
|
||||
|
||||
contract MyContract is Ownable {
|
||||
...
|
||||
@ -49,34 +49,16 @@ If you find a security issue, please email [security@openzeppelin.org](mailto:se
|
||||
|
||||
Building a distributed application, protocol or organization with OpenZeppelin?
|
||||
|
||||
- Read documentation: https://zeppelin-solidity.readthedocs.io/en/latest/
|
||||
- Read documentation: https://openzeppelin.org/api/docs/open-zeppelin.html
|
||||
|
||||
- Ask for help and follow progress at: https://slack.openzeppelin.org/
|
||||
|
||||
Interested in contributing to OpenZeppelin?
|
||||
|
||||
- Framework proposal and roadmap: https://medium.com/zeppelin-blog/zeppelin-framework-proposal-and-development-roadmap-fdfa9a3a32ab#.iain47pak
|
||||
- Issue tracker: https://github.com/OpenZeppelin/zeppelin-solidity/issues
|
||||
- Contribution guidelines: https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/CONTRIBUTING.md
|
||||
- Wiki: https://github.com/OpenZeppelin/zeppelin-solidity/wiki
|
||||
|
||||
## Collaborating organizations and audits by OpenZeppelin
|
||||
- [Golem](https://golem.network/)
|
||||
- [Mediachain](http://www.mediachain.io/)
|
||||
- [Truffle](http://truffleframework.com/)
|
||||
- [Firstblood](https://firstblood.io/)
|
||||
- [Rootstock](https://www.rsk.co/)
|
||||
- [Consensys](https://consensys.net/)
|
||||
- [DigixGlobal](https://www.dgx.io/)
|
||||
- [Coinfund](https://coinfund.io/)
|
||||
- [DemocracyEarth](https://democracy.earth/)
|
||||
- [Signatura](https://signatura.co/)
|
||||
- [Ether.camp](http://www.ether.camp/)
|
||||
- [Aragon](https://aragon.one/)
|
||||
- [Wings](https://wings.ai/)
|
||||
|
||||
among others...
|
||||
|
||||
- Issue tracker: https://github.com/OpenZeppelin/openzeppelin-solidity/issues
|
||||
- Contribution guidelines: https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/CONTRIBUTING.md
|
||||
- Wiki: https://github.com/OpenZeppelin/openzeppelin-solidity/wiki
|
||||
|
||||
## License
|
||||
Code released under the [MIT License](https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/LICENSE).
|
||||
Code released under the [MIT License](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/LICENSE).
|
||||
|
||||
2
contracts/.npmignore
Normal file
2
contracts/.npmignore
Normal file
@ -0,0 +1,2 @@
|
||||
mocks
|
||||
examples
|
||||
28
contracts/AddressUtils.sol
Normal file
28
contracts/AddressUtils.sol
Normal file
@ -0,0 +1,28 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
* Utility library of inline functions on addresses
|
||||
*/
|
||||
library AddressUtils {
|
||||
|
||||
/**
|
||||
* Returns whether the target address is a contract
|
||||
* @dev This function will return false if invoked during the constructor of a contract,
|
||||
* as the code is not actually created until after the constructor finishes.
|
||||
* @param addr address to check
|
||||
* @return whether the target address is a contract
|
||||
*/
|
||||
function isContract(address addr) internal view returns (bool) {
|
||||
uint256 size;
|
||||
// XXX Currently there is no better way to check if there is a contract in an address
|
||||
// than to check the size of the code at that address.
|
||||
// See https://ethereum.stackexchange.com/a/14016/36603
|
||||
// for more details about how this works.
|
||||
// TODO Check this again before the Serenity release, because all addresses will be
|
||||
// contracts then.
|
||||
assembly { size := extcodesize(addr) } // solium-disable-line security/no-inline-assembly
|
||||
return size > 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "./payment/PullPayment.sol";
|
||||
@ -30,7 +30,7 @@ contract Bounty is PullPayment, Destructible {
|
||||
function createTarget() public returns(Target) {
|
||||
Target target = Target(deployContract());
|
||||
researchers[target] = msg.sender;
|
||||
TargetCreated(target);
|
||||
emit TargetCreated(target);
|
||||
return target;
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ contract Bounty is PullPayment, Destructible {
|
||||
require(researcher != 0);
|
||||
// Check Target contract invariants
|
||||
require(!target.checkInvariant());
|
||||
asyncSend(researcher, this.balance);
|
||||
asyncSend(researcher, address(this).balance);
|
||||
claimed = true;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
@ -61,7 +61,8 @@ contract DayLimit {
|
||||
* @return uint256 of today's index.
|
||||
*/
|
||||
function today() private view returns (uint256) {
|
||||
return now / 1 days;
|
||||
// solium-disable-next-line security/no-block-members
|
||||
return block.timestamp / 1 days;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,30 +1,41 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
* @title Eliptic curve signature operations
|
||||
*
|
||||
* @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
|
||||
*
|
||||
* TODO Remove this library once solidity supports passing a signature to ecrecover.
|
||||
* See https://github.com/ethereum/solidity/issues/864
|
||||
*
|
||||
*/
|
||||
|
||||
library ECRecovery {
|
||||
|
||||
/**
|
||||
* @dev Recover signer address from a message by using his signature
|
||||
* @dev Recover signer address from a message by using their signature
|
||||
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
|
||||
* @param sig bytes signature, the signature is generated using web3.eth.sign()
|
||||
*/
|
||||
function recover(bytes32 hash, bytes sig) public pure returns (address) {
|
||||
function recover(bytes32 hash, bytes sig)
|
||||
internal
|
||||
pure
|
||||
returns (address)
|
||||
{
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
uint8 v;
|
||||
|
||||
//Check the signature length
|
||||
// Check the signature length
|
||||
if (sig.length != 65) {
|
||||
return (address(0));
|
||||
}
|
||||
|
||||
// Divide the signature in r, s and v variables
|
||||
// ecrecover takes the signature parameters, and the only way to get them
|
||||
// currently is to use assembly.
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
r := mload(add(sig, 32))
|
||||
s := mload(add(sig, 64))
|
||||
@ -40,8 +51,26 @@ library ECRecovery {
|
||||
if (v != 27 && v != 28) {
|
||||
return (address(0));
|
||||
} else {
|
||||
// solium-disable-next-line arg-overflow
|
||||
return ecrecover(hash, v, r, s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* toEthSignedMessageHash
|
||||
* @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
|
||||
* @dev and hash the result
|
||||
*/
|
||||
function toEthSignedMessageHash(bytes32 hash)
|
||||
internal
|
||||
pure
|
||||
returns (bytes32)
|
||||
{
|
||||
// 32 is the length in bytes of hash,
|
||||
// enforced by the type signature above
|
||||
return keccak256(
|
||||
"\x19Ethereum Signed Message:\n32",
|
||||
hash
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
@ -23,7 +23,7 @@ contract LimitBalance {
|
||||
* @dev Checks if limit was reached. Case true, it throws.
|
||||
*/
|
||||
modifier limitedPayable() {
|
||||
require(this.balance <= limit);
|
||||
require(address(this).balance <= limit);
|
||||
_;
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/*
|
||||
@ -14,20 +14,11 @@ library MerkleProof {
|
||||
* @param _root Merkle root
|
||||
* @param _leaf Leaf of Merkle tree
|
||||
*/
|
||||
function verifyProof(bytes _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {
|
||||
// Check if proof length is a multiple of 32
|
||||
if (_proof.length % 32 != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes32 proofElement;
|
||||
function verifyProof(bytes32[] _proof, bytes32 _root, bytes32 _leaf) internal pure returns (bool) {
|
||||
bytes32 computedHash = _leaf;
|
||||
|
||||
for (uint256 i = 32; i <= _proof.length; i += 32) {
|
||||
assembly {
|
||||
// Load the current element of the proof
|
||||
proofElement := mload(add(_proof, i))
|
||||
}
|
||||
for (uint256 i = 0; i < _proof.length; i++) {
|
||||
bytes32 proofElement = _proof[i];
|
||||
|
||||
if (computedHash < proofElement) {
|
||||
// Hash(current computed hash + current element of the proof)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
@ -12,7 +12,7 @@ contract ReentrancyGuard {
|
||||
/**
|
||||
* @dev We use a single lock for the whole contract.
|
||||
*/
|
||||
bool private reentrancy_lock = false;
|
||||
bool private reentrancyLock = false;
|
||||
|
||||
/**
|
||||
* @dev Prevents a contract from calling itself, directly or indirectly.
|
||||
@ -23,10 +23,10 @@ contract ReentrancyGuard {
|
||||
* wrapper marked as `nonReentrant`.
|
||||
*/
|
||||
modifier nonReentrant() {
|
||||
require(!reentrancy_lock);
|
||||
reentrancy_lock = true;
|
||||
require(!reentrancyLock);
|
||||
reentrancyLock = true;
|
||||
_;
|
||||
reentrancy_lock = false;
|
||||
reentrancyLock = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
90
contracts/access/SignatureBouncer.sol
Normal file
90
contracts/access/SignatureBouncer.sol
Normal file
@ -0,0 +1,90 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../ownership/rbac/RBAC.sol";
|
||||
import "../ECRecovery.sol";
|
||||
|
||||
/**
|
||||
* @title SignatureBouncer
|
||||
* @author PhABC and Shrugs
|
||||
* @dev Bouncer allows users to submit a signature as a permission to do an action.
|
||||
* @dev If the signature is from one of the authorized bouncer addresses, the signature
|
||||
* @dev is valid. The owner of the contract adds/removes bouncers.
|
||||
* @dev Bouncer addresses can be individual servers signing grants or different
|
||||
* @dev users within a decentralized club that have permission to invite other members.
|
||||
* @dev
|
||||
* @dev This technique is useful for whitelists and airdrops; instead of putting all
|
||||
* @dev valid addresses on-chain, simply sign a grant of the form
|
||||
* @dev keccak256(`:contractAddress` + `:granteeAddress`) using a valid bouncer address.
|
||||
* @dev Then restrict access to your crowdsale/whitelist/airdrop using the
|
||||
* @dev `onlyValidSignature` modifier (or implement your own using isValidSignature).
|
||||
* @dev
|
||||
* @dev See the tests Bouncer.test.js for specific usage examples.
|
||||
*/
|
||||
contract SignatureBouncer is Ownable, RBAC {
|
||||
using ECRecovery for bytes32;
|
||||
|
||||
string public constant ROLE_BOUNCER = "bouncer";
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature of a bouncer was provided
|
||||
*/
|
||||
modifier onlyValidSignature(bytes _sig)
|
||||
{
|
||||
require(isValidSignature(msg.sender, _sig));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev allows the owner to add additional bouncer addresses
|
||||
*/
|
||||
function addBouncer(address _bouncer)
|
||||
onlyOwner
|
||||
public
|
||||
{
|
||||
require(_bouncer != address(0));
|
||||
addRole(_bouncer, ROLE_BOUNCER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev allows the owner to remove bouncer addresses
|
||||
*/
|
||||
function removeBouncer(address _bouncer)
|
||||
onlyOwner
|
||||
public
|
||||
{
|
||||
require(_bouncer != address(0));
|
||||
removeRole(_bouncer, ROLE_BOUNCER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + sender` from a bouncer?
|
||||
* @return bool
|
||||
*/
|
||||
function isValidSignature(address _address, bytes _sig)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return isValidDataHash(
|
||||
keccak256(address(this), _address),
|
||||
_sig
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev internal function to convert a hash to an eth signed message
|
||||
* @dev and then recover the signature and check it against the bouncer role
|
||||
* @return bool
|
||||
*/
|
||||
function isValidDataHash(bytes32 hash, bytes _sig)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
address signer = hash
|
||||
.toEthSignedMessageHash()
|
||||
.recover(_sig);
|
||||
return hasRole(signer, ROLE_BOUNCER);
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
import "./Crowdsale.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title CappedCrowdsale
|
||||
* @dev Extension of Crowdsale with a max amount of funds raised
|
||||
*/
|
||||
contract CappedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public cap;
|
||||
|
||||
function CappedCrowdsale(uint256 _cap) public {
|
||||
require(_cap > 0);
|
||||
cap = _cap;
|
||||
}
|
||||
|
||||
// overriding Crowdsale#hasEnded to add cap logic
|
||||
// @return true if crowdsale event has ended
|
||||
function hasEnded() public view returns (bool) {
|
||||
bool capReached = weiRaised >= cap;
|
||||
return capReached || super.hasEnded();
|
||||
}
|
||||
|
||||
// overriding Crowdsale#validPurchase to add extra cap logic
|
||||
// @return true if investors can buy at the moment
|
||||
function validPurchase() internal view returns (bool) {
|
||||
bool withinCap = weiRaised.add(msg.value) <= cap;
|
||||
return withinCap && super.validPurchase();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,38 +1,38 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Crowdsale
|
||||
* @dev Crowdsale is a base contract for managing a token crowdsale.
|
||||
* Crowdsales have a start and end timestamps, where investors can make
|
||||
* token purchases and the crowdsale will assign them tokens based
|
||||
* on a token per ETH rate. Funds collected are forwarded to a wallet
|
||||
* as they arrive.
|
||||
* @dev Crowdsale is a base contract for managing a token crowdsale,
|
||||
* allowing investors to purchase tokens with ether. This contract implements
|
||||
* such functionality in its most fundamental form and can be extended to provide additional
|
||||
* functionality and/or custom behavior.
|
||||
* The external interface represents the basic interface for purchasing tokens, and conform
|
||||
* the base architecture for crowdsales. They are *not* intended to be modified / overriden.
|
||||
* The internal interface conforms the extensible and modifiable surface of crowdsales. Override
|
||||
* the methods to add functionality. Consider using 'super' where appropiate to concatenate
|
||||
* behavior.
|
||||
*/
|
||||
contract Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
// The token being sold
|
||||
MintableToken public token;
|
||||
ERC20 public token;
|
||||
|
||||
// start and end timestamps where investments are allowed (both inclusive)
|
||||
uint256 public startTime;
|
||||
uint256 public endTime;
|
||||
|
||||
// address where funds are collected
|
||||
// Address where funds are collected
|
||||
address public wallet;
|
||||
|
||||
// how many token units a buyer gets per wei
|
||||
// How many token units a buyer gets per wei
|
||||
uint256 public rate;
|
||||
|
||||
// amount of raised money in wei
|
||||
// Amount of wei raised
|
||||
uint256 public weiRaised;
|
||||
|
||||
/**
|
||||
* event for token purchase logging
|
||||
* Event for token purchase logging
|
||||
* @param purchaser who paid for the tokens
|
||||
* @param beneficiary who got the tokens
|
||||
* @param value weis paid for purchase
|
||||
@ -40,71 +40,124 @@ contract Crowdsale {
|
||||
*/
|
||||
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
|
||||
|
||||
|
||||
function Crowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet) public {
|
||||
require(_startTime >= now);
|
||||
require(_endTime >= _startTime);
|
||||
/**
|
||||
* @param _rate Number of token units a buyer gets per wei
|
||||
* @param _wallet Address where collected funds will be forwarded to
|
||||
* @param _token Address of the token being sold
|
||||
*/
|
||||
function Crowdsale(uint256 _rate, address _wallet, ERC20 _token) public {
|
||||
require(_rate > 0);
|
||||
require(_wallet != address(0));
|
||||
require(_token != address(0));
|
||||
|
||||
token = createTokenContract();
|
||||
startTime = _startTime;
|
||||
endTime = _endTime;
|
||||
rate = _rate;
|
||||
wallet = _wallet;
|
||||
token = _token;
|
||||
}
|
||||
|
||||
// fallback function can be used to buy tokens
|
||||
// -----------------------------------------
|
||||
// Crowdsale external interface
|
||||
// -----------------------------------------
|
||||
|
||||
/**
|
||||
* @dev fallback function ***DO NOT OVERRIDE***
|
||||
*/
|
||||
function () external payable {
|
||||
buyTokens(msg.sender);
|
||||
}
|
||||
|
||||
// low level token purchase function
|
||||
function buyTokens(address beneficiary) public payable {
|
||||
require(beneficiary != address(0));
|
||||
require(validPurchase());
|
||||
/**
|
||||
* @dev low level token purchase ***DO NOT OVERRIDE***
|
||||
* @param _beneficiary Address performing the token purchase
|
||||
*/
|
||||
function buyTokens(address _beneficiary) public payable {
|
||||
|
||||
uint256 weiAmount = msg.value;
|
||||
_preValidatePurchase(_beneficiary, weiAmount);
|
||||
|
||||
// calculate token amount to be created
|
||||
uint256 tokens = getTokenAmount(weiAmount);
|
||||
uint256 tokens = _getTokenAmount(weiAmount);
|
||||
|
||||
// update state
|
||||
weiRaised = weiRaised.add(weiAmount);
|
||||
|
||||
token.mint(beneficiary, tokens);
|
||||
TokenPurchase(msg.sender, beneficiary, weiAmount, tokens);
|
||||
_processPurchase(_beneficiary, tokens);
|
||||
emit TokenPurchase(
|
||||
msg.sender,
|
||||
_beneficiary,
|
||||
weiAmount,
|
||||
tokens
|
||||
);
|
||||
|
||||
forwardFunds();
|
||||
_updatePurchasingState(_beneficiary, weiAmount);
|
||||
|
||||
_forwardFunds();
|
||||
_postValidatePurchase(_beneficiary, weiAmount);
|
||||
}
|
||||
|
||||
// @return true if crowdsale event has ended
|
||||
function hasEnded() public view returns (bool) {
|
||||
return now > endTime;
|
||||
// -----------------------------------------
|
||||
// Internal interface (extensible)
|
||||
// -----------------------------------------
|
||||
|
||||
/**
|
||||
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations.
|
||||
* @param _beneficiary Address performing the token purchase
|
||||
* @param _weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
|
||||
require(_beneficiary != address(0));
|
||||
require(_weiAmount != 0);
|
||||
}
|
||||
|
||||
// creates the token to be sold.
|
||||
// override this method to have crowdsale of a specific mintable token.
|
||||
function createTokenContract() internal returns (MintableToken) {
|
||||
return new MintableToken();
|
||||
/**
|
||||
* @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met.
|
||||
* @param _beneficiary Address performing the token purchase
|
||||
* @param _weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _postValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
|
||||
// optional override
|
||||
}
|
||||
|
||||
// Override this method to have a way to add business logic to your crowdsale when buying
|
||||
function getTokenAmount(uint256 weiAmount) internal view returns(uint256) {
|
||||
return weiAmount.mul(rate);
|
||||
/**
|
||||
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
|
||||
* @param _beneficiary Address performing the token purchase
|
||||
* @param _tokenAmount Number of tokens to be emitted
|
||||
*/
|
||||
function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
|
||||
token.transfer(_beneficiary, _tokenAmount);
|
||||
}
|
||||
|
||||
// send ether to the fund collection wallet
|
||||
// override to create custom fund forwarding mechanisms
|
||||
function forwardFunds() internal {
|
||||
/**
|
||||
* @dev Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens.
|
||||
* @param _beneficiary Address receiving the tokens
|
||||
* @param _tokenAmount Number of tokens to be purchased
|
||||
*/
|
||||
function _processPurchase(address _beneficiary, uint256 _tokenAmount) internal {
|
||||
_deliverTokens(_beneficiary, _tokenAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.)
|
||||
* @param _beneficiary Address receiving the tokens
|
||||
* @param _weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _updatePurchasingState(address _beneficiary, uint256 _weiAmount) internal {
|
||||
// optional override
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Override to extend the way in which ether is converted to tokens.
|
||||
* @param _weiAmount Value in wei to be converted into tokens
|
||||
* @return Number of tokens that can be purchased with the specified _weiAmount
|
||||
*/
|
||||
function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
|
||||
return _weiAmount.mul(rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Determines how ETH is stored/forwarded on purchases.
|
||||
*/
|
||||
function _forwardFunds() internal {
|
||||
wallet.transfer(msg.value);
|
||||
}
|
||||
|
||||
// @return true if the transaction can buy tokens
|
||||
function validPurchase() internal view returns (bool) {
|
||||
bool withinPeriod = now >= startTime && now <= endTime;
|
||||
bool nonZeroPurchase = msg.value != 0;
|
||||
return withinPeriod && nonZeroPurchase;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
import "../ownership/Ownable.sol";
|
||||
import "./Crowdsale.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../../ownership/Ownable.sol";
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
|
||||
|
||||
/**
|
||||
@ -10,7 +10,7 @@ import "./Crowdsale.sol";
|
||||
* @dev Extension of Crowdsale where an owner can do extra work
|
||||
* after finishing.
|
||||
*/
|
||||
contract FinalizableCrowdsale is Crowdsale, Ownable {
|
||||
contract FinalizableCrowdsale is TimedCrowdsale, Ownable {
|
||||
using SafeMath for uint256;
|
||||
|
||||
bool public isFinalized = false;
|
||||
@ -23,10 +23,10 @@ contract FinalizableCrowdsale is Crowdsale, Ownable {
|
||||
*/
|
||||
function finalize() onlyOwner public {
|
||||
require(!isFinalized);
|
||||
require(hasEnded());
|
||||
require(hasClosed());
|
||||
|
||||
finalization();
|
||||
Finalized();
|
||||
emit Finalized();
|
||||
|
||||
isFinalized = true;
|
||||
}
|
||||
@ -38,4 +38,5 @@ contract FinalizableCrowdsale is Crowdsale, Ownable {
|
||||
*/
|
||||
function finalization() internal {
|
||||
}
|
||||
|
||||
}
|
||||
37
contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol
Normal file
37
contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol
Normal file
@ -0,0 +1,37 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../token/ERC20/ERC20.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title PostDeliveryCrowdsale
|
||||
* @dev Crowdsale that locks tokens from withdrawal until it ends.
|
||||
*/
|
||||
contract PostDeliveryCrowdsale is TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping(address => uint256) public balances;
|
||||
|
||||
/**
|
||||
* @dev Withdraw tokens only after crowdsale ends.
|
||||
*/
|
||||
function withdrawTokens() public {
|
||||
require(hasClosed());
|
||||
uint256 amount = balances[msg.sender];
|
||||
require(amount > 0);
|
||||
balances[msg.sender] = 0;
|
||||
_deliverTokens(msg.sender, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent by storing balances instead of issuing tokens right away.
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _tokenAmount Amount of tokens purchased
|
||||
*/
|
||||
function _processPurchase(address _beneficiary, uint256 _tokenAmount) internal {
|
||||
balances[_beneficiary] = balances[_beneficiary].add(_tokenAmount);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "./FinalizableCrowdsale.sol";
|
||||
import "./RefundVault.sol";
|
||||
import "./utils/RefundVault.sol";
|
||||
|
||||
|
||||
/**
|
||||
@ -21,13 +21,19 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
// refund vault used to hold funds while crowdsale is running
|
||||
RefundVault public vault;
|
||||
|
||||
/**
|
||||
* @dev Constructor, creates RefundVault.
|
||||
* @param _goal Funding goal
|
||||
*/
|
||||
function RefundableCrowdsale(uint256 _goal) public {
|
||||
require(_goal > 0);
|
||||
vault = new RefundVault(wallet);
|
||||
goal = _goal;
|
||||
}
|
||||
|
||||
// if crowdsale is unsuccessful, investors can claim refunds here
|
||||
/**
|
||||
* @dev Investors can claim refunds here if crowdsale is unsuccessful
|
||||
*/
|
||||
function claimRefund() public {
|
||||
require(isFinalized);
|
||||
require(!goalReached());
|
||||
@ -35,11 +41,17 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
vault.refund(msg.sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether funding goal was reached.
|
||||
* @return Whether funding goal was reached
|
||||
*/
|
||||
function goalReached() public view returns (bool) {
|
||||
return weiRaised >= goal;
|
||||
}
|
||||
|
||||
// vault finalization task, called when owner calls finalize()
|
||||
/**
|
||||
* @dev vault finalization task, called when owner calls finalize()
|
||||
*/
|
||||
function finalization() internal {
|
||||
if (goalReached()) {
|
||||
vault.close();
|
||||
@ -50,10 +62,10 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
super.finalization();
|
||||
}
|
||||
|
||||
// We're overriding the fund forwarding from Crowdsale.
|
||||
// In addition to sending the funds, we want to call
|
||||
// the RefundVault deposit function
|
||||
function forwardFunds() internal {
|
||||
/**
|
||||
* @dev Overrides Crowdsale fund forwarding, sending funds to vault.
|
||||
*/
|
||||
function _forwardFunds() internal {
|
||||
vault.deposit.value(msg.value)(msg.sender);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../../../math/SafeMath.sol";
|
||||
import "../../../ownership/Ownable.sol";
|
||||
|
||||
|
||||
/**
|
||||
@ -23,12 +23,18 @@ contract RefundVault is Ownable {
|
||||
event RefundsEnabled();
|
||||
event Refunded(address indexed beneficiary, uint256 weiAmount);
|
||||
|
||||
/**
|
||||
* @param _wallet Vault address
|
||||
*/
|
||||
function RefundVault(address _wallet) public {
|
||||
require(_wallet != address(0));
|
||||
wallet = _wallet;
|
||||
state = State.Active;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param investor Investor address
|
||||
*/
|
||||
function deposit(address investor) onlyOwner public payable {
|
||||
require(state == State.Active);
|
||||
deposited[investor] = deposited[investor].add(msg.value);
|
||||
@ -37,21 +43,24 @@ contract RefundVault is Ownable {
|
||||
function close() onlyOwner public {
|
||||
require(state == State.Active);
|
||||
state = State.Closed;
|
||||
Closed();
|
||||
wallet.transfer(this.balance);
|
||||
emit Closed();
|
||||
wallet.transfer(address(this).balance);
|
||||
}
|
||||
|
||||
function enableRefunds() onlyOwner public {
|
||||
require(state == State.Active);
|
||||
state = State.Refunding;
|
||||
RefundsEnabled();
|
||||
emit RefundsEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param investor Investor address
|
||||
*/
|
||||
function refund(address investor) public {
|
||||
require(state == State.Refunding);
|
||||
uint256 depositedValue = deposited[investor];
|
||||
deposited[investor] = 0;
|
||||
investor.transfer(depositedValue);
|
||||
Refunded(investor, depositedValue);
|
||||
emit Refunded(investor, depositedValue);
|
||||
}
|
||||
}
|
||||
42
contracts/crowdsale/emission/AllowanceCrowdsale.sol
Normal file
42
contracts/crowdsale/emission/AllowanceCrowdsale.sol
Normal file
@ -0,0 +1,42 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/ERC20.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title AllowanceCrowdsale
|
||||
* @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale.
|
||||
*/
|
||||
contract AllowanceCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
address public tokenWallet;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes token wallet address.
|
||||
* @param _tokenWallet Address holding the tokens, which has approved allowance to the crowdsale
|
||||
*/
|
||||
function AllowanceCrowdsale(address _tokenWallet) public {
|
||||
require(_tokenWallet != address(0));
|
||||
tokenWallet = _tokenWallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks the amount of tokens left in the allowance.
|
||||
* @return Amount of tokens left in the allowance
|
||||
*/
|
||||
function remainingTokens() public view returns (uint256) {
|
||||
return token.allowance(tokenWallet, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent behavior by transferring tokens from wallet.
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _tokenAmount Amount of tokens purchased
|
||||
*/
|
||||
function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
|
||||
token.transferFrom(tokenWallet, _beneficiary, _tokenAmount);
|
||||
}
|
||||
}
|
||||
22
contracts/crowdsale/emission/MintedCrowdsale.sol
Normal file
22
contracts/crowdsale/emission/MintedCrowdsale.sol
Normal file
@ -0,0 +1,22 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/MintableToken.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title MintedCrowdsale
|
||||
* @dev Extension of Crowdsale contract whose tokens are minted in each purchase.
|
||||
* Token ownership should be transferred to MintedCrowdsale for minting.
|
||||
*/
|
||||
contract MintedCrowdsale is Crowdsale {
|
||||
|
||||
/**
|
||||
* @dev Overrides delivery by minting tokens upon purchase.
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _tokenAmount Number of tokens to be minted
|
||||
*/
|
||||
function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
|
||||
require(MintableToken(token).mint(_beneficiary, _tokenAmount));
|
||||
}
|
||||
}
|
||||
54
contracts/crowdsale/price/IncreasingPriceCrowdsale.sol
Normal file
54
contracts/crowdsale/price/IncreasingPriceCrowdsale.sol
Normal file
@ -0,0 +1,54 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title IncreasingPriceCrowdsale
|
||||
* @dev Extension of Crowdsale contract that increases the price of tokens linearly in time.
|
||||
* Note that what should be provided to the constructor is the initial and final _rates_, that is,
|
||||
* the amount of tokens per wei contributed. Thus, the initial rate must be greater than the final rate.
|
||||
*/
|
||||
contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public initialRate;
|
||||
uint256 public finalRate;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes intial and final rates of tokens received per wei contributed.
|
||||
* @param _initialRate Number of tokens a buyer gets per wei at the start of the crowdsale
|
||||
* @param _finalRate Number of tokens a buyer gets per wei at the end of the crowdsale
|
||||
*/
|
||||
function IncreasingPriceCrowdsale(uint256 _initialRate, uint256 _finalRate) public {
|
||||
require(_initialRate >= _finalRate);
|
||||
require(_finalRate > 0);
|
||||
initialRate = _initialRate;
|
||||
finalRate = _finalRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the rate of tokens per wei at the present time.
|
||||
* Note that, as price _increases_ with time, the rate _decreases_.
|
||||
* @return The number of tokens a buyer gets per wei at a given time
|
||||
*/
|
||||
function getCurrentRate() public view returns (uint256) {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
uint256 elapsedTime = block.timestamp.sub(openingTime);
|
||||
uint256 timeRange = closingTime.sub(openingTime);
|
||||
uint256 rateRange = initialRate.sub(finalRate);
|
||||
return initialRate.sub(elapsedTime.mul(rateRange).div(timeRange));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent method taking into account variable rate.
|
||||
* @param _weiAmount The value in wei to be converted into tokens
|
||||
* @return The number of tokens _weiAmount wei will buy at present time
|
||||
*/
|
||||
function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
|
||||
uint256 currentRate = getCurrentRate();
|
||||
return currentRate.mul(_weiAmount);
|
||||
}
|
||||
|
||||
}
|
||||
43
contracts/crowdsale/validation/CappedCrowdsale.sol
Normal file
43
contracts/crowdsale/validation/CappedCrowdsale.sol
Normal file
@ -0,0 +1,43 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title CappedCrowdsale
|
||||
* @dev Crowdsale with a limit for total contributions.
|
||||
*/
|
||||
contract CappedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public cap;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes maximum amount of wei accepted in the crowdsale.
|
||||
* @param _cap Max amount of wei to be contributed
|
||||
*/
|
||||
function CappedCrowdsale(uint256 _cap) public {
|
||||
require(_cap > 0);
|
||||
cap = _cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether the cap has been reached.
|
||||
* @return Whether the cap was reached
|
||||
*/
|
||||
function capReached() public view returns (bool) {
|
||||
return weiRaised >= cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring purchase to respect the funding cap.
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
require(weiRaised.add(_weiAmount) <= cap);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
import "../../ownership/Ownable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title IndividuallyCappedCrowdsale
|
||||
* @dev Crowdsale with per-user caps.
|
||||
*/
|
||||
contract IndividuallyCappedCrowdsale is Crowdsale, Ownable {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping(address => uint256) public contributions;
|
||||
mapping(address => uint256) public caps;
|
||||
|
||||
/**
|
||||
* @dev Sets a specific user's maximum contribution.
|
||||
* @param _beneficiary Address to be capped
|
||||
* @param _cap Wei limit for individual contribution
|
||||
*/
|
||||
function setUserCap(address _beneficiary, uint256 _cap) external onlyOwner {
|
||||
caps[_beneficiary] = _cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sets a group of users' maximum contribution.
|
||||
* @param _beneficiaries List of addresses to be capped
|
||||
* @param _cap Wei limit for individual contribution
|
||||
*/
|
||||
function setGroupCap(address[] _beneficiaries, uint256 _cap) external onlyOwner {
|
||||
for (uint256 i = 0; i < _beneficiaries.length; i++) {
|
||||
caps[_beneficiaries[i]] = _cap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the cap of a specific user.
|
||||
* @param _beneficiary Address whose cap is to be checked
|
||||
* @return Current cap for individual user
|
||||
*/
|
||||
function getUserCap(address _beneficiary) public view returns (uint256) {
|
||||
return caps[_beneficiary];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the amount contributed so far by a sepecific user.
|
||||
* @param _beneficiary Address of contributor
|
||||
* @return User contribution so far
|
||||
*/
|
||||
function getUserContribution(address _beneficiary) public view returns (uint256) {
|
||||
return contributions[_beneficiary];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring purchase to respect the user's funding cap.
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
require(contributions[_beneficiary].add(_weiAmount) <= caps[_beneficiary]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior to update user contributions
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _updatePurchasingState(address _beneficiary, uint256 _weiAmount) internal {
|
||||
super._updatePurchasingState(_beneficiary, _weiAmount);
|
||||
contributions[_beneficiary] = contributions[_beneficiary].add(_weiAmount);
|
||||
}
|
||||
|
||||
}
|
||||
58
contracts/crowdsale/validation/TimedCrowdsale.sol
Normal file
58
contracts/crowdsale/validation/TimedCrowdsale.sol
Normal file
@ -0,0 +1,58 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title TimedCrowdsale
|
||||
* @dev Crowdsale accepting contributions only within a time frame.
|
||||
*/
|
||||
contract TimedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public openingTime;
|
||||
uint256 public closingTime;
|
||||
|
||||
/**
|
||||
* @dev Reverts if not in crowdsale time range.
|
||||
*/
|
||||
modifier onlyWhileOpen {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
require(block.timestamp >= openingTime && block.timestamp <= closingTime);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes crowdsale opening and closing times.
|
||||
* @param _openingTime Crowdsale opening time
|
||||
* @param _closingTime Crowdsale closing time
|
||||
*/
|
||||
function TimedCrowdsale(uint256 _openingTime, uint256 _closingTime) public {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
require(_openingTime >= block.timestamp);
|
||||
require(_closingTime >= _openingTime);
|
||||
|
||||
openingTime = _openingTime;
|
||||
closingTime = _closingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether the period in which the crowdsale is open has already elapsed.
|
||||
* @return Whether crowdsale period has elapsed
|
||||
*/
|
||||
function hasClosed() public view returns (bool) {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
return block.timestamp > closingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring to be within contributing period
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal onlyWhileOpen {
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
|
||||
}
|
||||
58
contracts/crowdsale/validation/WhitelistedCrowdsale.sol
Normal file
58
contracts/crowdsale/validation/WhitelistedCrowdsale.sol
Normal file
@ -0,0 +1,58 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../ownership/Ownable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title WhitelistedCrowdsale
|
||||
* @dev Crowdsale in which only whitelisted users can contribute.
|
||||
*/
|
||||
contract WhitelistedCrowdsale is Crowdsale, Ownable {
|
||||
|
||||
mapping(address => bool) public whitelist;
|
||||
|
||||
/**
|
||||
* @dev Reverts if beneficiary is not whitelisted. Can be used when extending this contract.
|
||||
*/
|
||||
modifier isWhitelisted(address _beneficiary) {
|
||||
require(whitelist[_beneficiary]);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Adds single address to whitelist.
|
||||
* @param _beneficiary Address to be added to the whitelist
|
||||
*/
|
||||
function addToWhitelist(address _beneficiary) external onlyOwner {
|
||||
whitelist[_beneficiary] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Adds list of addresses to whitelist. Not overloaded due to limitations with truffle testing.
|
||||
* @param _beneficiaries Addresses to be added to the whitelist
|
||||
*/
|
||||
function addManyToWhitelist(address[] _beneficiaries) external onlyOwner {
|
||||
for (uint256 i = 0; i < _beneficiaries.length; i++) {
|
||||
whitelist[_beneficiaries[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Removes single address from whitelist.
|
||||
* @param _beneficiary Address to be removed to the whitelist
|
||||
*/
|
||||
function removeFromWhitelist(address _beneficiary) external onlyOwner {
|
||||
whitelist[_beneficiary] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring beneficiary to be in whitelist.
|
||||
* @param _beneficiary Token beneficiary
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal isWhitelisted(_beneficiary) {
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../crowdsale/CappedCrowdsale.sol";
|
||||
import "../crowdsale/RefundableCrowdsale.sol";
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||
import "../crowdsale/emission/MintedCrowdsale.sol";
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
|
||||
|
||||
@ -30,21 +31,25 @@ contract SampleCrowdsaleToken is MintableToken {
|
||||
* After adding multiple features it's good practice to run integration tests
|
||||
* to ensure that subcontracts works together as intended.
|
||||
*/
|
||||
contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale {
|
||||
contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsale {
|
||||
|
||||
function SampleCrowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, uint256 _goal, uint256 _cap, address _wallet) public
|
||||
function SampleCrowdsale(
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
uint256 _cap,
|
||||
MintableToken _token,
|
||||
uint256 _goal
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
CappedCrowdsale(_cap)
|
||||
FinalizableCrowdsale()
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
RefundableCrowdsale(_goal)
|
||||
Crowdsale(_startTime, _endTime, _rate, _wallet)
|
||||
{
|
||||
//As goal needs to be met for a successful crowdsale
|
||||
//the value needs to less or equal than a cap which is limit for accepted funds
|
||||
require(_goal <= _cap);
|
||||
}
|
||||
|
||||
function createTokenContract() internal returns (MintableToken) {
|
||||
return new SampleCrowdsaleToken();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../ownership/Heritable.sol";
|
||||
|
||||
@ -20,12 +20,12 @@ contract SimpleSavingsWallet is Heritable {
|
||||
|
||||
|
||||
function SimpleSavingsWallet(uint256 _heartbeatTimeout) Heritable(_heartbeatTimeout) public {}
|
||||
|
||||
|
||||
/**
|
||||
* @dev wallet can receive funds.
|
||||
*/
|
||||
function () public payable {
|
||||
Received(msg.sender, msg.value, this.balance);
|
||||
emit Received(msg.sender, msg.value, address(this).balance);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -35,6 +35,6 @@ contract SimpleSavingsWallet is Heritable {
|
||||
require(payee != 0 && payee != address(this));
|
||||
require(amount > 0);
|
||||
payee.transfer(amount);
|
||||
Sent(payee, amount, this.balance);
|
||||
emit Sent(payee, amount, address(this).balance);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
@ -24,7 +24,7 @@ contract SimpleToken is StandardToken {
|
||||
function SimpleToken() public {
|
||||
totalSupply_ = INITIAL_SUPPLY;
|
||||
balances[msg.sender] = INITIAL_SUPPLY;
|
||||
Transfer(0x0, msg.sender, INITIAL_SUPPLY);
|
||||
emit Transfer(0x0, msg.sender, INITIAL_SUPPLY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Migrations
|
||||
* @dev This is a truffle contract, needed for truffle integration, not meant for use by Zeppelin users.
|
||||
*/
|
||||
contract Migrations is Ownable {
|
||||
uint256 public lastCompletedMigration;
|
||||
|
||||
function setCompleted(uint256 completed) onlyOwner public {
|
||||
lastCompletedMigration = completed;
|
||||
}
|
||||
|
||||
function upgrade(address newAddress) onlyOwner public {
|
||||
Migrations upgraded = Migrations(newAddress);
|
||||
upgraded.setCompleted(lastCompletedMigration);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
@ -36,7 +36,7 @@ contract Pausable is Ownable {
|
||||
*/
|
||||
function pause() onlyOwner whenNotPaused public {
|
||||
paused = true;
|
||||
Pause();
|
||||
emit Pause();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,6 +44,6 @@ contract Pausable is Ownable {
|
||||
*/
|
||||
function unpause() onlyOwner whenPaused public {
|
||||
paused = false;
|
||||
Unpause();
|
||||
emit Unpause();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../token/ERC20/ERC20Basic.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
@ -10,11 +10,11 @@ library SafeMath {
|
||||
/**
|
||||
* @dev Multiplies two numbers, throws on overflow.
|
||||
*/
|
||||
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
uint256 c = a * b;
|
||||
c = a * b;
|
||||
assert(c / a == b);
|
||||
return c;
|
||||
}
|
||||
@ -24,13 +24,13 @@ library SafeMath {
|
||||
*/
|
||||
function div(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// assert(b > 0); // Solidity automatically throws when dividing by 0
|
||||
uint256 c = a / b;
|
||||
// uint256 c = a / b;
|
||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
||||
return c;
|
||||
return a / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
|
||||
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
|
||||
*/
|
||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
assert(b <= a);
|
||||
@ -40,8 +40,8 @@ library SafeMath {
|
||||
/**
|
||||
* @dev Adds two numbers, throws on overflow.
|
||||
*/
|
||||
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
uint256 c = a + b;
|
||||
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
|
||||
c = a + b;
|
||||
assert(c >= a);
|
||||
return c;
|
||||
}
|
||||
|
||||
21
contracts/mocks/AllowanceCrowdsaleImpl.sol
Normal file
21
contracts/mocks/AllowanceCrowdsaleImpl.sol
Normal file
@ -0,0 +1,21 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/emission/AllowanceCrowdsale.sol";
|
||||
|
||||
|
||||
contract AllowanceCrowdsaleImpl is AllowanceCrowdsale {
|
||||
|
||||
function AllowanceCrowdsaleImpl (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token,
|
||||
address _tokenWallet
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
AllowanceCrowdsale(_tokenWallet)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../token/ERC20/BasicToken.sol";
|
||||
|
||||
22
contracts/mocks/BouncerMock.sol
Normal file
22
contracts/mocks/BouncerMock.sol
Normal file
@ -0,0 +1,22 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import "../access/SignatureBouncer.sol";
|
||||
|
||||
|
||||
contract SignatureBouncerMock is SignatureBouncer {
|
||||
function checkValidSignature(address _address, bytes _sig)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return isValidSignature(_address, _sig);
|
||||
}
|
||||
|
||||
function onlyWithValidSignature(bytes _sig)
|
||||
onlyValidSignature(_sig)
|
||||
public
|
||||
view
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/BurnableToken.sol";
|
||||
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../crowdsale/CappedCrowdsale.sol";
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
|
||||
|
||||
contract CappedCrowdsaleImpl is CappedCrowdsale {
|
||||
|
||||
function CappedCrowdsaleImpl (
|
||||
uint256 _startTime,
|
||||
uint256 _endTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token,
|
||||
uint256 _cap
|
||||
) public
|
||||
Crowdsale(_startTime, _endTime, _rate, _wallet)
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
CappedCrowdsale(_cap)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../../contracts/DayLimit.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
import "../token/ERC20/DetailedERC20.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../ECRecovery.sol";
|
||||
@ -7,10 +7,19 @@ import "../ECRecovery.sol";
|
||||
contract ECRecoveryMock {
|
||||
using ECRecovery for bytes32;
|
||||
|
||||
address public addrRecovered;
|
||||
|
||||
function recover(bytes32 hash, bytes sig) public returns (address) {
|
||||
addrRecovered = hash.recover(sig);
|
||||
function recover(bytes32 hash, bytes sig)
|
||||
public
|
||||
pure
|
||||
returns (address)
|
||||
{
|
||||
return hash.recover(sig);
|
||||
}
|
||||
|
||||
function toEthSignedMessageHash(bytes32 hash)
|
||||
public
|
||||
pure
|
||||
returns (bytes32)
|
||||
{
|
||||
return hash.toEthSignedMessageHash();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/BasicToken.sol";
|
||||
|
||||
|
||||
contract ERC223ContractInterface {
|
||||
function tokenFallback(address _from, uint256 _value, bytes _data) external;
|
||||
}
|
||||
|
||||
|
||||
contract ERC223TokenMock is BasicToken {
|
||||
|
||||
function ERC223TokenMock(address initialAccount, uint256 initialBalance) public {
|
||||
@ -18,11 +20,12 @@ contract ERC223TokenMock is BasicToken {
|
||||
returns (bool success)
|
||||
{
|
||||
transfer(_to, _value);
|
||||
bool is_contract = false;
|
||||
bool isContract = false;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
is_contract := not(iszero(extcodesize(_to)))
|
||||
isContract := not(iszero(extcodesize(_to)))
|
||||
}
|
||||
if (is_contract) {
|
||||
if (isContract) {
|
||||
ERC223ContractInterface receiver = ERC223ContractInterface(_to);
|
||||
receiver.tokenFallback(msg.sender, _value, _data);
|
||||
}
|
||||
|
||||
18
contracts/mocks/ERC721BasicTokenMock.sol
Normal file
18
contracts/mocks/ERC721BasicTokenMock.sol
Normal file
@ -0,0 +1,18 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC721/ERC721BasicToken.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC721BasicTokenMock
|
||||
* This mock just provides a public mint and burn functions for testing purposes
|
||||
*/
|
||||
contract ERC721BasicTokenMock is ERC721BasicToken {
|
||||
function mint(address _to, uint256 _tokenId) public {
|
||||
super._mint(_to, _tokenId);
|
||||
}
|
||||
|
||||
function burn(uint256 _tokenId) public {
|
||||
super._burn(ownerOf(_tokenId), _tokenId);
|
||||
}
|
||||
}
|
||||
34
contracts/mocks/ERC721ReceiverMock.sol
Normal file
34
contracts/mocks/ERC721ReceiverMock.sol
Normal file
@ -0,0 +1,34 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC721/ERC721Receiver.sol";
|
||||
|
||||
|
||||
contract ERC721ReceiverMock is ERC721Receiver {
|
||||
bytes4 retval;
|
||||
bool reverts;
|
||||
|
||||
event Received(address _address, uint256 _tokenId, bytes _data, uint256 _gas);
|
||||
|
||||
function ERC721ReceiverMock(bytes4 _retval, bool _reverts) public {
|
||||
retval = _retval;
|
||||
reverts = _reverts;
|
||||
}
|
||||
|
||||
function onERC721Received(
|
||||
address _address,
|
||||
uint256 _tokenId,
|
||||
bytes _data
|
||||
)
|
||||
public
|
||||
returns(bytes4)
|
||||
{
|
||||
require(!reverts);
|
||||
emit Received(
|
||||
_address,
|
||||
_tokenId,
|
||||
_data,
|
||||
gasleft() // msg.gas was deprecated in solidityv0.4.21
|
||||
);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,27 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC721/ERC721Token.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC721TokenMock
|
||||
* This mock just provides a public mint and burn functions for testing purposes.
|
||||
* This mock just provides a public mint and burn functions for testing purposes,
|
||||
* and a public setter for metadata URI
|
||||
*/
|
||||
contract ERC721TokenMock is ERC721Token {
|
||||
function ERC721TokenMock() ERC721Token() public { }
|
||||
function ERC721TokenMock(string name, string symbol) public
|
||||
ERC721Token(name, symbol)
|
||||
{ }
|
||||
|
||||
function mint(address _to, uint256 _tokenId) public {
|
||||
super._mint(_to, _tokenId);
|
||||
}
|
||||
|
||||
function burn(uint256 _tokenId) public {
|
||||
super._burn(_tokenId);
|
||||
super._burn(ownerOf(_tokenId), _tokenId);
|
||||
}
|
||||
|
||||
function setTokenURI(uint256 _tokenId, string _uri) public {
|
||||
super._setTokenURI(_tokenId, _uri);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.13;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../token/ERC827/ERC827Token.sol";
|
||||
|
||||
@ -1,18 +1,21 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../crowdsale/FinalizableCrowdsale.sol";
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
import "../crowdsale/distribution/FinalizableCrowdsale.sol";
|
||||
|
||||
|
||||
contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
|
||||
|
||||
function FinalizableCrowdsaleImpl (
|
||||
uint256 _startTime,
|
||||
uint256 _endTime,
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet
|
||||
) public
|
||||
Crowdsale(_startTime, _endTime, _rate, _wallet)
|
||||
address _wallet,
|
||||
MintableToken _token
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
// @title Force Ether into a contract.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../../contracts/ownership/HasNoEther.sol";
|
||||
|
||||
|
||||
24
contracts/mocks/IncreasingPriceCrowdsaleImpl.sol
Normal file
24
contracts/mocks/IncreasingPriceCrowdsaleImpl.sol
Normal file
@ -0,0 +1,24 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../crowdsale/price/IncreasingPriceCrowdsale.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
|
||||
contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale {
|
||||
|
||||
function IncreasingPriceCrowdsaleImpl (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
address _wallet,
|
||||
ERC20 _token,
|
||||
uint256 _initialRate,
|
||||
uint256 _finalRate
|
||||
)
|
||||
public
|
||||
Crowdsale(_initialRate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
IncreasingPriceCrowdsale(_initialRate, _finalRate)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
19
contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol
Normal file
19
contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol";
|
||||
|
||||
|
||||
contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale {
|
||||
|
||||
function IndividuallyCappedCrowdsaleImpl (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import {Bounty, Target} from "../../contracts/Bounty.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../LimitBalance.sol";
|
||||
|
||||
26
contracts/mocks/MathMock.sol
Normal file
26
contracts/mocks/MathMock.sol
Normal file
@ -0,0 +1,26 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../../contracts/math/Math.sol";
|
||||
|
||||
|
||||
contract MathMock {
|
||||
uint64 public result64;
|
||||
uint256 public result256;
|
||||
|
||||
function max64(uint64 a, uint64 b) public {
|
||||
result64 = Math.max64(a, b);
|
||||
}
|
||||
|
||||
function min64(uint64 a, uint64 b) public {
|
||||
result64 = Math.min64(a, b);
|
||||
}
|
||||
|
||||
function max256(uint256 a, uint256 b) public {
|
||||
result256 = Math.max256(a, b);
|
||||
}
|
||||
|
||||
function min256(uint256 a, uint256 b) public {
|
||||
result256 = Math.min256(a, b);
|
||||
}
|
||||
}
|
||||
11
contracts/mocks/MerkleProofWrapper.sol
Normal file
11
contracts/mocks/MerkleProofWrapper.sol
Normal file
@ -0,0 +1,11 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import { MerkleProof } from "../MerkleProof.sol";
|
||||
|
||||
|
||||
contract MerkleProofWrapper {
|
||||
|
||||
function verifyProof(bytes32[] _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {
|
||||
return MerkleProof.verifyProof(_proof, _root, _leaf);
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,22 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
contract MessageHelper {
|
||||
|
||||
event Show(bytes32 b32, uint256 number, string text);
|
||||
event Buy(bytes32 b32, uint256 number, string text, uint256 value);
|
||||
|
||||
function showMessage( bytes32 message, uint256 number, string text ) public returns (bool) {
|
||||
Show(message, number, text);
|
||||
emit Show(message, number, text);
|
||||
return true;
|
||||
}
|
||||
|
||||
function buyMessage( bytes32 message, uint256 number, string text ) public payable returns (bool) {
|
||||
emit Buy(
|
||||
message,
|
||||
number,
|
||||
text,
|
||||
msg.value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -14,6 +25,7 @@ contract MessageHelper {
|
||||
}
|
||||
|
||||
function call(address to, bytes data) public returns (bool) {
|
||||
// solium-disable-next-line security/no-low-level-calls
|
||||
if (to.call(data))
|
||||
return true;
|
||||
else
|
||||
|
||||
19
contracts/mocks/MintedCrowdsaleImpl.sol
Normal file
19
contracts/mocks/MintedCrowdsaleImpl.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
import "../crowdsale/emission/MintedCrowdsale.sol";
|
||||
|
||||
|
||||
contract MintedCrowdsaleImpl is MintedCrowdsale {
|
||||
|
||||
function MintedCrowdsaleImpl (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
MintableToken _token
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../lifecycle/Pausable.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/PausableToken.sol";
|
||||
|
||||
|
||||
22
contracts/mocks/PostDeliveryCrowdsaleImpl.sol
Normal file
22
contracts/mocks/PostDeliveryCrowdsaleImpl.sol
Normal file
@ -0,0 +1,22 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/distribution/PostDeliveryCrowdsale.sol";
|
||||
|
||||
|
||||
contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale {
|
||||
|
||||
function PostDeliveryCrowdsaleImpl (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
public
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../payment/PullPayment.sol";
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
pragma solidity ^0.4.8;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../ownership/rbac/RBAC.sol";
|
||||
import "../ownership/rbac/RBACWithAdmin.sol";
|
||||
|
||||
|
||||
contract RBACMock is RBAC {
|
||||
contract RBACMock is RBACWithAdmin {
|
||||
|
||||
string constant ROLE_ADVISOR = "advisor";
|
||||
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
contract ReentrancyAttack {
|
||||
|
||||
function callSender(bytes4 data) public {
|
||||
// solium-disable-next-line security/no-low-level-calls
|
||||
require(msg.sender.call(data));
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../ReentrancyGuard.sol";
|
||||
import "./ReentrancyAttack.sol";
|
||||
@ -27,7 +27,8 @@ contract ReentrancyMock is ReentrancyGuard {
|
||||
bytes4 func = bytes4(keccak256("countThisRecursive(uint256)"));
|
||||
if (n > 0) {
|
||||
count();
|
||||
bool result = this.call(func, n - 1);
|
||||
// solium-disable-next-line security/no-low-level-calls
|
||||
bool result = address(this).call(func, n - 1);
|
||||
require(result == true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,19 +1,22 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../crowdsale/RefundableCrowdsale.sol";
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||
|
||||
|
||||
contract RefundableCrowdsaleImpl is RefundableCrowdsale {
|
||||
|
||||
function RefundableCrowdsaleImpl (
|
||||
uint256 _startTime,
|
||||
uint256 _endTime,
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
MintableToken _token,
|
||||
uint256 _goal
|
||||
) public
|
||||
Crowdsale(_startTime, _endTime, _rate, _wallet)
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
RefundableCrowdsale(_goal)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
|
||||
@ -1,21 +1,24 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
|
||||
contract SafeMathMock {
|
||||
uint256 public result;
|
||||
|
||||
function multiply(uint256 a, uint256 b) public {
|
||||
result = SafeMath.mul(a, b);
|
||||
function mul(uint256 a, uint256 b) public pure returns (uint256) {
|
||||
return SafeMath.mul(a, b);
|
||||
}
|
||||
|
||||
function subtract(uint256 a, uint256 b) public {
|
||||
result = SafeMath.sub(a, b);
|
||||
function div(uint256 a, uint256 b) public pure returns (uint256) {
|
||||
return SafeMath.div(a, b);
|
||||
}
|
||||
|
||||
function add(uint256 a, uint256 b) public {
|
||||
result = SafeMath.add(a, b);
|
||||
function sub(uint256 a, uint256 b) public pure returns (uint256) {
|
||||
return SafeMath.sub(a, b);
|
||||
}
|
||||
|
||||
function add(uint256 a, uint256 b) public pure returns (uint256) {
|
||||
return SafeMath.add(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import {Bounty, Target} from "../../contracts/Bounty.sol";
|
||||
|
||||
|
||||
13
contracts/mocks/StandardBurnableTokenMock.sol
Normal file
13
contracts/mocks/StandardBurnableTokenMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import "../token/ERC20/StandardBurnableToken.sol";
|
||||
|
||||
|
||||
contract StandardBurnableTokenMock is StandardBurnableToken {
|
||||
|
||||
function StandardBurnableTokenMock(address initialAccount, uint initialBalance) public {
|
||||
balances[initialAccount] = initialBalance;
|
||||
totalSupply_ = initialBalance;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
|
||||
|
||||
// mock class using StandardToken
|
||||
contract StandardTokenMock is StandardToken {
|
||||
|
||||
|
||||
22
contracts/mocks/TimedCrowdsaleImpl.sol
Normal file
22
contracts/mocks/TimedCrowdsaleImpl.sol
Normal file
@ -0,0 +1,22 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/TimedCrowdsale.sol";
|
||||
|
||||
|
||||
contract TimedCrowdsaleImpl is TimedCrowdsale {
|
||||
|
||||
function TimedCrowdsaleImpl (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
14
contracts/mocks/WhitelistMock.sol
Normal file
14
contracts/mocks/WhitelistMock.sol
Normal file
@ -0,0 +1,14 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../ownership/Whitelist.sol";
|
||||
|
||||
|
||||
contract WhitelistMock is Whitelist {
|
||||
|
||||
function onlyWhitelistedCanDoThis()
|
||||
onlyWhitelisted
|
||||
view
|
||||
external
|
||||
{
|
||||
}
|
||||
}
|
||||
19
contracts/mocks/WhitelistedCrowdsaleImpl.sol
Normal file
19
contracts/mocks/WhitelistedCrowdsaleImpl.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/WhitelistedCrowdsale.sol";
|
||||
|
||||
|
||||
contract WhitelistedCrowdsaleImpl is WhitelistedCrowdsale {
|
||||
|
||||
function WhitelistedCrowdsaleImpl (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./Ownable.sol";
|
||||
import "../token/ERC20/ERC20Basic.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "./Ownable.sol";
|
||||
@ -32,7 +32,7 @@ contract Claimable is Ownable {
|
||||
* @dev Allows the pendingOwner address to finalize the transfer.
|
||||
*/
|
||||
function claimOwnership() onlyPendingOwner public {
|
||||
OwnershipTransferred(owner, pendingOwner);
|
||||
emit OwnershipTransferred(owner, pendingOwner);
|
||||
owner = pendingOwner;
|
||||
pendingOwner = address(0);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./Ownable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./Claimable.sol";
|
||||
|
||||
@ -31,7 +31,7 @@ contract DelayedClaimable is Claimable {
|
||||
*/
|
||||
function claimOwnership() onlyPendingOwner public {
|
||||
require((block.number <= end) && (block.number >= start));
|
||||
OwnershipTransferred(owner, pendingOwner);
|
||||
emit OwnershipTransferred(owner, pendingOwner);
|
||||
owner = pendingOwner;
|
||||
pendingOwner = address(0);
|
||||
end = 0;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./Ownable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./Ownable.sol";
|
||||
|
||||
@ -8,11 +8,11 @@ import "./Ownable.sol";
|
||||
* @author Remco Bloemen <remco@2π.com>
|
||||
* @dev This tries to block incoming ether to prevent accidental loss of Ether. Should Ether end up
|
||||
* in the contract, it will allow the owner to reclaim this ether.
|
||||
* @notice Ether can still be send to this contract by:
|
||||
* @notice Ether can still be sent to this contract by:
|
||||
* calling functions labeled `payable`
|
||||
* `selfdestruct(contract_address)`
|
||||
* mining directly to the contract address
|
||||
*/
|
||||
*/
|
||||
contract HasNoEther is Ownable {
|
||||
|
||||
/**
|
||||
@ -36,6 +36,7 @@ contract HasNoEther is Ownable {
|
||||
* @dev Transfer all Ether held by the contract to the owner.
|
||||
*/
|
||||
function reclaimEther() external onlyOwner {
|
||||
assert(owner.send(this.balance));
|
||||
// solium-disable-next-line security/no-send
|
||||
assert(owner.send(address(this).balance));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./CanReclaimToken.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "./Ownable.sol";
|
||||
@ -11,13 +11,13 @@ import "./Ownable.sol";
|
||||
* owner's death.
|
||||
*/
|
||||
contract Heritable is Ownable {
|
||||
address public heir;
|
||||
address private heir_;
|
||||
|
||||
// Time window the owner has to notify they are alive.
|
||||
uint256 public heartbeatTimeout;
|
||||
uint256 private heartbeatTimeout_;
|
||||
|
||||
// Timestamp of the owner's death, as pronounced by the heir.
|
||||
uint256 public timeOfDeath;
|
||||
uint256 private timeOfDeath_;
|
||||
|
||||
event HeirChanged(address indexed owner, address indexed newHeir);
|
||||
event OwnerHeartbeated(address indexed owner);
|
||||
@ -29,7 +29,7 @@ contract Heritable is Ownable {
|
||||
* @dev Throw an exception if called by any account other than the heir's.
|
||||
*/
|
||||
modifier onlyHeir() {
|
||||
require(msg.sender == heir);
|
||||
require(msg.sender == heir_);
|
||||
_;
|
||||
}
|
||||
|
||||
@ -46,8 +46,24 @@ contract Heritable is Ownable {
|
||||
function setHeir(address newHeir) public onlyOwner {
|
||||
require(newHeir != owner);
|
||||
heartbeat();
|
||||
HeirChanged(owner, newHeir);
|
||||
heir = newHeir;
|
||||
emit HeirChanged(owner, newHeir);
|
||||
heir_ = newHeir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Use these getter functions to access the internal variables in
|
||||
* an inherited contract.
|
||||
*/
|
||||
function heir() public view returns(address) {
|
||||
return heir_;
|
||||
}
|
||||
|
||||
function heartbeatTimeout() public view returns(uint256) {
|
||||
return heartbeatTimeout_;
|
||||
}
|
||||
|
||||
function timeOfDeath() public view returns(uint256) {
|
||||
return timeOfDeath_;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,7 +71,7 @@ contract Heritable is Ownable {
|
||||
*/
|
||||
function removeHeir() public onlyOwner {
|
||||
heartbeat();
|
||||
heir = 0;
|
||||
heir_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,16 +80,17 @@ contract Heritable is Ownable {
|
||||
*/
|
||||
function proclaimDeath() public onlyHeir {
|
||||
require(ownerLives());
|
||||
OwnerProclaimedDead(owner, heir, timeOfDeath);
|
||||
timeOfDeath = now;
|
||||
emit OwnerProclaimedDead(owner, heir_, timeOfDeath_);
|
||||
// solium-disable-next-line security/no-block-members
|
||||
timeOfDeath_ = block.timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Owner can send a heartbeat if they were mistakenly pronounced dead.
|
||||
*/
|
||||
function heartbeat() public onlyOwner {
|
||||
OwnerHeartbeated(owner);
|
||||
timeOfDeath = 0;
|
||||
emit OwnerHeartbeated(owner);
|
||||
timeOfDeath_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,19 +98,20 @@ contract Heritable is Ownable {
|
||||
*/
|
||||
function claimHeirOwnership() public onlyHeir {
|
||||
require(!ownerLives());
|
||||
require(now >= timeOfDeath + heartbeatTimeout);
|
||||
OwnershipTransferred(owner, heir);
|
||||
HeirOwnershipClaimed(owner, heir);
|
||||
owner = heir;
|
||||
timeOfDeath = 0;
|
||||
// solium-disable-next-line security/no-block-members
|
||||
require(block.timestamp >= timeOfDeath_ + heartbeatTimeout_);
|
||||
emit OwnershipTransferred(owner, heir_);
|
||||
emit HeirOwnershipClaimed(owner, heir_);
|
||||
owner = heir_;
|
||||
timeOfDeath_ = 0;
|
||||
}
|
||||
|
||||
function setHeartbeatTimeout(uint256 newHeartbeatTimeout) internal onlyOwner {
|
||||
require(ownerLives());
|
||||
heartbeatTimeout = newHeartbeatTimeout;
|
||||
heartbeatTimeout_ = newHeartbeatTimeout;
|
||||
}
|
||||
|
||||
function ownerLives() internal view returns (bool) {
|
||||
return timeOfDeath == 0;
|
||||
return timeOfDeath_ == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./HasNoEther.sol";
|
||||
import "./HasNoTokens.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
@ -35,7 +35,7 @@ contract Ownable {
|
||||
*/
|
||||
function transferOwnership(address newOwner) public onlyOwner {
|
||||
require(newOwner != address(0));
|
||||
OwnershipTransferred(owner, newOwner);
|
||||
emit OwnershipTransferred(owner, newOwner);
|
||||
owner = newOwner;
|
||||
}
|
||||
|
||||
|
||||
81
contracts/ownership/Whitelist.sol
Normal file
81
contracts/ownership/Whitelist.sol
Normal file
@ -0,0 +1,81 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "./Ownable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Whitelist
|
||||
* @dev The Whitelist contract has a whitelist of addresses, and provides basic authorization control functions.
|
||||
* @dev This simplifies the implementation of "user permissions".
|
||||
*/
|
||||
contract Whitelist is Ownable {
|
||||
mapping(address => bool) public whitelist;
|
||||
|
||||
event WhitelistedAddressAdded(address addr);
|
||||
event WhitelistedAddressRemoved(address addr);
|
||||
|
||||
/**
|
||||
* @dev Throws if called by any account that's not whitelisted.
|
||||
*/
|
||||
modifier onlyWhitelisted() {
|
||||
require(whitelist[msg.sender]);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add an address to the whitelist
|
||||
* @param addr address
|
||||
* @return true if the address was added to the whitelist, false if the address was already in the whitelist
|
||||
*/
|
||||
function addAddressToWhitelist(address addr) onlyOwner public returns(bool success) {
|
||||
if (!whitelist[addr]) {
|
||||
whitelist[addr] = true;
|
||||
emit WhitelistedAddressAdded(addr);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add addresses to the whitelist
|
||||
* @param addrs addresses
|
||||
* @return true if at least one address was added to the whitelist,
|
||||
* false if all addresses were already in the whitelist
|
||||
*/
|
||||
function addAddressesToWhitelist(address[] addrs) onlyOwner public returns(bool success) {
|
||||
for (uint256 i = 0; i < addrs.length; i++) {
|
||||
if (addAddressToWhitelist(addrs[i])) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove an address from the whitelist
|
||||
* @param addr address
|
||||
* @return true if the address was removed from the whitelist,
|
||||
* false if the address wasn't in the whitelist in the first place
|
||||
*/
|
||||
function removeAddressFromWhitelist(address addr) onlyOwner public returns(bool success) {
|
||||
if (whitelist[addr]) {
|
||||
whitelist[addr] = false;
|
||||
emit WhitelistedAddressRemoved(addr);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove addresses from the whitelist
|
||||
* @param addrs addresses
|
||||
* @return true if at least one address was removed from the whitelist,
|
||||
* false if all addresses weren't in the whitelist in the first place
|
||||
*/
|
||||
function removeAddressesFromWhitelist(address[] addrs) onlyOwner public returns(bool success) {
|
||||
for (uint256 i = 0; i < addrs.length; i++) {
|
||||
if (removeAddressFromWhitelist(addrs[i])) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./Roles.sol";
|
||||
|
||||
@ -7,8 +7,8 @@ import "./Roles.sol";
|
||||
* @title RBAC (Role-Based Access Control)
|
||||
* @author Matt Condon (@Shrugs)
|
||||
* @dev Stores and provides setters and getters for roles and addresses.
|
||||
* Supports unlimited numbers of roles and addresses.
|
||||
* See //contracts/mocks/RBACMock.sol for an example of usage.
|
||||
* @dev Supports unlimited numbers of roles and addresses.
|
||||
* @dev See //contracts/mocks/RBACMock.sol for an example of usage.
|
||||
* This RBAC method uses strings to key roles. It may be beneficial
|
||||
* for you to write your own implementation of this interface using Enums or similar.
|
||||
* It's also recommended that you define constants in the contract, like ROLE_ADMIN below,
|
||||
@ -22,20 +22,6 @@ contract RBAC {
|
||||
event RoleAdded(address addr, string roleName);
|
||||
event RoleRemoved(address addr, string roleName);
|
||||
|
||||
/**
|
||||
* A constant role name for indicating admins.
|
||||
*/
|
||||
string public constant ROLE_ADMIN = "admin";
|
||||
|
||||
/**
|
||||
* @dev constructor. Sets msg.sender as admin by default
|
||||
*/
|
||||
function RBAC()
|
||||
public
|
||||
{
|
||||
addRole(msg.sender, ROLE_ADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev reverts if addr does not have role
|
||||
* @param addr address
|
||||
@ -63,30 +49,6 @@ contract RBAC {
|
||||
return roles[roleName].has(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add a role to an address
|
||||
* @param addr address
|
||||
* @param roleName the name of the role
|
||||
*/
|
||||
function adminAddRole(address addr, string roleName)
|
||||
onlyAdmin
|
||||
public
|
||||
{
|
||||
addRole(addr, roleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove a role from an address
|
||||
* @param addr address
|
||||
* @param roleName the name of the role
|
||||
*/
|
||||
function adminRemoveRole(address addr, string roleName)
|
||||
onlyAdmin
|
||||
public
|
||||
{
|
||||
removeRole(addr, roleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add a role to an address
|
||||
* @param addr address
|
||||
@ -96,7 +58,7 @@ contract RBAC {
|
||||
internal
|
||||
{
|
||||
roles[roleName].add(addr);
|
||||
RoleAdded(addr, roleName);
|
||||
emit RoleAdded(addr, roleName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +70,7 @@ contract RBAC {
|
||||
internal
|
||||
{
|
||||
roles[roleName].remove(addr);
|
||||
RoleRemoved(addr, roleName);
|
||||
emit RoleRemoved(addr, roleName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,16 +84,6 @@ contract RBAC {
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev modifier to scope access to admins
|
||||
* // reverts
|
||||
*/
|
||||
modifier onlyAdmin()
|
||||
{
|
||||
checkRole(msg.sender, ROLE_ADMIN);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev modifier to scope access to a set of roles (uses msg.sender as addr)
|
||||
* @param roleNames the names of the roles to scope access to
|
||||
|
||||
60
contracts/ownership/rbac/RBACWithAdmin.sol
Normal file
60
contracts/ownership/rbac/RBACWithAdmin.sol
Normal file
@ -0,0 +1,60 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./RBAC.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title RBACWithAdmin
|
||||
* @author Matt Condon (@Shrugs)
|
||||
* @dev It's recommended that you define constants in the contract,
|
||||
* @dev like ROLE_ADMIN below, to avoid typos.
|
||||
*/
|
||||
contract RBACWithAdmin is RBAC {
|
||||
/**
|
||||
* A constant role name for indicating admins.
|
||||
*/
|
||||
string public constant ROLE_ADMIN = "admin";
|
||||
|
||||
/**
|
||||
* @dev modifier to scope access to admins
|
||||
* // reverts
|
||||
*/
|
||||
modifier onlyAdmin()
|
||||
{
|
||||
checkRole(msg.sender, ROLE_ADMIN);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev constructor. Sets msg.sender as admin by default
|
||||
*/
|
||||
function RBACWithAdmin()
|
||||
public
|
||||
{
|
||||
addRole(msg.sender, ROLE_ADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add a role to an address
|
||||
* @param addr address
|
||||
* @param roleName the name of the role
|
||||
*/
|
||||
function adminAddRole(address addr, string roleName)
|
||||
onlyAdmin
|
||||
public
|
||||
{
|
||||
addRole(addr, roleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove a role from an address
|
||||
* @param addr address
|
||||
* @param roleName the name of the role
|
||||
*/
|
||||
function adminRemoveRole(address addr, string roleName)
|
||||
onlyAdmin
|
||||
public
|
||||
{
|
||||
removeRole(addr, roleName);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
@ -7,7 +7,7 @@ import "../math/SafeMath.sol";
|
||||
/**
|
||||
* @title PullPayment
|
||||
* @dev Base contract supporting async send for pull payments. Inherit from this
|
||||
* contract and use asyncSend instead of send.
|
||||
* contract and use asyncSend instead of send or transfer.
|
||||
*/
|
||||
contract PullPayment {
|
||||
using SafeMath for uint256;
|
||||
@ -16,19 +16,19 @@ contract PullPayment {
|
||||
uint256 public totalPayments;
|
||||
|
||||
/**
|
||||
* @dev withdraw accumulated balance, called by payee.
|
||||
* @dev Withdraw accumulated balance, called by payee.
|
||||
*/
|
||||
function withdrawPayments() public {
|
||||
address payee = msg.sender;
|
||||
uint256 payment = payments[payee];
|
||||
|
||||
require(payment != 0);
|
||||
require(this.balance >= payment);
|
||||
require(address(this).balance >= payment);
|
||||
|
||||
totalPayments = totalPayments.sub(payment);
|
||||
payments[payee] = 0;
|
||||
|
||||
assert(payee.send(payment));
|
||||
payee.transfer(payment);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
@ -42,11 +42,11 @@ contract SplitPayment {
|
||||
|
||||
require(shares[payee] > 0);
|
||||
|
||||
uint256 totalReceived = this.balance.add(totalReleased);
|
||||
uint256 totalReceived = address(this).balance.add(totalReleased);
|
||||
uint256 payment = totalReceived.mul(shares[payee]).div(totalShares).sub(released[payee]);
|
||||
|
||||
require(payment != 0);
|
||||
require(this.balance >= payment);
|
||||
require(address(this).balance >= payment);
|
||||
|
||||
released[payee] = released[payee].add(payment);
|
||||
totalReleased = totalReleased.add(payment);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
import "./ERC20Basic.sol";
|
||||
@ -32,10 +32,9 @@ contract BasicToken is ERC20Basic {
|
||||
require(_to != address(0));
|
||||
require(_value <= balances[msg.sender]);
|
||||
|
||||
// SafeMath.sub will throw if there is not enough balance.
|
||||
balances[msg.sender] = balances[msg.sender].sub(_value);
|
||||
balances[_to] = balances[_to].add(_value);
|
||||
Transfer(msg.sender, _to, _value);
|
||||
emit Transfer(msg.sender, _to, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -44,7 +43,7 @@ contract BasicToken is ERC20Basic {
|
||||
* @param _owner The address to query the the balance of.
|
||||
* @return An uint256 representing the amount owned by the passed address.
|
||||
*/
|
||||
function balanceOf(address _owner) public view returns (uint256 balance) {
|
||||
function balanceOf(address _owner) public view returns (uint256) {
|
||||
return balances[_owner];
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./BasicToken.sol";
|
||||
|
||||
@ -16,13 +16,17 @@ contract BurnableToken is BasicToken {
|
||||
* @param _value The amount of token to be burned.
|
||||
*/
|
||||
function burn(uint256 _value) public {
|
||||
require(_value <= balances[msg.sender]);
|
||||
_burn(msg.sender, _value);
|
||||
}
|
||||
|
||||
function _burn(address _who, uint256 _value) internal {
|
||||
require(_value <= balances[_who]);
|
||||
// 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
|
||||
|
||||
address burner = msg.sender;
|
||||
balances[burner] = balances[burner].sub(_value);
|
||||
balances[_who] = balances[_who].sub(_value);
|
||||
totalSupply_ = totalSupply_.sub(_value);
|
||||
Burn(burner, _value);
|
||||
emit Burn(_who, _value);
|
||||
emit Transfer(_who, address(0), _value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./MintableToken.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./ERC20.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./ERC20Basic.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "./StandardToken.sol";
|
||||
import "../../ownership/Ownable.sol";
|
||||
@ -7,7 +7,7 @@ import "../../ownership/Ownable.sol";
|
||||
/**
|
||||
* @title Mintable token
|
||||
* @dev Simple ERC20 Token example, with mintable token creation
|
||||
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
|
||||
* @dev Issue: * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/120
|
||||
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
|
||||
*/
|
||||
contract MintableToken is StandardToken, Ownable {
|
||||
@ -31,8 +31,8 @@ contract MintableToken is StandardToken, Ownable {
|
||||
function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
|
||||
totalSupply_ = totalSupply_.add(_amount);
|
||||
balances[_to] = balances[_to].add(_amount);
|
||||
Mint(_to, _amount);
|
||||
Transfer(address(0), _to, _amount);
|
||||
emit Mint(_to, _amount);
|
||||
emit Transfer(address(0), _to, _amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ contract MintableToken is StandardToken, Ownable {
|
||||
*/
|
||||
function finishMinting() onlyOwner canMint public returns (bool) {
|
||||
mintingFinished = true;
|
||||
MintFinished();
|
||||
emit MintFinished();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user