Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cc9fa57777 | |||
| eb4dfea6e9 | |||
| 8fd072cf8e | |||
| c2ad8c3f57 | |||
| fd253d6b8d | |||
| 7d8e3ca8b2 | |||
| 6b37ba36a1 | |||
| dc1e352cc4 | |||
| f18c3bc438 | |||
| 0047e79681 | |||
| 74a62a1314 | |||
| 92b695f2fb | |||
| ee78f67985 | |||
| 07020e9544 | |||
| b4406d385f | |||
| 78e39aa2ad | |||
| e4ed8f0705 | |||
| 5daaf60d11 | |||
| e1dc1411fc | |||
| 9f1d294ba4 | |||
| 9951acf6d8 | |||
| 72792a724d | |||
| b0292cf628 | |||
| 39385f9f4e | |||
| 7a61371b19 | |||
| 259b9da3e6 | |||
| 5326e7c36e | |||
| feb665136c | |||
| 7fb84b42d5 | |||
| 5db0d7d1a0 | |||
| 512e8218ca | |||
| 9d6ffae8cb | |||
| 2a997a8e92 | |||
| 5651538045 | |||
| 10e84aecaf | |||
| 2637bd89be | |||
| 32ec8b5398 | |||
| a0c03ee61c | |||
| e3f866c982 | |||
| 5ab9024b6a | |||
| d5f06ab32f | |||
| 746673a94f | |||
| ba4cf03da7 | |||
| 39370ff690 | |||
| ad12381549 | |||
| 20b85be6aa | |||
| 4223c9d50e | |||
| f0eea31bdf | |||
| ce0a928a6c | |||
| 85f079ee89 | |||
| 7e44204d9b | |||
| 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 |
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@ -12,7 +12,7 @@
|
||||
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
|
||||
|
||||
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -11,7 +11,7 @@ Fixes #
|
||||
|
||||
<!-- 3. Before submitting, please review the following checklist: -->
|
||||
|
||||
- [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](/docs/CONTRIBUTING.md)
|
||||
- [ ] 📘 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`).
|
||||
- [ ] 🎨 I've run the JS/Solidity linters and fixed any issues (`npm run lint:all:fix`).
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -34,3 +34,6 @@ build/
|
||||
|
||||
# lol macs
|
||||
.DS_Store/
|
||||
|
||||
# truffle
|
||||
.node-xmlhttprequest-*
|
||||
|
||||
@ -3,8 +3,10 @@
|
||||
"plugins": ["security"],
|
||||
"rules": {
|
||||
"quotes": ["error", "double"],
|
||||
"no-empty-blocks": "off",
|
||||
"indentation": ["error", 2],
|
||||
"arg-overflow": ["warning", 3],
|
||||
"max-len": ["warning", 79],
|
||||
"no-constant": ["error"],
|
||||
"security/enforce-explicit-visibility": ["error"],
|
||||
"security/no-block-members": ["warning"],
|
||||
"security/no-inline-assembly": ["warning"]
|
||||
|
||||
@ -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,29 +5,28 @@ 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/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/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 remote add upstream https://github.com/OpenZeppelin/openzeppelin-solidity.git
|
||||
git fetch upstream
|
||||
git checkout development
|
||||
git pull --rebase upstream development
|
||||
git pull --rebase upstream master
|
||||
```
|
||||
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`:
|
||||
2) Branch out from `master` into `fix/some-bug-#123`:
|
||||
(Postfixing #123 will associate your PR with the issue #123 and make everyone's life easier =D)
|
||||
```
|
||||
git checkout -b fix/some-bug-#123
|
||||
@ -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!
|
||||
|
||||
72
README.md
72
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.
|
||||
|
||||
@ -13,7 +13,11 @@ With OpenZeppelin, you can build distributed applications, protocols and organiz
|
||||
|
||||
## Getting Started
|
||||
|
||||
OpenZeppelin integrates with [Truffle](https://github.com/ConsenSys/truffle), an Ethereum development environment. Please install Truffle and initialize your project with `truffle init`.
|
||||
OpenZeppelin integrates with [Truffle](https://github.com/ConsenSys/truffle) and [Embark](https://github.com/embark-framework/embark/).
|
||||
|
||||
## Truffle
|
||||
|
||||
To use with Truffle, first install it and initialize your project with `truffle init`.
|
||||
|
||||
```sh
|
||||
npm install -g truffle
|
||||
@ -21,24 +25,46 @@ mkdir myproject && cd myproject
|
||||
truffle init
|
||||
```
|
||||
|
||||
To install the OpenZeppelin library, run the following in your Solidity project root directory:
|
||||
## Embark
|
||||
|
||||
To use with Embark, first install it and initialize your project with `embark new MyApp`.
|
||||
|
||||
```sh
|
||||
npm install -g embark
|
||||
embark new MyApp
|
||||
cd MyApp
|
||||
```
|
||||
|
||||
## Installing OpenZeppelin
|
||||
|
||||
After installing either Framework, 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 {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
If you are using Embark, you can also import directly from github:
|
||||
|
||||
```solidity
|
||||
import "github.com/OpenZeppelin/openzeppelin-solidity/contracts/ownership/Ownable.sol#v1.9.0";
|
||||
|
||||
contract MyContract is Ownable {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Security
|
||||
OpenZeppelin is meant to provide secure, tested and community-audited code, but please use common sense when doing anything that deals with real money! We take no responsibility for your implementation decisions and any security problem you might experience.
|
||||
@ -56,27 +82,9 @@ Building a distributed application, protocol or organization with OpenZeppelin?
|
||||
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
|
||||
@ -1,4 +1,5 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* Utility library of inline functions on addresses
|
||||
@ -6,14 +7,21 @@ pragma solidity ^0.4.18;
|
||||
library AddressUtils {
|
||||
|
||||
/**
|
||||
* Returns whether there is code in the target address
|
||||
* 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 address to check
|
||||
* @return whether there is code in the target address
|
||||
* 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.
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly { size := extcodesize(addr) }
|
||||
return size > 0;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "./payment/PullPayment.sol";
|
||||
@ -30,20 +30,20 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sends the contract funds to the researcher that proved the contract is broken.
|
||||
* @dev Transfers the contract funds to the researcher that proved the contract is broken.
|
||||
* @param target contract
|
||||
*/
|
||||
function claim(Target target) public {
|
||||
address researcher = researchers[target];
|
||||
require(researcher != 0);
|
||||
require(researcher != address(0));
|
||||
// Check Target contract invariants
|
||||
require(!target.checkInvariant());
|
||||
asyncSend(researcher, this.balance);
|
||||
asyncTransfer(researcher, address(this).balance);
|
||||
claimed = true;
|
||||
}
|
||||
|
||||
|
||||
@ -1,74 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
|
||||
/**
|
||||
* @title DayLimit
|
||||
* @dev Base contract that enables methods to be protected by placing a linear limit (specifiable)
|
||||
* on a particular resource per calendar day. Is multiowned to allow the limit to be altered.
|
||||
*/
|
||||
contract DayLimit {
|
||||
|
||||
uint256 public dailyLimit;
|
||||
uint256 public spentToday;
|
||||
uint256 public lastDay;
|
||||
|
||||
/**
|
||||
* @dev Constructor that sets the passed value as a dailyLimit.
|
||||
* @param _limit uint256 to represent the daily limit.
|
||||
*/
|
||||
function DayLimit(uint256 _limit) public {
|
||||
dailyLimit = _limit;
|
||||
lastDay = today();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev sets the daily limit. Does not alter the amount already spent today.
|
||||
* @param _newLimit uint256 to represent the new limit.
|
||||
*/
|
||||
function _setDailyLimit(uint256 _newLimit) internal {
|
||||
dailyLimit = _newLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Resets the amount already spent today.
|
||||
*/
|
||||
function _resetSpentToday() internal {
|
||||
spentToday = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks to see if there is enough resource to spend today. If true, the resource may be expended.
|
||||
* @param _value uint256 representing the amount of resource to spend.
|
||||
* @return A boolean that is True if the resource was spent and false otherwise.
|
||||
*/
|
||||
function underLimit(uint256 _value) internal returns (bool) {
|
||||
// reset the spend limit if we're on a different day to last time.
|
||||
if (today() > lastDay) {
|
||||
spentToday = 0;
|
||||
lastDay = today();
|
||||
}
|
||||
// check to see if there's enough left - if so, subtract and return true.
|
||||
// overflow protection // dailyLimit check
|
||||
if (spentToday + _value >= spentToday && spentToday + _value <= dailyLimit) {
|
||||
spentToday += _value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Private function to determine today's index
|
||||
* @return uint256 of today's index.
|
||||
*/
|
||||
function today() private view returns (uint256) {
|
||||
return now / 1 days;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Simple modifier for daily limit.
|
||||
*/
|
||||
modifier limitedDaily(uint256 _value) {
|
||||
require(underLimit(_value));
|
||||
_;
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
@ -14,17 +15,24 @@ library ECRecovery {
|
||||
* @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) internal 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 +48,25 @@ 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:"
|
||||
* 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(
|
||||
abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @title LimitBalance
|
||||
* @dev Simple contract to limit the balance of child contract.
|
||||
* @dev Note this doesn't prevent other contracts to send funds by using selfdestruct(address);
|
||||
* @dev See: https://github.com/ConsenSys/smart-contract-best-practices#remember-that-ether-can-be-forcibly-sent-to-an-account
|
||||
* Note this doesn't prevent other contracts to send funds by using selfdestruct(address);
|
||||
* See: https://github.com/ConsenSys/smart-contract-best-practices#remember-that-ether-can-be-forcibly-sent-to-an-account
|
||||
*/
|
||||
contract LimitBalance {
|
||||
|
||||
@ -15,7 +15,7 @@ contract LimitBalance {
|
||||
* @dev Constructor that sets the passed value as a limit.
|
||||
* @param _limit uint256 to represent the limit.
|
||||
*/
|
||||
function LimitBalance(uint256 _limit) public {
|
||||
constructor(uint256 _limit) public {
|
||||
limit = _limit;
|
||||
}
|
||||
|
||||
@ -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,10 +1,10 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/*
|
||||
* @title MerkleProof
|
||||
* @dev Merkle proof verification
|
||||
* @note Based on https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
|
||||
* @dev Merkle proof verification based on
|
||||
* https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
|
||||
*/
|
||||
library MerkleProof {
|
||||
/*
|
||||
@ -14,27 +14,26 @@ 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)
|
||||
computedHash = keccak256(computedHash, proofElement);
|
||||
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
|
||||
} else {
|
||||
// Hash(current element of the proof + current computed hash)
|
||||
computedHash = keccak256(proofElement, computedHash);
|
||||
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
159
contracts/access/SignatureBouncer.sol
Normal file
159
contracts/access/SignatureBouncer.sol
Normal file
@ -0,0 +1,159 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../ownership/rbac/RBAC.sol";
|
||||
import "../ECRecovery.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title SignatureBouncer
|
||||
* @author PhABC, Shrugs and aflesher
|
||||
* @dev Bouncer allows users to submit a signature as a permission to do an action.
|
||||
* If the signature is from one of the authorized bouncer addresses, the signature
|
||||
* is valid. The owner of the contract adds/removes bouncers.
|
||||
* Bouncer addresses can be individual servers signing grants or different
|
||||
* users within a decentralized club that have permission to invite other members.
|
||||
* This technique is useful for whitelists and airdrops; instead of putting all
|
||||
* valid addresses on-chain, simply sign a grant of the form
|
||||
* keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a valid bouncer address.
|
||||
* Then restrict access to your crowdsale/whitelist/airdrop using the
|
||||
* `onlyValidSignature` modifier (or implement your own using isValidSignature).
|
||||
* In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and
|
||||
* `onlyValidSignatureAndData` can be used to restrict access to only a given method
|
||||
* or a given method with given parameters respectively.
|
||||
* See the tests Bouncer.test.js for specific usage examples.
|
||||
* @notice A method that uses the `onlyValidSignatureAndData` modifier must make the _sig
|
||||
* parameter the "last" parameter. You cannot sign a message that has its own
|
||||
* signature in it so the last 128 bytes of msg.data (which represents the
|
||||
* length of the _sig data and the _sig data itself) is ignored when validating.
|
||||
* Also non fixed sized parameters make constructing the data in the signature
|
||||
* much more complex. See https://ethereum.stackexchange.com/a/50616 for more details.
|
||||
*/
|
||||
contract SignatureBouncer is Ownable, RBAC {
|
||||
using ECRecovery for bytes32;
|
||||
|
||||
string public constant ROLE_BOUNCER = "bouncer";
|
||||
uint constant METHOD_ID_SIZE = 4;
|
||||
// (signature length size) 32 bytes + (signature size 65 bytes padded) 96 bytes
|
||||
uint constant SIGNATURE_SIZE = 128;
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature of a bouncer was provided
|
||||
*/
|
||||
modifier onlyValidSignature(bytes _sig)
|
||||
{
|
||||
require(isValidSignature(msg.sender, _sig));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature with a specifed method of a bouncer was provided
|
||||
*/
|
||||
modifier onlyValidSignatureAndMethod(bytes _sig)
|
||||
{
|
||||
require(isValidSignatureAndMethod(msg.sender, _sig));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature with a specifed method and params of a bouncer was provided
|
||||
*/
|
||||
modifier onlyValidSignatureAndData(bytes _sig)
|
||||
{
|
||||
require(isValidSignatureAndData(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(abi.encodePacked(address(this), _address)),
|
||||
_sig
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + sender + methodId` from a bouncer?
|
||||
* @return bool
|
||||
*/
|
||||
function isValidSignatureAndMethod(address _address, bytes _sig)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
bytes memory data = new bytes(METHOD_ID_SIZE);
|
||||
for (uint i = 0; i < data.length; i++) {
|
||||
data[i] = msg.data[i];
|
||||
}
|
||||
return isValidDataHash(
|
||||
keccak256(abi.encodePacked(address(this), _address, data)),
|
||||
_sig
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + sender + methodId + params(s)` from a bouncer?
|
||||
* @notice the _sig parameter of the method being validated must be the "last" parameter
|
||||
* @return bool
|
||||
*/
|
||||
function isValidSignatureAndData(address _address, bytes _sig)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
require(msg.data.length > SIGNATURE_SIZE);
|
||||
bytes memory data = new bytes(msg.data.length - SIGNATURE_SIZE);
|
||||
for (uint i = 0; i < data.length; i++) {
|
||||
data[i] = msg.data[i];
|
||||
}
|
||||
return isValidDataHash(
|
||||
keccak256(abi.encodePacked(address(this), _address, data)),
|
||||
_sig
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev internal function to convert a hash to an eth signed message
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
91
contracts/access/Whitelist.sol
Normal file
91
contracts/access/Whitelist.sol
Normal file
@ -0,0 +1,91 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../ownership/rbac/RBAC.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Whitelist
|
||||
* @dev The Whitelist contract has a whitelist of addresses, and provides basic authorization control functions.
|
||||
* This simplifies the implementation of "user permissions".
|
||||
*/
|
||||
contract Whitelist is Ownable, RBAC {
|
||||
string public constant ROLE_WHITELISTED = "whitelist";
|
||||
|
||||
/**
|
||||
* @dev Throws if operator is not whitelisted.
|
||||
* @param _operator address
|
||||
*/
|
||||
modifier onlyIfWhitelisted(address _operator) {
|
||||
checkRole(_operator, ROLE_WHITELISTED);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add an address to the whitelist
|
||||
* @param _operator address
|
||||
* @return true if the address was added to the whitelist, false if the address was already in the whitelist
|
||||
*/
|
||||
function addAddressToWhitelist(address _operator)
|
||||
onlyOwner
|
||||
public
|
||||
{
|
||||
addRole(_operator, ROLE_WHITELISTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev getter to determine if address is in whitelist
|
||||
*/
|
||||
function whitelist(address _operator)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return hasRole(_operator, ROLE_WHITELISTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add addresses to the whitelist
|
||||
* @param _operators 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[] _operators)
|
||||
onlyOwner
|
||||
public
|
||||
{
|
||||
for (uint256 i = 0; i < _operators.length; i++) {
|
||||
addAddressToWhitelist(_operators[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove an address from the whitelist
|
||||
* @param _operator 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 _operator)
|
||||
onlyOwner
|
||||
public
|
||||
{
|
||||
removeRole(_operator, ROLE_WHITELISTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove addresses from the whitelist
|
||||
* @param _operators 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[] _operators)
|
||||
onlyOwner
|
||||
public
|
||||
{
|
||||
for (uint256 i = 0; i < _operators.length; i++) {
|
||||
removeAddressFromWhitelist(_operators[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Crowdsale
|
||||
@ -11,13 +13,13 @@ import "../math/SafeMath.sol";
|
||||
* 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 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;
|
||||
using SafeERC20 for ERC20;
|
||||
|
||||
// The token being sold
|
||||
ERC20 public token;
|
||||
@ -25,7 +27,10 @@ contract Crowdsale {
|
||||
// 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.
|
||||
// The rate is the conversion between wei and the smallest and indivisible token unit.
|
||||
// So, if you are using a rate of 1 with a DetailedERC20 token with 3 decimals called TOK
|
||||
// 1 wei will give you 1 unit, or 0.001 TOK.
|
||||
uint256 public rate;
|
||||
|
||||
// Amount of wei raised
|
||||
@ -38,14 +43,19 @@ contract Crowdsale {
|
||||
* @param value weis paid for purchase
|
||||
* @param amount amount of tokens purchased
|
||||
*/
|
||||
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
|
||||
event TokenPurchase(
|
||||
address indexed purchaser,
|
||||
address indexed beneficiary,
|
||||
uint256 value,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
constructor(uint256 _rate, address _wallet, ERC20 _token) public {
|
||||
require(_rate > 0);
|
||||
require(_wallet != address(0));
|
||||
require(_token != address(0));
|
||||
@ -82,7 +92,12 @@ contract Crowdsale {
|
||||
weiRaised = weiRaised.add(weiAmount);
|
||||
|
||||
_processPurchase(_beneficiary, tokens);
|
||||
TokenPurchase(msg.sender, _beneficiary, weiAmount, tokens);
|
||||
emit TokenPurchase(
|
||||
msg.sender,
|
||||
_beneficiary,
|
||||
weiAmount,
|
||||
tokens
|
||||
);
|
||||
|
||||
_updatePurchasingState(_beneficiary, weiAmount);
|
||||
|
||||
@ -99,7 +114,12 @@ contract Crowdsale {
|
||||
* @param _beneficiary Address performing the token purchase
|
||||
* @param _weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
|
||||
function _preValidatePurchase(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
require(_beneficiary != address(0));
|
||||
require(_weiAmount != 0);
|
||||
}
|
||||
@ -109,7 +129,12 @@ contract Crowdsale {
|
||||
* @param _beneficiary Address performing the token purchase
|
||||
* @param _weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _postValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
|
||||
function _postValidatePurchase(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
// optional override
|
||||
}
|
||||
|
||||
@ -118,8 +143,13 @@ contract Crowdsale {
|
||||
* @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);
|
||||
function _deliverTokens(
|
||||
address _beneficiary,
|
||||
uint256 _tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
token.safeTransfer(_beneficiary, _tokenAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,7 +157,12 @@ contract Crowdsale {
|
||||
* @param _beneficiary Address receiving the tokens
|
||||
* @param _tokenAmount Number of tokens to be purchased
|
||||
*/
|
||||
function _processPurchase(address _beneficiary, uint256 _tokenAmount) internal {
|
||||
function _processPurchase(
|
||||
address _beneficiary,
|
||||
uint256 _tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
_deliverTokens(_beneficiary, _tokenAmount);
|
||||
}
|
||||
|
||||
@ -136,7 +171,12 @@ contract Crowdsale {
|
||||
* @param _beneficiary Address receiving the tokens
|
||||
* @param _weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _updatePurchasingState(address _beneficiary, uint256 _weiAmount) internal {
|
||||
function _updatePurchasingState(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
// optional override
|
||||
}
|
||||
|
||||
@ -145,7 +185,9 @@ contract Crowdsale {
|
||||
* @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) {
|
||||
function _getTokenAmount(uint256 _weiAmount)
|
||||
internal view returns (uint256)
|
||||
{
|
||||
return _weiAmount.mul(rate);
|
||||
}
|
||||
|
||||
@ -155,4 +197,4 @@ contract Crowdsale {
|
||||
function _forwardFunds() internal {
|
||||
wallet.transfer(msg.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,10 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../../ownership/Ownable.sol";
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title FinalizableCrowdsale
|
||||
* @dev Extension of Crowdsale where an owner can do extra work
|
||||
@ -25,7 +26,7 @@ contract FinalizableCrowdsale is TimedCrowdsale, Ownable {
|
||||
require(hasClosed());
|
||||
|
||||
finalization();
|
||||
Finalized();
|
||||
emit Finalized();
|
||||
|
||||
isFinalized = true;
|
||||
}
|
||||
@ -37,4 +38,5 @@ contract FinalizableCrowdsale is TimedCrowdsale, Ownable {
|
||||
*/
|
||||
function finalization() internal {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
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.
|
||||
@ -13,15 +14,6 @@ contract PostDeliveryCrowdsale is TimedCrowdsale {
|
||||
|
||||
mapping(address => uint256) public balances;
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw tokens only after crowdsale ends.
|
||||
*/
|
||||
@ -32,4 +24,19 @@ contract PostDeliveryCrowdsale is TimedCrowdsale {
|
||||
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,16 +1,15 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "./FinalizableCrowdsale.sol";
|
||||
import "./utils/RefundVault.sol";
|
||||
import "../../payment/RefundEscrow.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title RefundableCrowdsale
|
||||
* @dev Extension of Crowdsale contract that adds a funding goal, and
|
||||
* the possibility of users getting a refund if goal is not met.
|
||||
* Uses a RefundVault as the crowdsale's vault.
|
||||
*/
|
||||
contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
@ -18,16 +17,16 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
// minimum amount of funds to be raised in weis
|
||||
uint256 public goal;
|
||||
|
||||
// refund vault used to hold funds while crowdsale is running
|
||||
RefundVault public vault;
|
||||
// refund escrow used to hold funds while crowdsale is running
|
||||
RefundEscrow private escrow;
|
||||
|
||||
/**
|
||||
* @dev Constructor, creates RefundVault.
|
||||
* @dev Constructor, creates RefundEscrow.
|
||||
* @param _goal Funding goal
|
||||
*/
|
||||
function RefundableCrowdsale(uint256 _goal) public {
|
||||
constructor(uint256 _goal) public {
|
||||
require(_goal > 0);
|
||||
vault = new RefundVault(wallet);
|
||||
escrow = new RefundEscrow(wallet);
|
||||
goal = _goal;
|
||||
}
|
||||
|
||||
@ -38,11 +37,11 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
require(isFinalized);
|
||||
require(!goalReached());
|
||||
|
||||
vault.refund(msg.sender);
|
||||
escrow.withdraw(msg.sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether funding goal was reached.
|
||||
* @dev Checks whether funding goal was reached.
|
||||
* @return Whether funding goal was reached
|
||||
*/
|
||||
function goalReached() public view returns (bool) {
|
||||
@ -50,23 +49,24 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev vault finalization task, called when owner calls finalize()
|
||||
* @dev escrow finalization task, called when owner calls finalize()
|
||||
*/
|
||||
function finalization() internal {
|
||||
if (goalReached()) {
|
||||
vault.close();
|
||||
escrow.close();
|
||||
escrow.beneficiaryWithdraw();
|
||||
} else {
|
||||
vault.enableRefunds();
|
||||
escrow.enableRefunds();
|
||||
}
|
||||
|
||||
super.finalization();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides Crowdsale fund forwarding, sending funds to vault.
|
||||
* @dev Overrides Crowdsale fund forwarding, sending funds to escrow.
|
||||
*/
|
||||
function _forwardFunds() internal {
|
||||
vault.deposit.value(msg.value)(msg.sender);
|
||||
escrow.deposit.value(msg.value)(msg.sender);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,66 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import "../../../math/SafeMath.sol";
|
||||
import "../../../ownership/Ownable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title RefundVault
|
||||
* @dev This contract is used for storing funds while a crowdsale
|
||||
* is in progress. Supports refunding the money if crowdsale fails,
|
||||
* and forwarding it if crowdsale is successful.
|
||||
*/
|
||||
contract RefundVault is Ownable {
|
||||
using SafeMath for uint256;
|
||||
|
||||
enum State { Active, Refunding, Closed }
|
||||
|
||||
mapping (address => uint256) public deposited;
|
||||
address public wallet;
|
||||
State public state;
|
||||
|
||||
event Closed();
|
||||
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);
|
||||
}
|
||||
|
||||
function close() onlyOwner public {
|
||||
require(state == State.Active);
|
||||
state = State.Closed;
|
||||
Closed();
|
||||
wallet.transfer(this.balance);
|
||||
}
|
||||
|
||||
function enableRefunds() onlyOwner public {
|
||||
require(state == State.Active);
|
||||
state = State.Refunding;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,25 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/ERC20.sol";
|
||||
import "../../token/ERC20/ERC20Basic.sol";
|
||||
import "../../token/ERC20/SafeERC20.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;
|
||||
using SafeERC20 for ERC20;
|
||||
|
||||
address public tokenWallet;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes token wallet address.
|
||||
* @dev Constructor, takes token wallet address.
|
||||
* @param _tokenWallet Address holding the tokens, which has approved allowance to the crowdsale
|
||||
*/
|
||||
function AllowanceCrowdsale(address _tokenWallet) public {
|
||||
constructor(address _tokenWallet) public {
|
||||
require(_tokenWallet != address(0));
|
||||
tokenWallet = _tokenWallet;
|
||||
}
|
||||
@ -36,7 +37,12 @@ contract AllowanceCrowdsale is Crowdsale {
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _tokenAmount Amount of tokens purchased
|
||||
*/
|
||||
function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
|
||||
token.transferFrom(tokenWallet, _beneficiary, _tokenAmount);
|
||||
function _deliverTokens(
|
||||
address _beneficiary,
|
||||
uint256 _tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
token.safeTransferFrom(tokenWallet, _beneficiary, _tokenAmount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/MintableToken.sol";
|
||||
@ -7,7 +7,7 @@ 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.
|
||||
* Token ownership should be transferred to MintedCrowdsale for minting.
|
||||
*/
|
||||
contract MintedCrowdsale is Crowdsale {
|
||||
|
||||
@ -16,7 +16,12 @@ contract MintedCrowdsale is Crowdsale {
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _tokenAmount Number of tokens to be minted
|
||||
*/
|
||||
function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
|
||||
function _deliverTokens(
|
||||
address _beneficiary,
|
||||
uint256 _tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
require(MintableToken(token).mint(_beneficiary, _tokenAmount));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title IncreasingPriceCrowdsale
|
||||
* @dev Extension of Crowdsale contract that increases the price of tokens linearly in time.
|
||||
* @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.
|
||||
*/
|
||||
@ -20,7 +21,7 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
||||
* @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 {
|
||||
constructor(uint256 _initialRate, uint256 _finalRate) public {
|
||||
require(_initialRate >= _finalRate);
|
||||
require(_finalRate > 0);
|
||||
initialRate = _initialRate;
|
||||
@ -28,12 +29,13 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the rate of tokens per wei at the present time.
|
||||
* Note that, as price _increases_ with time, the rate _decreases_.
|
||||
* @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) {
|
||||
uint256 elapsedTime = now.sub(openingTime);
|
||||
// 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));
|
||||
@ -44,7 +46,9 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
||||
* @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) {
|
||||
function _getTokenAmount(uint256 _weiAmount)
|
||||
internal view returns (uint256)
|
||||
{
|
||||
uint256 currentRate = getCurrentRate();
|
||||
return currentRate.mul(_weiAmount);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
@ -17,13 +17,13 @@ contract CappedCrowdsale is Crowdsale {
|
||||
* @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 {
|
||||
constructor(uint256 _cap) public {
|
||||
require(_cap > 0);
|
||||
cap = _cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether the cap has been reached.
|
||||
* @dev Checks whether the cap has been reached.
|
||||
* @return Whether the cap was reached
|
||||
*/
|
||||
function capReached() public view returns (bool) {
|
||||
@ -35,7 +35,12 @@ contract CappedCrowdsale is Crowdsale {
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
|
||||
function _preValidatePurchase(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
require(weiRaised.add(_weiAmount) <= cap);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
@ -29,7 +29,13 @@ contract IndividuallyCappedCrowdsale is Crowdsale, Ownable {
|
||||
* @param _beneficiaries List of addresses to be capped
|
||||
* @param _cap Wei limit for individual contribution
|
||||
*/
|
||||
function setGroupCap(address[] _beneficiaries, uint256 _cap) external onlyOwner {
|
||||
function setGroupCap(
|
||||
address[] _beneficiaries,
|
||||
uint256 _cap
|
||||
)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
for (uint256 i = 0; i < _beneficiaries.length; i++) {
|
||||
caps[_beneficiaries[i]] = _cap;
|
||||
}
|
||||
@ -49,7 +55,9 @@ contract IndividuallyCappedCrowdsale is Crowdsale, Ownable {
|
||||
* @param _beneficiary Address of contributor
|
||||
* @return User contribution so far
|
||||
*/
|
||||
function getUserContribution(address _beneficiary) public view returns (uint256) {
|
||||
function getUserContribution(address _beneficiary)
|
||||
public view returns (uint256)
|
||||
{
|
||||
return contributions[_beneficiary];
|
||||
}
|
||||
|
||||
@ -58,7 +66,12 @@ contract IndividuallyCappedCrowdsale is Crowdsale, Ownable {
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
|
||||
function _preValidatePurchase(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
require(contributions[_beneficiary].add(_weiAmount) <= caps[_beneficiary]);
|
||||
}
|
||||
@ -68,7 +81,12 @@ contract IndividuallyCappedCrowdsale is Crowdsale, Ownable {
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _updatePurchasingState(address _beneficiary, uint256 _weiAmount) internal {
|
||||
function _updatePurchasingState(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
super._updatePurchasingState(_beneficiary, _weiAmount);
|
||||
contributions[_beneficiary] = contributions[_beneficiary].add(_weiAmount);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
@ -15,10 +15,11 @@ contract TimedCrowdsale is Crowdsale {
|
||||
uint256 public closingTime;
|
||||
|
||||
/**
|
||||
* @dev Reverts if not in crowdsale time range.
|
||||
* @dev Reverts if not in crowdsale time range.
|
||||
*/
|
||||
modifier onlyWhileOpen {
|
||||
require(now >= openingTime && now <= closingTime);
|
||||
// solium-disable-next-line security/no-block-members
|
||||
require(block.timestamp >= openingTime && block.timestamp <= closingTime);
|
||||
_;
|
||||
}
|
||||
|
||||
@ -27,8 +28,9 @@ contract TimedCrowdsale is Crowdsale {
|
||||
* @param _openingTime Crowdsale opening time
|
||||
* @param _closingTime Crowdsale closing time
|
||||
*/
|
||||
function TimedCrowdsale(uint256 _openingTime, uint256 _closingTime) public {
|
||||
require(_openingTime >= now);
|
||||
constructor(uint256 _openingTime, uint256 _closingTime) public {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
require(_openingTime >= block.timestamp);
|
||||
require(_closingTime >= _openingTime);
|
||||
|
||||
openingTime = _openingTime;
|
||||
@ -40,15 +42,22 @@ contract TimedCrowdsale is Crowdsale {
|
||||
* @return Whether crowdsale period has elapsed
|
||||
*/
|
||||
function hasClosed() public view returns (bool) {
|
||||
return now > closingTime;
|
||||
// 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 {
|
||||
function _preValidatePurchase(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
internal
|
||||
onlyWhileOpen
|
||||
{
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
|
||||
|
||||
@ -1,57 +1,26 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../ownership/Ownable.sol";
|
||||
import "../../access/Whitelist.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;
|
||||
}
|
||||
|
||||
contract WhitelistedCrowdsale is Whitelist, Crowdsale {
|
||||
/**
|
||||
* @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) {
|
||||
function _preValidatePurchase(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
onlyIfWhitelisted(_beneficiary)
|
||||
internal
|
||||
{
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
|
||||
|
||||
66
contracts/examples/RBACWithAdmin.sol
Normal file
66
contracts/examples/RBACWithAdmin.sol
Normal file
@ -0,0 +1,66 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../ownership/rbac/RBAC.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title RBACWithAdmin
|
||||
* @author Matt Condon (@Shrugs)
|
||||
* @dev It's recommended that you define constants in the contract,
|
||||
* like ROLE_ADMIN below, to avoid typos.
|
||||
* @notice RBACWithAdmin is probably too expansive and powerful for your
|
||||
* application; an admin is actually able to change any address to any role
|
||||
* which is a very large API surface. It's recommended that you follow a strategy
|
||||
* of strictly defining the abilities of your roles
|
||||
* and the API-surface of your contract.
|
||||
* This is just an example for example's sake.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
constructor()
|
||||
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.24;
|
||||
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||
@ -13,7 +13,8 @@ import "../token/ERC20/MintableToken.sol";
|
||||
*/
|
||||
contract SampleCrowdsaleToken is MintableToken {
|
||||
|
||||
string public constant name = "Sample Crowdsale Token"; // solium-disable-line uppercase
|
||||
// solium-disable-next-line uppercase
|
||||
string public constant name = "Sample Crowdsale Token";
|
||||
string public constant symbol = "SCT"; // solium-disable-line uppercase
|
||||
uint8 public constant decimals = 18; // solium-disable-line uppercase
|
||||
|
||||
@ -31,9 +32,23 @@ contract SampleCrowdsaleToken is MintableToken {
|
||||
* After adding multiple features it's good practice to run integration tests
|
||||
* to ensure that subcontracts works together as intended.
|
||||
*/
|
||||
// XXX There doesn't seem to be a way to split this line that keeps solium
|
||||
// happy. See:
|
||||
// https://github.com/duaraghav8/Solium/issues/205
|
||||
// --elopio - 2018-05-10
|
||||
// solium-disable-next-line max-len
|
||||
contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsale {
|
||||
|
||||
function SampleCrowdsale(uint256 _openingTime, uint256 _closingTime, uint256 _rate, address _wallet, uint256 _cap, MintableToken _token, uint256 _goal) public
|
||||
constructor(
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
uint256 _cap,
|
||||
MintableToken _token,
|
||||
uint256 _goal
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
CappedCrowdsale(_cap)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../ownership/Heritable.sol";
|
||||
|
||||
@ -19,22 +19,22 @@ contract SimpleSavingsWallet is Heritable {
|
||||
event Received(address indexed payer, uint256 amount, uint256 balance);
|
||||
|
||||
|
||||
function SimpleSavingsWallet(uint256 _heartbeatTimeout) Heritable(_heartbeatTimeout) public {}
|
||||
|
||||
constructor(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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev wallet can send funds
|
||||
*/
|
||||
function sendTo(address payee, uint256 amount) public onlyOwner {
|
||||
require(payee != 0 && payee != address(this));
|
||||
require(payee != address(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.24;
|
||||
|
||||
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
@ -21,10 +21,10 @@ contract SimpleToken is StandardToken {
|
||||
/**
|
||||
* @dev Constructor that gives msg.sender all of existing tokens.
|
||||
*/
|
||||
function SimpleToken() public {
|
||||
constructor() public {
|
||||
totalSupply_ = INITIAL_SUPPLY;
|
||||
balances[msg.sender] = INITIAL_SUPPLY;
|
||||
Transfer(0x0, msg.sender, INITIAL_SUPPLY);
|
||||
emit Transfer(address(0), msg.sender, INITIAL_SUPPLY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
20
contracts/introspection/ERC165.sol
Normal file
20
contracts/introspection/ERC165.sol
Normal file
@ -0,0 +1,20 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC165
|
||||
* @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
|
||||
*/
|
||||
interface ERC165 {
|
||||
|
||||
/**
|
||||
* @notice Query if a contract implements an interface
|
||||
* @param _interfaceId The interface identifier, as specified in ERC-165
|
||||
* @dev Interface identification is specified in ERC-165. This function
|
||||
* uses less than 30,000 gas.
|
||||
*/
|
||||
function supportsInterface(bytes4 _interfaceId)
|
||||
external
|
||||
view
|
||||
returns (bool);
|
||||
}
|
||||
53
contracts/introspection/SupportsInterfaceWithLookup.sol
Normal file
53
contracts/introspection/SupportsInterfaceWithLookup.sol
Normal file
@ -0,0 +1,53 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "./ERC165.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title SupportsInterfaceWithLookup
|
||||
* @author Matt Condon (@shrugs)
|
||||
* @dev Implements ERC165 using a lookup table.
|
||||
*/
|
||||
contract SupportsInterfaceWithLookup is ERC165 {
|
||||
bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7;
|
||||
/**
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
*/
|
||||
|
||||
/**
|
||||
* @dev a mapping of interface id to whether or not it's supported
|
||||
*/
|
||||
mapping(bytes4 => bool) internal supportedInterfaces;
|
||||
|
||||
/**
|
||||
* @dev A contract implementing SupportsInterfaceWithLookup
|
||||
* implement ERC165 itself
|
||||
*/
|
||||
constructor()
|
||||
public
|
||||
{
|
||||
_registerInterface(InterfaceId_ERC165);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev implement supportsInterface(bytes4) using a lookup table
|
||||
*/
|
||||
function supportsInterface(bytes4 _interfaceId)
|
||||
external
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return supportedInterfaces[_interfaceId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev private method for registering an interface
|
||||
*/
|
||||
function _registerInterface(bytes4 _interfaceId)
|
||||
internal
|
||||
{
|
||||
require(_interfaceId != 0xffffffff);
|
||||
supportedInterfaces[_interfaceId] = true;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
@ -10,7 +10,7 @@ import "../ownership/Ownable.sol";
|
||||
*/
|
||||
contract Destructible is Ownable {
|
||||
|
||||
function Destructible() public payable { }
|
||||
constructor() public payable { }
|
||||
|
||||
/**
|
||||
* @dev Transfers the current balance to the owner and terminates the contract.
|
||||
|
||||
@ -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.24;
|
||||
|
||||
|
||||
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.24;
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../token/ERC20/ERC20Basic.sol";
|
||||
@ -12,7 +12,7 @@ import "../token/ERC20/ERC20Basic.sol";
|
||||
*/
|
||||
contract TokenDestructible is Ownable {
|
||||
|
||||
function TokenDestructible() public payable { }
|
||||
constructor() public payable { }
|
||||
|
||||
/**
|
||||
* @notice Terminate contract and refund to owner
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
@ -10,11 +10,15 @@ 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) {
|
||||
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the
|
||||
// benefit is lost if 'b' is also tested.
|
||||
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
uint256 c = a * b;
|
||||
|
||||
c = a * b;
|
||||
assert(c / a == b);
|
||||
return c;
|
||||
}
|
||||
@ -24,9 +28,9 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -40,8 +44,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;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/emission/AllowanceCrowdsale.sol";
|
||||
@ -6,12 +6,12 @@ import "../crowdsale/emission/AllowanceCrowdsale.sol";
|
||||
|
||||
contract AllowanceCrowdsaleImpl is AllowanceCrowdsale {
|
||||
|
||||
function AllowanceCrowdsaleImpl (
|
||||
constructor (
|
||||
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.24;
|
||||
|
||||
|
||||
import "../token/ERC20/BasicToken.sol";
|
||||
@ -7,7 +7,7 @@ import "../token/ERC20/BasicToken.sol";
|
||||
// mock class using BasicToken
|
||||
contract BasicTokenMock is BasicToken {
|
||||
|
||||
function BasicTokenMock(address initialAccount, uint256 initialBalance) public {
|
||||
constructor(address initialAccount, uint256 initialBalance) public {
|
||||
balances[initialAccount] = initialBalance;
|
||||
totalSupply_ = initialBalance;
|
||||
}
|
||||
|
||||
54
contracts/mocks/BouncerMock.sol
Normal file
54
contracts/mocks/BouncerMock.sol
Normal file
@ -0,0 +1,54 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
function checkValidSignatureAndMethod(address _address, bytes _sig)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return isValidSignatureAndMethod(_address, _sig);
|
||||
}
|
||||
|
||||
function onlyWithValidSignatureAndMethod(bytes _sig)
|
||||
onlyValidSignatureAndMethod(_sig)
|
||||
public
|
||||
view
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
function checkValidSignatureAndData(address _address, bytes _bytes, uint _val, bytes _sig)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return isValidSignatureAndData(_address, _sig);
|
||||
}
|
||||
|
||||
function onlyWithValidSignatureAndData(uint _val, bytes _sig)
|
||||
onlyValidSignatureAndData(_sig)
|
||||
public
|
||||
view
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,11 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/BurnableToken.sol";
|
||||
|
||||
|
||||
contract BurnableTokenMock is BurnableToken {
|
||||
|
||||
function BurnableTokenMock(address initialAccount, uint initialBalance) public {
|
||||
constructor(address initialAccount, uint initialBalance) public {
|
||||
balances[initialAccount] = initialBalance;
|
||||
totalSupply_ = initialBalance;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
@ -6,12 +6,12 @@ import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
|
||||
contract CappedCrowdsaleImpl is CappedCrowdsale {
|
||||
|
||||
function CappedCrowdsaleImpl (
|
||||
constructor (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token,
|
||||
uint256 _cap
|
||||
)
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
CappedCrowdsale(_cap)
|
||||
|
||||
18
contracts/mocks/ConditionalEscrowMock.sol
Normal file
18
contracts/mocks/ConditionalEscrowMock.sol
Normal file
@ -0,0 +1,18 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../payment/ConditionalEscrow.sol";
|
||||
|
||||
|
||||
// mock class using ConditionalEscrow
|
||||
contract ConditionalEscrowMock is ConditionalEscrow {
|
||||
mapping(address => bool) public allowed;
|
||||
|
||||
function setAllowed(address _payee, bool _allowed) public {
|
||||
allowed[_payee] = _allowed;
|
||||
}
|
||||
|
||||
function withdrawalAllowed(address _payee) public view returns (bool) {
|
||||
return allowed[_payee];
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import "../../contracts/DayLimit.sol";
|
||||
|
||||
|
||||
contract DayLimitMock is DayLimit {
|
||||
uint256 public totalSpending;
|
||||
|
||||
function DayLimitMock(uint256 _value) public DayLimit(_value) {
|
||||
totalSpending = 0;
|
||||
}
|
||||
|
||||
function attemptSpend(uint256 _value) external limitedDaily(_value) {
|
||||
totalSpending += _value;
|
||||
}
|
||||
|
||||
function setDailyLimit(uint256 _newLimit) external {
|
||||
_setDailyLimit(_newLimit);
|
||||
}
|
||||
|
||||
function resetSpentToday() external {
|
||||
_resetSpentToday();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,9 +1,16 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
import "../token/ERC20/DetailedERC20.sol";
|
||||
|
||||
|
||||
contract DetailedERC20Mock is StandardToken, DetailedERC20 {
|
||||
function DetailedERC20Mock(string _name, string _symbol, uint8 _decimals) DetailedERC20(_name, _symbol, _decimals) public {}
|
||||
constructor(
|
||||
string _name,
|
||||
string _symbol,
|
||||
uint8 _decimals
|
||||
)
|
||||
DetailedERC20(_name, _symbol, _decimals)
|
||||
public
|
||||
{}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
13
contracts/mocks/ERC20WithMetadataMock.sol
Normal file
13
contracts/mocks/ERC20WithMetadataMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
import "../proposals/ERC1046/TokenMetadata.sol";
|
||||
|
||||
|
||||
contract ERC20WithMetadataMock is StandardToken, ERC20WithMetadata {
|
||||
function ERC20WithMetadataMock(string _tokenURI)
|
||||
ERC20WithMetadata(_tokenURI)
|
||||
public
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,16 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
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 {
|
||||
constructor(address initialAccount, uint256 initialBalance) public {
|
||||
balances[initialAccount] = initialBalance;
|
||||
totalSupply_ = initialBalance;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC721/ERC721BasicToken.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC721BasicTokenMock
|
||||
* This mock just provides a public mint and burn functions for testing purposes
|
||||
|
||||
@ -1,21 +1,42 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
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 {
|
||||
event Received(
|
||||
address _operator,
|
||||
address _from,
|
||||
uint256 _tokenId,
|
||||
bytes _data,
|
||||
uint256 _gas
|
||||
);
|
||||
|
||||
constructor(bytes4 _retval, bool _reverts) public {
|
||||
retval = _retval;
|
||||
reverts = _reverts;
|
||||
}
|
||||
|
||||
function onERC721Received(address _address, uint256 _tokenId, bytes _data) public returns(bytes4) {
|
||||
function onERC721Received(
|
||||
address _operator,
|
||||
address _from,
|
||||
uint256 _tokenId,
|
||||
bytes _data
|
||||
)
|
||||
public
|
||||
returns(bytes4)
|
||||
{
|
||||
require(!reverts);
|
||||
Received(_address, _tokenId, _data, msg.gas);
|
||||
emit Received(
|
||||
_operator,
|
||||
_from,
|
||||
_tokenId,
|
||||
_data,
|
||||
gasleft() // msg.gas was deprecated in solidityv0.4.21
|
||||
);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC721/ERC721Token.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC721TokenMock
|
||||
* 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(string name, string symbol) public
|
||||
constructor(string name, string symbol) public
|
||||
ERC721Token(name, symbol)
|
||||
{ }
|
||||
|
||||
@ -23,4 +24,4 @@ contract ERC721TokenMock is ERC721Token {
|
||||
function setTokenURI(uint256 _tokenId, string _uri) public {
|
||||
super._setTokenURI(_tokenId, _uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
pragma solidity ^0.4.13;
|
||||
|
||||
|
||||
import "../token/ERC827/ERC827Token.sol";
|
||||
|
||||
|
||||
// mock class using ERC827 Token
|
||||
contract ERC827TokenMock is ERC827Token {
|
||||
|
||||
function ERC827TokenMock(address initialAccount, uint256 initialBalance) public {
|
||||
balances[initialAccount] = initialBalance;
|
||||
totalSupply_ = initialBalance;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
import "../crowdsale/distribution/FinalizableCrowdsale.sol";
|
||||
@ -6,13 +6,13 @@ import "../crowdsale/distribution/FinalizableCrowdsale.sol";
|
||||
|
||||
contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
|
||||
|
||||
function FinalizableCrowdsaleImpl (
|
||||
constructor (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
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.24;
|
||||
|
||||
|
||||
// @title Force Ether into a contract.
|
||||
@ -8,7 +8,7 @@ pragma solidity ^0.4.18;
|
||||
// @author Remco Bloemen <remco@neufund.org>
|
||||
contract ForceEther {
|
||||
|
||||
function ForceEther() public payable { }
|
||||
constructor() public payable { }
|
||||
|
||||
function destroyAndSend(address _recipient) public {
|
||||
selfdestruct(_recipient);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../contracts/ownership/HasNoEther.sol";
|
||||
|
||||
@ -6,7 +6,7 @@ import "../../contracts/ownership/HasNoEther.sol";
|
||||
contract HasNoEtherTest is HasNoEther {
|
||||
|
||||
// Constructor with explicit payable — should still fail
|
||||
function HasNoEtherTest() public payable {
|
||||
constructor() public payable {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../crowdsale/price/IncreasingPriceCrowdsale.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
@ -6,14 +6,14 @@ import "../math/SafeMath.sol";
|
||||
|
||||
contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale {
|
||||
|
||||
function IncreasingPriceCrowdsaleImpl (
|
||||
constructor (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
address _wallet,
|
||||
ERC20 _token,
|
||||
uint256 _initialRate,
|
||||
uint256 _finalRate
|
||||
)
|
||||
)
|
||||
public
|
||||
Crowdsale(_initialRate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol";
|
||||
|
||||
|
||||
contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale {
|
||||
|
||||
function IndividuallyCappedCrowdsaleImpl (
|
||||
|
||||
constructor (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
{
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import {Bounty, Target} from "../../contracts/Bounty.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
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.24;
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
19
contracts/mocks/MerkleProofWrapper.sol
Normal file
19
contracts/mocks/MerkleProofWrapper.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
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,37 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
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);
|
||||
function showMessage(
|
||||
bytes32 message,
|
||||
uint256 number,
|
||||
string text
|
||||
)
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
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 +40,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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
import "../crowdsale/emission/MintedCrowdsale.sol";
|
||||
@ -6,11 +6,11 @@ import "../crowdsale/emission/MintedCrowdsale.sol";
|
||||
|
||||
contract MintedCrowdsaleImpl is MintedCrowdsale {
|
||||
|
||||
function MintedCrowdsaleImpl (
|
||||
constructor (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
MintableToken _token
|
||||
)
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
{
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../lifecycle/Pausable.sol";
|
||||
@ -9,7 +9,7 @@ contract PausableMock is Pausable {
|
||||
bool public drasticMeasureTaken;
|
||||
uint256 public count;
|
||||
|
||||
function PausableMock() public {
|
||||
constructor() public {
|
||||
drasticMeasureTaken = false;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/PausableToken.sol";
|
||||
|
||||
@ -6,7 +6,7 @@ import "../token/ERC20/PausableToken.sol";
|
||||
// mock class using PausableToken
|
||||
contract PausableTokenMock is PausableToken {
|
||||
|
||||
function PausableTokenMock(address initialAccount, uint initialBalance) public {
|
||||
constructor(address initialAccount, uint initialBalance) public {
|
||||
balances[initialAccount] = initialBalance;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/distribution/PostDeliveryCrowdsale.sol";
|
||||
@ -6,13 +6,13 @@ import "../crowdsale/distribution/PostDeliveryCrowdsale.sol";
|
||||
|
||||
contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale {
|
||||
|
||||
function PostDeliveryCrowdsaleImpl (
|
||||
constructor (
|
||||
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.24;
|
||||
|
||||
|
||||
import "../payment/PullPayment.sol";
|
||||
@ -7,11 +7,11 @@ import "../payment/PullPayment.sol";
|
||||
// mock class using PullPayment
|
||||
contract PullPaymentMock is PullPayment {
|
||||
|
||||
function PullPaymentMock() public payable { }
|
||||
constructor() public payable { }
|
||||
|
||||
// test helper function to call asyncSend
|
||||
function callSend(address dest, uint256 amount) public {
|
||||
asyncSend(dest, amount);
|
||||
// test helper function to call asyncTransfer
|
||||
function callTransfer(address dest, uint256 amount) public {
|
||||
asyncTransfer(dest, amount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
13
contracts/mocks/RBACCappedTokenMock.sol
Normal file
13
contracts/mocks/RBACCappedTokenMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/RBACMintableToken.sol";
|
||||
import "../token/ERC20/CappedToken.sol";
|
||||
|
||||
contract RBACCappedTokenMock is CappedToken, RBACMintableToken {
|
||||
constructor(
|
||||
uint256 _cap
|
||||
)
|
||||
CappedToken(_cap)
|
||||
public
|
||||
{}
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
pragma solidity ^0.4.8;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../ownership/rbac/RBAC.sol";
|
||||
import "../examples/RBACWithAdmin.sol";
|
||||
|
||||
|
||||
contract RBACMock is RBAC {
|
||||
contract RBACMock is RBACWithAdmin {
|
||||
|
||||
string constant ROLE_ADVISOR = "advisor";
|
||||
|
||||
@ -16,7 +16,7 @@ contract RBACMock is RBAC {
|
||||
_;
|
||||
}
|
||||
|
||||
function RBACMock(address[] _advisors)
|
||||
constructor(address[] _advisors)
|
||||
public
|
||||
{
|
||||
addRole(msg.sender, ROLE_ADVISOR);
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
contract ReentrancyAttack {
|
||||
|
||||
function callSender(bytes4 data) public {
|
||||
require(msg.sender.call(data));
|
||||
// solium-disable-next-line security/no-low-level-calls
|
||||
require(msg.sender.call(abi.encodeWithSelector(data)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../ReentrancyGuard.sol";
|
||||
import "./ReentrancyAttack.sol";
|
||||
@ -8,7 +8,7 @@ contract ReentrancyMock is ReentrancyGuard {
|
||||
|
||||
uint256 public counter;
|
||||
|
||||
function ReentrancyMock() public {
|
||||
constructor() public {
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
@ -24,10 +24,10 @@ contract ReentrancyMock is ReentrancyGuard {
|
||||
}
|
||||
|
||||
function countThisRecursive(uint256 n) public nonReentrant {
|
||||
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(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1));
|
||||
require(result == true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||
|
||||
|
||||
contract RefundableCrowdsaleImpl is RefundableCrowdsale {
|
||||
|
||||
function RefundableCrowdsaleImpl (
|
||||
constructor (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
MintableToken _token,
|
||||
uint256 _goal
|
||||
)
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
@ -21,11 +21,11 @@ contract ERC20FailingMock is ERC20 {
|
||||
return false;
|
||||
}
|
||||
|
||||
function balanceOf(address) public constant returns (uint256) {
|
||||
function balanceOf(address) public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function allowance(address, address) public constant returns (uint256) {
|
||||
function allowance(address, address) public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,7 @@ contract ERC20SucceedingMock is ERC20 {
|
||||
function totalSupply() public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function transfer(address, uint256) public returns (bool) {
|
||||
return true;
|
||||
}
|
||||
@ -48,11 +48,11 @@ contract ERC20SucceedingMock is ERC20 {
|
||||
return true;
|
||||
}
|
||||
|
||||
function balanceOf(address) public constant returns (uint256) {
|
||||
function balanceOf(address) public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function allowance(address, address) public constant returns (uint256) {
|
||||
function allowance(address, address) public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -64,32 +64,32 @@ contract SafeERC20Helper {
|
||||
ERC20 failing;
|
||||
ERC20 succeeding;
|
||||
|
||||
function SafeERC20Helper() public {
|
||||
constructor() public {
|
||||
failing = new ERC20FailingMock();
|
||||
succeeding = new ERC20SucceedingMock();
|
||||
}
|
||||
|
||||
function doFailingTransfer() public {
|
||||
failing.safeTransfer(0, 0);
|
||||
failing.safeTransfer(address(0), 0);
|
||||
}
|
||||
|
||||
function doFailingTransferFrom() public {
|
||||
failing.safeTransferFrom(0, 0, 0);
|
||||
failing.safeTransferFrom(address(0), address(0), 0);
|
||||
}
|
||||
|
||||
function doFailingApprove() public {
|
||||
failing.safeApprove(0, 0);
|
||||
failing.safeApprove(address(0), 0);
|
||||
}
|
||||
|
||||
function doSucceedingTransfer() public {
|
||||
succeeding.safeTransfer(0, 0);
|
||||
succeeding.safeTransfer(address(0), 0);
|
||||
}
|
||||
|
||||
function doSucceedingTransferFrom() public {
|
||||
succeeding.safeTransferFrom(0, 0, 0);
|
||||
succeeding.safeTransferFrom(address(0), address(0), 0);
|
||||
}
|
||||
|
||||
function doSucceedingApprove() public {
|
||||
succeeding.safeApprove(0, 0);
|
||||
succeeding.safeApprove(address(0), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,21 +1,24 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
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.24;
|
||||
|
||||
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.24;
|
||||
|
||||
import "../token/ERC20/StandardBurnableToken.sol";
|
||||
|
||||
|
||||
contract StandardBurnableTokenMock is StandardBurnableToken {
|
||||
|
||||
constructor(address initialAccount, uint initialBalance) public {
|
||||
balances[initialAccount] = initialBalance;
|
||||
totalSupply_ = initialBalance;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,11 +1,12 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
|
||||
|
||||
// mock class using StandardToken
|
||||
contract StandardTokenMock is StandardToken {
|
||||
|
||||
function StandardTokenMock(address initialAccount, uint256 initialBalance) public {
|
||||
constructor(address initialAccount, uint256 initialBalance) public {
|
||||
balances[initialAccount] = initialBalance;
|
||||
totalSupply_ = initialBalance;
|
||||
}
|
||||
|
||||
12
contracts/mocks/SupportsInterfaceWithLookupMock.sol
Normal file
12
contracts/mocks/SupportsInterfaceWithLookupMock.sol
Normal file
@ -0,0 +1,12 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../introspection/SupportsInterfaceWithLookup.sol";
|
||||
|
||||
|
||||
contract SupportsInterfaceWithLookupMock is SupportsInterfaceWithLookup {
|
||||
function registerInterface(bytes4 _interfaceId)
|
||||
public
|
||||
{
|
||||
_registerInterface(_interfaceId);
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,18 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/TimedCrowdsale.sol";
|
||||
|
||||
|
||||
contract TimedCrowdsaleImpl is TimedCrowdsale {
|
||||
|
||||
function TimedCrowdsaleImpl (
|
||||
constructor (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
import "../ownership/Whitelist.sol";
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../access/Whitelist.sol";
|
||||
|
||||
contract WhitelistMock is Whitelist {
|
||||
|
||||
function onlyWhitelistedCanDoThis()
|
||||
onlyWhitelisted
|
||||
onlyIfWhitelisted(msg.sender)
|
||||
view
|
||||
external
|
||||
{
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/WhitelistedCrowdsale.sol";
|
||||
import "../crowdsale/Crowdsale.sol";
|
||||
|
||||
|
||||
contract WhitelistedCrowdsaleImpl is WhitelistedCrowdsale {
|
||||
contract WhitelistedCrowdsaleImpl is Crowdsale, WhitelistedCrowdsale {
|
||||
|
||||
function WhitelistedCrowdsaleImpl (
|
||||
constructor (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
public
|
||||
)
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
public
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "./Ownable.sol";
|
||||
import "../token/ERC20/ERC20Basic.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
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.24;
|
||||
|
||||
import "./Ownable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
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.24;
|
||||
|
||||
import "./Ownable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "./Ownable.sol";
|
||||
|
||||
@ -8,21 +8,21 @@ 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 {
|
||||
|
||||
/**
|
||||
* @dev Constructor that rejects incoming Ether
|
||||
* @dev The `payable` flag is added so we can access `msg.value` without compiler warning. If we
|
||||
* The `payable` flag is added so we can access `msg.value` without compiler warning. If we
|
||||
* leave out payable, then Solidity will allow inheriting contracts to implement a payable
|
||||
* constructor. By doing it this way we prevent a payable constructor from working. Alternatively
|
||||
* we could use assembly to access msg.value.
|
||||
*/
|
||||
function HasNoEther() public payable {
|
||||
constructor() public payable {
|
||||
require(msg.value == 0);
|
||||
}
|
||||
|
||||
@ -36,6 +36,6 @@ contract HasNoEther is Ownable {
|
||||
* @dev Transfer all Ether held by the contract to the owner.
|
||||
*/
|
||||
function reclaimEther() external onlyOwner {
|
||||
assert(owner.send(this.balance));
|
||||
owner.transfer(address(this).balance);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "./CanReclaimToken.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "./Ownable.sol";
|
||||
@ -21,8 +21,15 @@ contract Heritable is Ownable {
|
||||
|
||||
event HeirChanged(address indexed owner, address indexed newHeir);
|
||||
event OwnerHeartbeated(address indexed owner);
|
||||
event OwnerProclaimedDead(address indexed owner, address indexed heir, uint256 timeOfDeath);
|
||||
event HeirOwnershipClaimed(address indexed previousOwner, address indexed newOwner);
|
||||
event OwnerProclaimedDead(
|
||||
address indexed owner,
|
||||
address indexed heir,
|
||||
uint256 timeOfDeath
|
||||
);
|
||||
event HeirOwnershipClaimed(
|
||||
address indexed previousOwner,
|
||||
address indexed newOwner
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
@ -39,14 +46,14 @@ contract Heritable is Ownable {
|
||||
* @param _heartbeatTimeout time available for the owner to notify they are alive,
|
||||
* before the heir can take ownership.
|
||||
*/
|
||||
function Heritable(uint256 _heartbeatTimeout) public {
|
||||
constructor(uint256 _heartbeatTimeout) public {
|
||||
setHeartbeatTimeout(_heartbeatTimeout);
|
||||
}
|
||||
|
||||
function setHeir(address newHeir) public onlyOwner {
|
||||
require(newHeir != owner);
|
||||
heartbeat();
|
||||
HeirChanged(owner, newHeir);
|
||||
emit HeirChanged(owner, newHeir);
|
||||
heir_ = newHeir;
|
||||
}
|
||||
|
||||
@ -61,7 +68,7 @@ contract Heritable is Ownable {
|
||||
function heartbeatTimeout() public view returns(uint256) {
|
||||
return heartbeatTimeout_;
|
||||
}
|
||||
|
||||
|
||||
function timeOfDeath() public view returns(uint256) {
|
||||
return timeOfDeath_;
|
||||
}
|
||||
@ -71,7 +78,7 @@ contract Heritable is Ownable {
|
||||
*/
|
||||
function removeHeir() public onlyOwner {
|
||||
heartbeat();
|
||||
heir_ = 0;
|
||||
heir_ = address(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,7 +87,8 @@ contract Heritable is Ownable {
|
||||
*/
|
||||
function proclaimDeath() public onlyHeir {
|
||||
require(ownerLives());
|
||||
OwnerProclaimedDead(owner, heir_, timeOfDeath_);
|
||||
emit OwnerProclaimedDead(owner, heir_, timeOfDeath_);
|
||||
// solium-disable-next-line security/no-block-members
|
||||
timeOfDeath_ = block.timestamp;
|
||||
}
|
||||
|
||||
@ -88,7 +96,7 @@ contract Heritable is Ownable {
|
||||
* @dev Owner can send a heartbeat if they were mistakenly pronounced dead.
|
||||
*/
|
||||
function heartbeat() public onlyOwner {
|
||||
OwnerHeartbeated(owner);
|
||||
emit OwnerHeartbeated(owner);
|
||||
timeOfDeath_ = 0;
|
||||
}
|
||||
|
||||
@ -97,14 +105,17 @@ contract Heritable is Ownable {
|
||||
*/
|
||||
function claimHeirOwnership() public onlyHeir {
|
||||
require(!ownerLives());
|
||||
// solium-disable-next-line security/no-block-members
|
||||
require(block.timestamp >= timeOfDeath_ + heartbeatTimeout_);
|
||||
OwnershipTransferred(owner, heir_);
|
||||
HeirOwnershipClaimed(owner, heir_);
|
||||
emit OwnershipTransferred(owner, heir_);
|
||||
emit HeirOwnershipClaimed(owner, heir_);
|
||||
owner = heir_;
|
||||
timeOfDeath_ = 0;
|
||||
}
|
||||
|
||||
function setHeartbeatTimeout(uint256 newHeartbeatTimeout) internal onlyOwner {
|
||||
function setHeartbeatTimeout(uint256 newHeartbeatTimeout)
|
||||
internal onlyOwner
|
||||
{
|
||||
require(ownerLives());
|
||||
heartbeatTimeout_ = newHeartbeatTimeout;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "./HasNoEther.sol";
|
||||
import "./HasNoTokens.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
@ -10,14 +10,18 @@ contract Ownable {
|
||||
address public owner;
|
||||
|
||||
|
||||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
|
||||
event OwnershipRenounced(address indexed previousOwner);
|
||||
event OwnershipTransferred(
|
||||
address indexed previousOwner,
|
||||
address indexed newOwner
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
|
||||
* account.
|
||||
*/
|
||||
function Ownable() public {
|
||||
constructor() public {
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
@ -30,13 +34,31 @@ contract Ownable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Allows the current owner to transfer control of the contract to a newOwner.
|
||||
* @param newOwner The address to transfer ownership to.
|
||||
* @dev Allows the current owner to relinquish control of the contract.
|
||||
* @notice Renouncing to ownership will leave the contract without an owner.
|
||||
* It will not be possible to call the functions with the `onlyOwner`
|
||||
* modifier anymore.
|
||||
*/
|
||||
function transferOwnership(address newOwner) public onlyOwner {
|
||||
require(newOwner != address(0));
|
||||
OwnershipTransferred(owner, newOwner);
|
||||
owner = newOwner;
|
||||
function renounceOwnership() public onlyOwner {
|
||||
emit OwnershipRenounced(owner);
|
||||
owner = address(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Allows the current owner to transfer control of the contract to a newOwner.
|
||||
* @param _newOwner The address to transfer ownership to.
|
||||
*/
|
||||
function transferOwnership(address _newOwner) public onlyOwner {
|
||||
_transferOwnership(_newOwner);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers control of the contract to a newOwner.
|
||||
* @param _newOwner The address to transfer ownership to.
|
||||
*/
|
||||
function _transferOwnership(address _newOwner) internal {
|
||||
require(_newOwner != address(0));
|
||||
emit OwnershipTransferred(owner, _newOwner);
|
||||
owner = _newOwner;
|
||||
}
|
||||
}
|
||||
|
||||
62
contracts/ownership/Superuser.sol
Normal file
62
contracts/ownership/Superuser.sol
Normal file
@ -0,0 +1,62 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "./Ownable.sol";
|
||||
import "./rbac/RBAC.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Superuser
|
||||
* @dev The Superuser contract defines a single superuser who can transfer the ownership
|
||||
* of a contract to a new address, even if he is not the owner.
|
||||
* A superuser can transfer his role to a new address.
|
||||
*/
|
||||
contract Superuser is Ownable, RBAC {
|
||||
string public constant ROLE_SUPERUSER = "superuser";
|
||||
|
||||
constructor () public {
|
||||
addRole(msg.sender, ROLE_SUPERUSER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Throws if called by any account that's not a superuser.
|
||||
*/
|
||||
modifier onlySuperuser() {
|
||||
checkRole(msg.sender, ROLE_SUPERUSER);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyOwnerOrSuperuser() {
|
||||
require(msg.sender == owner || isSuperuser(msg.sender));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev getter to determine if address has superuser role
|
||||
*/
|
||||
function isSuperuser(address _addr)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return hasRole(_addr, ROLE_SUPERUSER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Allows the current superuser to transfer his role to a newSuperuser.
|
||||
* @param _newSuperuser The address to transfer ownership to.
|
||||
*/
|
||||
function transferSuperuser(address _newSuperuser) public onlySuperuser {
|
||||
require(_newSuperuser != address(0));
|
||||
removeRole(msg.sender, ROLE_SUPERUSER);
|
||||
addRole(_newSuperuser, ROLE_SUPERUSER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Allows the current superuser or owner to transfer control of the contract to a newOwner.
|
||||
* @param _newOwner The address to transfer ownership to.
|
||||
*/
|
||||
function transferOwnership(address _newOwner) public onlyOwnerOrSuperuser {
|
||||
_transferOwnership(_newOwner);
|
||||
}
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
|
||||
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;
|
||||
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;
|
||||
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.24;
|
||||
|
||||
import "./Roles.sol";
|
||||
|
||||
@ -7,143 +7,95 @@ 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.
|
||||
* Supports unlimited numbers of roles and addresses.
|
||||
* 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.
|
||||
* 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,
|
||||
* to avoid typos.
|
||||
* to avoid typos.
|
||||
*/
|
||||
contract RBAC {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
mapping (string => Roles.Role) private roles;
|
||||
|
||||
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);
|
||||
}
|
||||
event RoleAdded(address indexed operator, string role);
|
||||
event RoleRemoved(address indexed operator, string role);
|
||||
|
||||
/**
|
||||
* @dev reverts if addr does not have role
|
||||
* @param addr address
|
||||
* @param roleName the name of the role
|
||||
* @param _operator address
|
||||
* @param _role the name of the role
|
||||
* // reverts
|
||||
*/
|
||||
function checkRole(address addr, string roleName)
|
||||
function checkRole(address _operator, string _role)
|
||||
view
|
||||
public
|
||||
{
|
||||
roles[roleName].check(addr);
|
||||
roles[_role].check(_operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev determine if addr has role
|
||||
* @param addr address
|
||||
* @param roleName the name of the role
|
||||
* @param _operator address
|
||||
* @param _role the name of the role
|
||||
* @return bool
|
||||
*/
|
||||
function hasRole(address addr, string roleName)
|
||||
function hasRole(address _operator, string _role)
|
||||
view
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
return roles[roleName].has(addr);
|
||||
return roles[_role].has(_operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add a role to an address
|
||||
* @param addr address
|
||||
* @param roleName the name of the role
|
||||
* @param _operator address
|
||||
* @param _role the name of the role
|
||||
*/
|
||||
function adminAddRole(address addr, string roleName)
|
||||
onlyAdmin
|
||||
public
|
||||
function addRole(address _operator, string _role)
|
||||
internal
|
||||
{
|
||||
addRole(addr, roleName);
|
||||
roles[_role].add(_operator);
|
||||
emit RoleAdded(_operator, _role);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove a role from an address
|
||||
* @param addr address
|
||||
* @param roleName the name of the role
|
||||
* @param _operator address
|
||||
* @param _role 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
|
||||
* @param roleName the name of the role
|
||||
*/
|
||||
function addRole(address addr, string roleName)
|
||||
function removeRole(address _operator, string _role)
|
||||
internal
|
||||
{
|
||||
roles[roleName].add(addr);
|
||||
RoleAdded(addr, roleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove a role from an address
|
||||
* @param addr address
|
||||
* @param roleName the name of the role
|
||||
*/
|
||||
function removeRole(address addr, string roleName)
|
||||
internal
|
||||
{
|
||||
roles[roleName].remove(addr);
|
||||
RoleRemoved(addr, roleName);
|
||||
roles[_role].remove(_operator);
|
||||
emit RoleRemoved(_operator, _role);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev modifier to scope access to a single role (uses msg.sender as addr)
|
||||
* @param roleName the name of the role
|
||||
* @param _role the name of the role
|
||||
* // reverts
|
||||
*/
|
||||
modifier onlyRole(string roleName)
|
||||
modifier onlyRole(string _role)
|
||||
{
|
||||
checkRole(msg.sender, roleName);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev modifier to scope access to admins
|
||||
* // reverts
|
||||
*/
|
||||
modifier onlyAdmin()
|
||||
{
|
||||
checkRole(msg.sender, ROLE_ADMIN);
|
||||
checkRole(msg.sender, _role);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param _roles the names of the roles to scope access to
|
||||
* // reverts
|
||||
*
|
||||
* @TODO - when solidity supports dynamic arrays as arguments to modifiers, provide this
|
||||
* see: https://github.com/ethereum/solidity/issues/2467
|
||||
*/
|
||||
// modifier onlyRoles(string[] roleNames) {
|
||||
// modifier onlyRoles(string[] _roles) {
|
||||
// bool hasAnyRole = false;
|
||||
// for (uint8 i = 0; i < roleNames.length; i++) {
|
||||
// if (hasRole(msg.sender, roleNames[i])) {
|
||||
// for (uint8 i = 0; i < _roles.length; i++) {
|
||||
// if (hasRole(msg.sender, _roles[i])) {
|
||||
// hasAnyRole = true;
|
||||
// break;
|
||||
// }
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @title Roles
|
||||
* @author Francisco Giordano (@frangio)
|
||||
* @dev Library for managing addresses assigned to a Role.
|
||||
* See RBAC.sol for example usage.
|
||||
* See RBAC.sol for example usage.
|
||||
*/
|
||||
library Roles {
|
||||
struct Role {
|
||||
|
||||
22
contracts/payment/ConditionalEscrow.sol
Normal file
22
contracts/payment/ConditionalEscrow.sol
Normal file
@ -0,0 +1,22 @@
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
import "./Escrow.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title ConditionalEscrow
|
||||
* @dev Base abstract escrow to only allow withdrawal if a condition is met.
|
||||
*/
|
||||
contract ConditionalEscrow is Escrow {
|
||||
/**
|
||||
* @dev Returns whether an address is allowed to withdraw their funds. To be
|
||||
* implemented by derived contracts.
|
||||
* @param _payee The destination address of the funds.
|
||||
*/
|
||||
function withdrawalAllowed(address _payee) public view returns (bool);
|
||||
|
||||
function withdraw(address _payee) public {
|
||||
require(withdrawalAllowed(_payee));
|
||||
super.withdraw(_payee);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user