Compare commits
41 Commits
v2.2.3
...
v2.3.0-rc.
| Author | SHA1 | Date | |
|---|---|---|---|
| a3af8266db | |||
| 9d868ee846 | |||
| 2f8e844514 | |||
| 3682c6575c | |||
| 4a0a67b04c | |||
| 97a9ca5681 | |||
| 19c7414052 | |||
| 5e46cf6de4 | |||
| ed5652b0aa | |||
| 412cdfd0be | |||
| 59f03f00c5 | |||
| ea59f86cdf | |||
| 0df0e1b250 | |||
| 5a2b349992 | |||
| 963f1eb35b | |||
| bbe0eefd9f | |||
| 19c705d928 | |||
| d45f0c89db | |||
| 1ebeef7ffd | |||
| b353f7e18c | |||
| 92e68e3aaa | |||
| 07fc8c731a | |||
| 81e36d2e74 | |||
| 35d8e860ad | |||
| 8b44efd035 | |||
| 3cb4a00fce | |||
| c008f1f0c6 | |||
| dc5ca8edc4 | |||
| 7ccd224567 | |||
| cf7375d6b8 | |||
| 308a4c9907 | |||
| 269e096c5a | |||
| edfce5a3dd | |||
| ab14debb08 | |||
| 40d2eb3007 | |||
| 2a37b09cf6 | |||
| 29fa0a4ce5 | |||
| 06f7266a6e | |||
| 4c706480e5 | |||
| 4dd8575bb6 | |||
| 9c69df5962 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -6,7 +6,7 @@ about: Report a bug in OpenZeppelin
|
||||
|
||||
<!-- Briefly describe the issue you're experiencing. Tell us what you were trying to do and what happened instead. -->
|
||||
|
||||
<!-- Remember, this is not a place to ask for help debugging code. For that, we welcome you in the OpenZeppelin Slack channel: https://slack.openzeppelin.org/. -->
|
||||
<!-- Remember, this is not a place to ask for help debugging code. For that, we welcome you in the Zeppelin Forum: https://forum.zeppelin.solutions/. -->
|
||||
|
||||
**💻 Environment**
|
||||
|
||||
|
||||
66
.github/stale.yml
vendored
Normal file
66
.github/stale.yml
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 15
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 15
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- on hold
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Set to true to ignore issues with an assignee (defaults to false)
|
||||
exemptAssignees: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: stale
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
Hi all!
|
||||
|
||||
This Pull Request has not had any recent activity, is it still relevant? If so, what is blocking it?
|
||||
Is there anything we can do to help move it forward?
|
||||
|
||||
Thanks!
|
||||
|
||||
|
||||
# Comment to post when removing the stale label.
|
||||
# unmarkComment: >
|
||||
# Your comment here.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
closeComment: >
|
||||
Hi folks!
|
||||
|
||||
This Pull Request is being closed as there was no response to the previous prompt.
|
||||
However, please leave a comment whenever you're ready to resume, so it can be reopened.
|
||||
|
||||
Thanks again!
|
||||
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 30
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
only: pulls
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
# pulls:
|
||||
# daysUntilStale: 30
|
||||
# markComment: >
|
||||
# This pull request has been automatically marked as stale because it has not had
|
||||
# recent activity. It will be closed if no further activity occurs. Thank you
|
||||
# for your contributions.
|
||||
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - confirmed
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -40,3 +40,7 @@ build/
|
||||
|
||||
# IntelliJ IDE
|
||||
.idea
|
||||
|
||||
# docsite artifacts
|
||||
docsite-build
|
||||
docs/api
|
||||
|
||||
@ -35,15 +35,6 @@ jobs:
|
||||
script: npm run test
|
||||
env: SOLC_NIGHTLY=true
|
||||
|
||||
- stage: update docs
|
||||
if: tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- curl
|
||||
script:
|
||||
- ./scripts/ci/trigger_docs_update "${TRAVIS_TAG}"
|
||||
|
||||
notifications:
|
||||
slack:
|
||||
rooms:
|
||||
|
||||
21
CHANGELOG.md
21
CHANGELOG.md
@ -1,10 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
## 2.3.0 (unreleased)
|
||||
|
||||
### New features:
|
||||
* `ERC1820`: added support for interacting with the [ERC1820](https://eips.ethereum.org/EIPS/eip-1820) registry contract (`IERC1820Registry`), as well as base contracts that can be registered as implementers there. ([#1677](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1677))
|
||||
* `ERC777`: initial support for the [ERC777 token](https://eips.ethereum.org/EIPS/eip-777), which has multiple improvements over `ERC20` such as built-in burning, a more straightforward permission system, and optional sender and receiver hooks on transfer (mandatory for contracts!). ([#1684](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1684))
|
||||
* All contracts now have revert reason strings, which give insight into error conditions, and help debug failing transactions. ([#1704](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1704))
|
||||
|
||||
### Improvements:
|
||||
* Upgraded the minimum compiler version to v0.5.7: this prevents users from encountering compiler bugs that were fixed in this version. ([#1724](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1724))
|
||||
|
||||
### Bugfixes:
|
||||
* `PostDeliveryCrowdsale`: some validations where skipped when paired with other crowdsale flavors, such as `AllowanceCrowdsale`, or `MintableCrowdsale` and `ERC20Capped`, which could cause buyers to not be able to claim their purchased tokens. ([#1721](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1721))
|
||||
|
||||
## 2.2.0 (2019-03-14)
|
||||
|
||||
### New features:
|
||||
* `ERC20Snapshot`: create snapshots on demand of the token balances and total supply, to later retrieve and e.g. calculate dividends at a past time. ([#1617](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1617))
|
||||
* `SafeERC20`: `ERC20` contracts with no return value (i.e. that revert on failure) are now supported. ([#1655](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/))
|
||||
* `SafeERC20`: `ERC20` contracts with no return value (i.e. that revert on failure) are now supported. ([#1655](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1655))
|
||||
* `ERC20`: added internal `_approve(address owner, address spender, uint256 value)`, allowing derived contracts to set the allowance of arbitrary accounts. ([#1609](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1609))
|
||||
* `ERC20Metadata`: added internal `_setTokenURI(string memory tokenURI)`. ([#1618](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1618))
|
||||
* `TimedCrowdsale`: added internal `_extendTime(uint256 newClosingTime)` as well as `TimedCrowdsaleExtended(uint256 prevClosingTime, uint256 newClosingTime)` event allowing to extend the crowdsale, as long as it hasn't already closed.
|
||||
@ -13,14 +26,14 @@
|
||||
* Upgraded the minimum compiler version to v0.5.2: this removes many Solidity warnings that were false positives. ([#1606](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1606))
|
||||
* `ECDSA`: `recover` no longer accepts malleable signatures (those using upper-range values for `s`, or 0/1 for `v`). ([#1622](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1622))
|
||||
* `ERC721`'s transfers are now more gas efficient due to removal of unnecessary `SafeMath` calls. ([#1610](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1610))
|
||||
* `Counter`'s API has been improved, and is now used by `ERC721` (though it is still in `drafts`). ([#1610](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1610))
|
||||
* Fixed variable shadowing issues. ([#1606](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1606))
|
||||
|
||||
### Bugfixes:
|
||||
* (minor) `SafeERC20`: `safeApprove` wasn't properly checking for a zero allowance when attempting to set a non-zero allowance. ([#1647](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1647))
|
||||
|
||||
### Breaking changes:
|
||||
* `TokenMetadata` (in drafts) has been renamed to `ERC20Metadata`. ([#1618](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1618))
|
||||
### Breaking changes in drafts:
|
||||
* `TokenMetadata` has been renamed to `ERC20Metadata`. ([#1618](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1618))
|
||||
* The library `Counter` has been renamed to `Counters` and its API has been improved. See an example in `ERC721`, lines [17](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/3cb4a00fce1da76196ac0ac3a0ae9702b99642b5/contracts/token/ERC721/ERC721.sol#L17) and [204](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/3cb4a00fce1da76196ac0ac3a0ae9702b99642b5/contracts/token/ERC721/ERC721.sol#L204). ([#1610](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1610))
|
||||
|
||||
## 2.1.3 (2019-02-26)
|
||||
* Backported `SafeERC20.safeApprove` bugfix. ([#1647](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1647))
|
||||
|
||||
19
DOCUMENTATION.md
Normal file
19
DOCUMENTATION.md
Normal file
@ -0,0 +1,19 @@
|
||||
We're building an improved documentation website. It's still in development and
|
||||
contributions will be really appreciated.
|
||||
|
||||
All of the content for the site is in this repository. The guides are in the
|
||||
[docs](/docs) directory, and the API Reference is extracted from comments in
|
||||
the source code. If you want to help improve the content, this is the
|
||||
repository you should be contributing to.
|
||||
|
||||
[`solidity-docgen`](https://github.com/OpenZeppelin/solidity-docgen/tree/next) is the
|
||||
program that extracts the API Reference from source code.
|
||||
|
||||
The [`openzeppelin-docsite`](https://github.com/OpenZeppelin/openzeppelin-docsite/tree/next)
|
||||
repository hosts the configuration for Docusaurus, the static site generator
|
||||
that we use.
|
||||
|
||||
To run the docsite locally you should run `npm run docsite start` on this
|
||||
repository. This will live reload as the guides are edited, but not with
|
||||
changes to the source code comments, for that you need to restart the server.
|
||||
This should be improved eventually (contributions welcome!).
|
||||
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Smart Contract Solutions, Inc.
|
||||
Copyright (c) 2016-2019 zOS Global Limited
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
npm install openzeppelin-solidity
|
||||
```
|
||||
|
||||
OpenZeppelin features a stable API, which means your contracts won't break unexpectedly when upgrading to a newer minor version. You can read ṫhe details in our [API Stability](https://forum.zeppelin.solutions/t/api-stability/138) document.
|
||||
|
||||
## Usage
|
||||
|
||||
To write your custom contracts, import ours and extend them through inheritance.
|
||||
@ -28,9 +30,9 @@ contract MyNFT is ERC721Full, ERC721Mintable {
|
||||
}
|
||||
```
|
||||
|
||||
> You need an ethereum development framework for the above import statements to work! Check out these guides for [Truffle] or [Embark].
|
||||
> You need an ethereum development framework for the above import statements to work! Check out these guides for [Truffle], [Embark] or [Buidler].
|
||||
|
||||
On our site you will find a few [guides] to learn about the different parts of OpenZeppelin, as well as [documentation for the API][API docs]. Keep in mind that the API docs are work in progress, and don’t hesitate to ask questions in [our Slack][Slack].
|
||||
On our site you will find a few [guides] to learn about the different parts of OpenZeppelin, as well as [documentation for the API][API docs]. Keep in mind that the API docs are work in progress, and don’t hesitate to ask questions in [our forum][forum].
|
||||
|
||||
## Security
|
||||
|
||||
@ -53,8 +55,9 @@ OpenZeppelin is released under the [MIT License](LICENSE).
|
||||
|
||||
[API docs]: https://openzeppelin.org/api/docs/token_ERC721_ERC721BasicToken.html
|
||||
[guides]: https://openzeppelin.org/api/docs/get-started.html
|
||||
[Slack]: https://slack.openzeppelin.org
|
||||
[forum]: https://forum.zeppelin.solutions
|
||||
[Zeppelin]: https://zeppelin.solutions
|
||||
[contribution guide]: CONTRIBUTING.md
|
||||
[Truffle]: https://truffleframework.com/docs/truffle/quickstart
|
||||
[Embark]: https://embark.status.im/docs/quick_start.html
|
||||
[Buidler]: https://buidler.dev/guides/#getting-started
|
||||
|
||||
@ -40,7 +40,7 @@ Once the CI run for the new tag is green, publish on npm under the `next` tag. Y
|
||||
npm publish --tag next
|
||||
```
|
||||
|
||||
Publish the release notes on GitHub and ask our community manager to announce the release candidate on at least Slack and Twitter.
|
||||
Publish the release notes on GitHub and the forum, and ask our community manager to announce the release candidate on at least Twitter.
|
||||
|
||||
## Creating the final release
|
||||
|
||||
|
||||
7
contracts/access/README.md
Normal file
7
contracts/access/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
sections:
|
||||
- title: Library
|
||||
contracts:
|
||||
- Roles
|
||||
- subdirectory: roles
|
||||
---
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title Roles
|
||||
@ -10,31 +10,27 @@ library Roles {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev give an account access to this role
|
||||
* @dev Give an account access to this role.
|
||||
*/
|
||||
function add(Role storage role, address account) internal {
|
||||
require(account != address(0));
|
||||
require(!has(role, account));
|
||||
|
||||
require(!has(role, account), "Roles: account already has role");
|
||||
role.bearer[account] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove an account's access to this role
|
||||
* @dev Remove an account's access to this role.
|
||||
*/
|
||||
function remove(Role storage role, address account) internal {
|
||||
require(account != address(0));
|
||||
require(has(role, account));
|
||||
|
||||
require(has(role, account), "Roles: account does not have role");
|
||||
role.bearer[account] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev check if an account has this role
|
||||
* @dev Check if an account has this role.
|
||||
* @return bool
|
||||
*/
|
||||
function has(Role storage role, address account) internal view returns (bool) {
|
||||
require(account != address(0));
|
||||
require(account != address(0), "Roles: account is the zero address");
|
||||
return role.bearer[account];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../Roles.sol";
|
||||
|
||||
@ -15,7 +15,7 @@ contract CapperRole {
|
||||
}
|
||||
|
||||
modifier onlyCapper() {
|
||||
require(isCapper(msg.sender));
|
||||
require(isCapper(msg.sender), "CapperRole: caller does not have the Capper role");
|
||||
_;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../Roles.sol";
|
||||
|
||||
@ -15,7 +15,7 @@ contract MinterRole {
|
||||
}
|
||||
|
||||
modifier onlyMinter() {
|
||||
require(isMinter(msg.sender));
|
||||
require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role");
|
||||
_;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../Roles.sol";
|
||||
|
||||
@ -15,7 +15,7 @@ contract PauserRole {
|
||||
}
|
||||
|
||||
modifier onlyPauser() {
|
||||
require(isPauser(msg.sender));
|
||||
require(isPauser(msg.sender), "PauserRole: caller does not have the Pauser role");
|
||||
_;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../Roles.sol";
|
||||
|
||||
@ -15,7 +15,7 @@ contract SignerRole {
|
||||
}
|
||||
|
||||
modifier onlySigner() {
|
||||
require(isSigner(msg.sender));
|
||||
require(isSigner(msg.sender), "SignerRole: caller does not have the Signer role");
|
||||
_;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../Roles.sol";
|
||||
|
||||
@ -19,7 +19,7 @@ contract WhitelistAdminRole {
|
||||
}
|
||||
|
||||
modifier onlyWhitelistAdmin() {
|
||||
require(isWhitelistAdmin(msg.sender));
|
||||
require(isWhitelistAdmin(msg.sender), "WhitelistAdminRole: caller does not have the WhitelistAdmin role");
|
||||
_;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../Roles.sol";
|
||||
import "./WhitelistAdminRole.sol";
|
||||
@ -18,7 +18,7 @@ contract WhitelistedRole is WhitelistAdminRole {
|
||||
Roles.Role private _whitelisteds;
|
||||
|
||||
modifier onlyWhitelisted() {
|
||||
require(isWhitelisted(msg.sender));
|
||||
require(isWhitelisted(msg.sender), "WhitelistedRole: caller does not have the Whitelisted role");
|
||||
_;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
@ -54,9 +54,9 @@ contract Crowdsale is ReentrancyGuard {
|
||||
* @param token Address of the token being sold
|
||||
*/
|
||||
constructor (uint256 rate, address payable wallet, IERC20 token) public {
|
||||
require(rate > 0);
|
||||
require(wallet != address(0));
|
||||
require(address(token) != address(0));
|
||||
require(rate > 0, "Crowdsale: rate is 0");
|
||||
require(wallet != address(0), "Crowdsale: wallet is the zero address");
|
||||
require(address(token) != address(0), "Crowdsale: token is the zero address");
|
||||
|
||||
_rate = rate;
|
||||
_wallet = wallet;
|
||||
@ -136,8 +136,8 @@ contract Crowdsale is ReentrancyGuard {
|
||||
* @param weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
require(beneficiary != address(0));
|
||||
require(weiAmount != 0);
|
||||
require(beneficiary != address(0), "Crowdsale: beneficiary is the zero address");
|
||||
require(weiAmount != 0, "Crowdsale: weiAmount is 0");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
11
contracts/crowdsale/README.md
Normal file
11
contracts/crowdsale/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
title: Crowdsales
|
||||
sections:
|
||||
- title: Core
|
||||
contracts:
|
||||
- Crowdsale
|
||||
- subdirectory: emission
|
||||
- subdirectory: price
|
||||
- subdirectory: validation
|
||||
- subdirectory: distribution
|
||||
---
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
@ -31,8 +31,8 @@ contract FinalizableCrowdsale is TimedCrowdsale {
|
||||
* work. Calls the contract's finalization function.
|
||||
*/
|
||||
function finalize() public {
|
||||
require(!_finalized);
|
||||
require(hasClosed());
|
||||
require(!_finalized, "FinalizableCrowdsale: already finalized");
|
||||
require(hasClosed(), "FinalizableCrowdsale: not closed");
|
||||
|
||||
_finalized = true;
|
||||
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../../ownership/Secondary.sol";
|
||||
import "../../token/ERC20/IERC20.sol";
|
||||
|
||||
/**
|
||||
* @title PostDeliveryCrowdsale
|
||||
@ -11,17 +13,23 @@ contract PostDeliveryCrowdsale is TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping(address => uint256) private _balances;
|
||||
__unstable__TokenVault private _vault;
|
||||
|
||||
constructor() public {
|
||||
_vault = new __unstable__TokenVault();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw tokens only after crowdsale ends.
|
||||
* @param beneficiary Whose tokens will be withdrawn.
|
||||
*/
|
||||
function withdrawTokens(address beneficiary) public {
|
||||
require(hasClosed());
|
||||
require(hasClosed(), "PostDeliveryCrowdsale: not closed");
|
||||
uint256 amount = _balances[beneficiary];
|
||||
require(amount > 0);
|
||||
require(amount > 0, "PostDeliveryCrowdsale: beneficiary is not due any tokens");
|
||||
|
||||
_balances[beneficiary] = 0;
|
||||
_deliverTokens(beneficiary, amount);
|
||||
_vault.transfer(token(), beneficiary, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,12 +40,26 @@ contract PostDeliveryCrowdsale is TimedCrowdsale {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent by storing balances instead of issuing tokens right away.
|
||||
* @dev Overrides parent by storing due balances, and delivering tokens to the vault instead of the end user. This
|
||||
* ensures that the tokens will be available by the time they are withdrawn (which may not be the case if
|
||||
* `_deliverTokens` was called later).
|
||||
* @param beneficiary Token purchaser
|
||||
* @param tokenAmount Amount of tokens purchased
|
||||
*/
|
||||
function _processPurchase(address beneficiary, uint256 tokenAmount) internal {
|
||||
_balances[beneficiary] = _balances[beneficiary].add(tokenAmount);
|
||||
_deliverTokens(address(_vault), tokenAmount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @title __unstable__TokenVault
|
||||
* @dev Similar to an Escrow for tokens, this contract allows its primary account to spend its tokens as it sees fit.
|
||||
* This contract is an internal helper for PostDeliveryCrowdsale, and should not be used outside of this context.
|
||||
*/
|
||||
// solhint-disable-next-line contract-name-camelcase
|
||||
contract __unstable__TokenVault is Secondary {
|
||||
function transfer(IERC20 token, address to, uint256 amount) public onlyPrimary {
|
||||
token.transfer(to, amount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "./FinalizableCrowdsale.sol";
|
||||
@ -28,7 +28,7 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
* @param goal Funding goal
|
||||
*/
|
||||
constructor (uint256 goal) public {
|
||||
require(goal > 0);
|
||||
require(goal > 0, "RefundableCrowdsale: goal is 0");
|
||||
_escrow = new RefundEscrow(wallet());
|
||||
_goal = goal;
|
||||
}
|
||||
@ -41,12 +41,12 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Investors can claim refunds here if crowdsale is unsuccessful
|
||||
* @dev Investors can claim refunds here if crowdsale is unsuccessful.
|
||||
* @param refundee Whose refund will be claimed.
|
||||
*/
|
||||
function claimRefund(address payable refundee) public {
|
||||
require(finalized());
|
||||
require(!goalReached());
|
||||
require(finalized(), "RefundableCrowdsale: not finalized");
|
||||
require(!goalReached(), "RefundableCrowdsale: goal reached");
|
||||
|
||||
_escrow.withdraw(refundee);
|
||||
}
|
||||
@ -60,7 +60,7 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev escrow finalization task, called when finalize() is called
|
||||
* @dev Escrow finalization task, called when finalize() is called.
|
||||
*/
|
||||
function _finalization() internal {
|
||||
if (goalReached()) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "./RefundableCrowdsale.sol";
|
||||
import "./PostDeliveryCrowdsale.sol";
|
||||
@ -12,8 +12,8 @@ import "./PostDeliveryCrowdsale.sol";
|
||||
*/
|
||||
contract RefundablePostDeliveryCrowdsale is RefundableCrowdsale, PostDeliveryCrowdsale {
|
||||
function withdrawTokens(address beneficiary) public {
|
||||
require(finalized());
|
||||
require(goalReached());
|
||||
require(finalized(), "RefundablePostDeliveryCrowdsale: not finalized");
|
||||
require(goalReached(), "RefundablePostDeliveryCrowdsale: goal not reached");
|
||||
|
||||
super.withdrawTokens(beneficiary);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/IERC20.sol";
|
||||
@ -18,10 +18,10 @@ contract AllowanceCrowdsale is Crowdsale {
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes token wallet address.
|
||||
* @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale
|
||||
* @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale.
|
||||
*/
|
||||
constructor (address tokenWallet) public {
|
||||
require(tokenWallet != address(0));
|
||||
require(tokenWallet != address(0), "AllowanceCrowdsale: token wallet is the zero address");
|
||||
_tokenWallet = tokenWallet;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/ERC20Mintable.sol";
|
||||
@ -16,6 +16,9 @@ contract MintedCrowdsale is Crowdsale {
|
||||
*/
|
||||
function _deliverTokens(address beneficiary, uint256 tokenAmount) internal {
|
||||
// Potentially dangerous assumption about the type of the token.
|
||||
require(ERC20Mintable(address(token())).mint(beneficiary, tokenAmount));
|
||||
require(
|
||||
ERC20Mintable(address(token())).mint(beneficiary, tokenAmount),
|
||||
"MintedCrowdsale: minting failed"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
@ -21,8 +21,9 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
||||
* @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale
|
||||
*/
|
||||
constructor (uint256 initialRate, uint256 finalRate) public {
|
||||
require(finalRate > 0);
|
||||
require(initialRate > finalRate);
|
||||
require(finalRate > 0, "IncreasingPriceCrowdsale: final rate is 0");
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(initialRate > finalRate, "IncreasingPriceCrowdsale: initial rate is not greater than final rate");
|
||||
_initialRate = initialRate;
|
||||
_finalRate = finalRate;
|
||||
}
|
||||
@ -32,7 +33,7 @@ contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
||||
* all calls to it are a mistake.
|
||||
*/
|
||||
function rate() public view returns (uint256) {
|
||||
revert();
|
||||
revert("IncreasingPriceCrowdsale: rate() called");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
@ -17,7 +17,7 @@ contract CappedCrowdsale is Crowdsale {
|
||||
* @param cap Max amount of wei to be contributed
|
||||
*/
|
||||
constructor (uint256 cap) public {
|
||||
require(cap > 0);
|
||||
require(cap > 0, "CappedCrowdsale: cap is 0");
|
||||
_cap = cap;
|
||||
}
|
||||
|
||||
@ -43,6 +43,6 @@ contract CappedCrowdsale is Crowdsale {
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
require(weiRaised().add(weiAmount) <= _cap);
|
||||
require(weiRaised().add(weiAmount) <= _cap, "CappedCrowdsale: cap exceeded");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
@ -48,11 +48,12 @@ contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole {
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
require(_contributions[beneficiary].add(weiAmount) <= _caps[beneficiary]);
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(_contributions[beneficiary].add(weiAmount) <= _caps[beneficiary], "IndividuallyCappedCrowdsale: beneficiary's cap exceeded");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior to update beneficiary contributions
|
||||
* @dev Extend parent behavior to update beneficiary contributions.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../lifecycle/Pausable.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
@ -24,7 +24,7 @@ contract TimedCrowdsale is Crowdsale {
|
||||
* @dev Reverts if not in crowdsale time range.
|
||||
*/
|
||||
modifier onlyWhileOpen {
|
||||
require(isOpen());
|
||||
require(isOpen(), "TimedCrowdsale: not open");
|
||||
_;
|
||||
}
|
||||
|
||||
@ -35,8 +35,9 @@ contract TimedCrowdsale is Crowdsale {
|
||||
*/
|
||||
constructor (uint256 openingTime, uint256 closingTime) public {
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
require(openingTime >= block.timestamp);
|
||||
require(closingTime > openingTime);
|
||||
require(openingTime >= block.timestamp, "TimedCrowdsale: opening time is before current time");
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(closingTime > openingTime, "TimedCrowdsale: opening time is not before closing time");
|
||||
|
||||
_openingTime = openingTime;
|
||||
_closingTime = closingTime;
|
||||
@ -74,7 +75,7 @@ contract TimedCrowdsale is Crowdsale {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring to be within contributing period
|
||||
* @dev Extend parent behavior requiring to be within contributing period.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
@ -83,12 +84,13 @@ contract TimedCrowdsale is Crowdsale {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend crowdsale
|
||||
* @dev Extend crowdsale.
|
||||
* @param newClosingTime Crowdsale closing time
|
||||
*/
|
||||
function _extendTime(uint256 newClosingTime) internal {
|
||||
require(!hasClosed());
|
||||
require(newClosingTime > _closingTime);
|
||||
require(!hasClosed(), "TimedCrowdsale: already closed");
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(newClosingTime > _closingTime, "TimedCrowdsale: new closing time is before current closing time");
|
||||
|
||||
emit TimedCrowdsaleExtended(_closingTime, newClosingTime);
|
||||
_closingTime = newClosingTime;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
import "../Crowdsale.sol";
|
||||
import "../../access/roles/WhitelistedRole.sol";
|
||||
|
||||
@ -15,7 +15,7 @@ contract WhitelistCrowdsale is WhitelistedRole, Crowdsale {
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal view {
|
||||
require(isWhitelisted(_beneficiary));
|
||||
require(isWhitelisted(_beneficiary), "WhitelistCrowdsale: beneficiary doesn't have the Whitelisted role");
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title Elliptic curve signature operations
|
||||
@ -9,7 +9,7 @@ pragma solidity ^0.5.2;
|
||||
|
||||
library ECDSA {
|
||||
/**
|
||||
* @dev Recover signer address from a message by using their signature
|
||||
* @dev Recover signer address from a message by using their signature.
|
||||
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
|
||||
* @param signature bytes signature, the signature is generated using web3.eth.sign()
|
||||
*/
|
||||
@ -56,8 +56,8 @@ library ECDSA {
|
||||
|
||||
/**
|
||||
* toEthSignedMessageHash
|
||||
* @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
|
||||
* and hash the result
|
||||
* @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,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title MerkleProof
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
@ -6,7 +6,7 @@ import "../math/SafeMath.sol";
|
||||
* @title Counters
|
||||
* @author Matt Condon (@shrugs)
|
||||
* @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
|
||||
* of elements in a mapping, issuing ERC721 ids, or counting request ids
|
||||
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
|
||||
*
|
||||
* Include with `using Counters for Counters.Counter;`
|
||||
* Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the SafeMath
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../../token/ERC20/IERC20.sol";
|
||||
|
||||
|
||||
24
contracts/drafts/ERC1820Implementer.sol
Normal file
24
contracts/drafts/ERC1820Implementer.sol
Normal file
@ -0,0 +1,24 @@
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "./IERC1820Implementer.sol";
|
||||
|
||||
/**
|
||||
* @dev ERC1820Implementer allows your contract to implement an interface for another account in the sense of ERC1820.
|
||||
* That account or one of its ERC1820 managers can register the implementer in the ERC1820 registry, but the registry
|
||||
* will first check with the implementer if it agrees to it, and only allow it if it does. Using the internal
|
||||
* function _registerInterfaceForAddress provided by this contract, you are expressing this agreement,
|
||||
* and you will be able to register the contract as an implementer in the registry for that account.
|
||||
*/
|
||||
contract ERC1820Implementer is IERC1820Implementer {
|
||||
bytes32 constant private ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"));
|
||||
|
||||
mapping(bytes32 => mapping(address => bool)) private _supportedInterfaces;
|
||||
|
||||
function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32) {
|
||||
return _supportedInterfaces[interfaceHash][account] ? ERC1820_ACCEPT_MAGIC : bytes32(0x00);
|
||||
}
|
||||
|
||||
function _registerInterfaceForAddress(bytes32 interfaceHash, address account) internal {
|
||||
_supportedInterfaces[interfaceHash][account] = true;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../token/ERC20/ERC20Mintable.sol";
|
||||
@ -44,7 +44,7 @@ contract ERC20Migrator {
|
||||
* @param legacyToken address of the old token contract
|
||||
*/
|
||||
constructor (IERC20 legacyToken) public {
|
||||
require(address(legacyToken) != address(0));
|
||||
require(address(legacyToken) != address(0), "ERC20Migrator: legacy token is the zero address");
|
||||
_legacyToken = legacyToken;
|
||||
}
|
||||
|
||||
@ -68,9 +68,10 @@ contract ERC20Migrator {
|
||||
* @param newToken_ the token that will be minted
|
||||
*/
|
||||
function beginMigration(ERC20Mintable newToken_) public {
|
||||
require(address(_newToken) == address(0));
|
||||
require(address(newToken_) != address(0));
|
||||
require(newToken_.isMinter(address(this)));
|
||||
require(address(_newToken) == address(0), "ERC20Migrator: migration already started");
|
||||
require(address(newToken_) != address(0), "ERC20Migrator: new token is the zero address");
|
||||
//solhint-disable-next-line max-line-length
|
||||
require(newToken_.isMinter(address(this)), "ERC20Migrator: not a minter for new token");
|
||||
|
||||
_newToken = newToken_;
|
||||
}
|
||||
@ -82,7 +83,7 @@ contract ERC20Migrator {
|
||||
* @param amount amount of tokens to be migrated
|
||||
*/
|
||||
function migrate(address account, uint256 amount) public {
|
||||
require(address(_newToken) != address(0));
|
||||
require(address(_newToken) != address(0), "ERC20Migrator: migration not started");
|
||||
_legacyToken.safeTransferFrom(account, address(this), amount);
|
||||
_newToken.mint(account, amount);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
import "../utils/Arrays.sol";
|
||||
@ -31,7 +31,7 @@ contract ERC20Snapshot is ERC20 {
|
||||
}
|
||||
|
||||
mapping (address => Snapshots) private _accountBalanceSnapshots;
|
||||
Snapshots private _totalSupplySnaphots;
|
||||
Snapshots private _totalSupplySnapshots;
|
||||
|
||||
// Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid.
|
||||
Counters.Counter private _currentSnapshotId;
|
||||
@ -56,7 +56,7 @@ contract ERC20Snapshot is ERC20 {
|
||||
}
|
||||
|
||||
function totalSupplyAt(uint256 snapshotId) public view returns(uint256) {
|
||||
(bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnaphots);
|
||||
(bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots);
|
||||
|
||||
return snapshotted ? value : totalSupply();
|
||||
}
|
||||
@ -101,8 +101,9 @@ contract ERC20Snapshot is ERC20 {
|
||||
function _valueAt(uint256 snapshotId, Snapshots storage snapshots)
|
||||
private view returns (bool, uint256)
|
||||
{
|
||||
require(snapshotId > 0);
|
||||
require(snapshotId <= _currentSnapshotId.current());
|
||||
require(snapshotId > 0, "ERC20Snapshot: id is 0");
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(snapshotId <= _currentSnapshotId.current(), "ERC20Snapshot: nonexistent id");
|
||||
|
||||
uint256 index = snapshots.ids.findUpperBound(snapshotId);
|
||||
|
||||
@ -118,7 +119,7 @@ contract ERC20Snapshot is ERC20 {
|
||||
}
|
||||
|
||||
function _updateTotalSupplySnapshot() private {
|
||||
_updateSnapshot(_totalSupplySnaphots, totalSupply());
|
||||
_updateSnapshot(_totalSupplySnapshots, totalSupply());
|
||||
}
|
||||
|
||||
function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private {
|
||||
|
||||
357
contracts/drafts/ERC777/ERC777.sol
Normal file
357
contracts/drafts/ERC777/ERC777.sol
Normal file
@ -0,0 +1,357 @@
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "./IERC777.sol";
|
||||
import "./IERC777Recipient.sol";
|
||||
import "./IERC777Sender.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../../utils/Address.sol";
|
||||
import "../IERC1820Registry.sol";
|
||||
|
||||
/**
|
||||
* @title ERC777 token implementation
|
||||
* @author etsvigun <utgarda@gmail.com>, Bertrand Masius <github@catageeks.tk>
|
||||
*/
|
||||
contract ERC777 is IERC777 {
|
||||
using SafeMath for uint256;
|
||||
using Address for address;
|
||||
|
||||
IERC1820Registry private _erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
|
||||
|
||||
string private _name;
|
||||
|
||||
string private _symbol;
|
||||
|
||||
mapping(address => uint256) private _balances;
|
||||
|
||||
uint256 private _totalSupply;
|
||||
|
||||
uint256 private _granularity;
|
||||
|
||||
bytes32 constant private TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
|
||||
bytes32 constant private TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");
|
||||
|
||||
// This isn't ever read from - it's only used to respond to the defaultOperators query.
|
||||
address[] private _defaultOperatorsArray;
|
||||
|
||||
// Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
|
||||
mapping(address => bool) private _defaultOperators;
|
||||
|
||||
// For each account, a mapping of its operators and revoked default operators.
|
||||
mapping(address => mapping(address => bool)) private _operators;
|
||||
mapping(address => mapping(address => bool)) private _revokedDefaultOperators;
|
||||
|
||||
constructor(
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
uint256 granularity,
|
||||
address[] memory defaultOperators
|
||||
) public {
|
||||
require(granularity > 0);
|
||||
|
||||
_name = name;
|
||||
_symbol = symbol;
|
||||
_granularity = granularity;
|
||||
|
||||
_defaultOperatorsArray = defaultOperators;
|
||||
for (uint256 i = 0; i < _defaultOperatorsArray.length; i++) {
|
||||
_defaultOperators[_defaultOperatorsArray[i]] = true;
|
||||
}
|
||||
|
||||
// register interface
|
||||
_erc1820.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Send the amount of tokens from the address msg.sender to the address to
|
||||
* @param to address recipient address
|
||||
* @param amount uint256 amount of tokens to transfer
|
||||
* @param data bytes information attached to the send, and intended for the recipient (to)
|
||||
*/
|
||||
function send(address to, uint256 amount, bytes calldata data) external {
|
||||
_send(msg.sender, msg.sender, to, amount, data, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Send the amount of tokens on behalf of the address from to the address to
|
||||
* @param from address token holder address.
|
||||
* @param to address recipient address
|
||||
* @param amount uint256 amount of tokens to transfer
|
||||
* @param data bytes information attached to the send, and intended for the recipient (to)
|
||||
* @param operatorData bytes extra information provided by the operator (if any)
|
||||
*/
|
||||
function operatorSend(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata data,
|
||||
bytes calldata operatorData
|
||||
)
|
||||
external
|
||||
{
|
||||
require(isOperatorFor(msg.sender, from));
|
||||
_send(msg.sender, from, to, amount, data, operatorData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Burn the amount of tokens from the address msg.sender
|
||||
* @param amount uint256 amount of tokens to transfer
|
||||
* @param data bytes extra information provided by the token holder
|
||||
*/
|
||||
function burn(uint256 amount, bytes calldata data) external {
|
||||
_burn(msg.sender, msg.sender, amount, data, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Burn the amount of tokens on behalf of the address from
|
||||
* @param from address token holder address.
|
||||
* @param amount uint256 amount of tokens to transfer
|
||||
* @param data bytes extra information provided by the token holder
|
||||
* @param operatorData bytes extra information provided by the operator (if any)
|
||||
*/
|
||||
function operatorBurn(address from, uint256 amount, bytes calldata data, bytes calldata operatorData) external {
|
||||
require(isOperatorFor(msg.sender, from));
|
||||
_burn(msg.sender, from, amount, data, operatorData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Authorize an operator for the sender
|
||||
* @param operator address to be authorized as operator
|
||||
*/
|
||||
function authorizeOperator(address operator) external {
|
||||
require(msg.sender != operator);
|
||||
|
||||
if (_defaultOperators[operator]) {
|
||||
delete _revokedDefaultOperators[msg.sender][operator];
|
||||
} else {
|
||||
_operators[msg.sender][operator] = true;
|
||||
}
|
||||
|
||||
emit AuthorizedOperator(operator, msg.sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Revoke operator rights from one of the default operators
|
||||
* @param operator address to revoke operator rights from
|
||||
*/
|
||||
function revokeOperator(address operator) external {
|
||||
require(operator != msg.sender);
|
||||
|
||||
if (_defaultOperators[operator]) {
|
||||
_revokedDefaultOperators[msg.sender][operator] = true;
|
||||
} else {
|
||||
delete _operators[msg.sender][operator];
|
||||
}
|
||||
|
||||
emit RevokedOperator(operator, msg.sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the token.
|
||||
*/
|
||||
function name() public view returns (string memory) {
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the symbol of the token.
|
||||
*/
|
||||
function symbol() public view returns (string memory) {
|
||||
return _symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Total number of tokens in existence
|
||||
*/
|
||||
function totalSupply() public view returns (uint256) {
|
||||
return _totalSupply;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets the balance of the specified address.
|
||||
* @param tokenHolder The address to query the balance of.
|
||||
* @return uint256 representing the amount owned by the specified address.
|
||||
*/
|
||||
function balanceOf(address tokenHolder) public view returns (uint256) {
|
||||
return _balances[tokenHolder];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets the token's granularity,
|
||||
* i.e. the smallest number of tokens (in the basic unit)
|
||||
* which may be minted, sent or burned at any time
|
||||
* @return uint256 granularity
|
||||
*/
|
||||
function granularity() public view returns (uint256) {
|
||||
return _granularity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the list of default operators as defined by the token contract.
|
||||
* @return address[] default operators
|
||||
*/
|
||||
function defaultOperators() public view returns (address[] memory) {
|
||||
return _defaultOperatorsArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Indicate whether an address
|
||||
* is an operator of the tokenHolder address
|
||||
* @param operator address which may be an operator of tokenHolder
|
||||
* @param tokenHolder address of a token holder which may have the operator
|
||||
* address as an operator.
|
||||
*/
|
||||
function isOperatorFor(
|
||||
address operator,
|
||||
address tokenHolder
|
||||
) public view returns (bool) {
|
||||
return operator == tokenHolder ||
|
||||
(_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
|
||||
_operators[tokenHolder][operator];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Mint tokens. Does not check authorization of operator
|
||||
* @dev the caller may ckeck that operator is authorized before calling
|
||||
* @param operator address operator requesting the operation
|
||||
* @param to address token recipient address
|
||||
* @param amount uint256 amount of tokens to mint
|
||||
* @param userData bytes extra information defined by the token recipient (if any)
|
||||
* @param operatorData bytes extra information provided by the operator (if any)
|
||||
*/
|
||||
function _mint(
|
||||
address operator,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes memory userData,
|
||||
bytes memory operatorData
|
||||
)
|
||||
internal
|
||||
{
|
||||
require(to != address(0));
|
||||
require((amount % _granularity) == 0);
|
||||
|
||||
// Update state variables
|
||||
_totalSupply = _totalSupply.add(amount);
|
||||
_balances[to] = _balances[to].add(amount);
|
||||
|
||||
_callTokensReceived(operator, address(0), to, amount, userData, operatorData);
|
||||
|
||||
emit Minted(operator, to, amount, userData, operatorData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Send tokens
|
||||
* @param operator address operator requesting the transfer
|
||||
* @param from address token holder address
|
||||
* @param to address recipient address
|
||||
* @param amount uint256 amount of tokens to transfer
|
||||
* @param userData bytes extra information provided by the token holder (if any)
|
||||
* @param operatorData bytes extra information provided by the operator (if any)
|
||||
*/
|
||||
function _send(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes memory userData,
|
||||
bytes memory operatorData
|
||||
)
|
||||
private
|
||||
{
|
||||
require(from != address(0));
|
||||
require(to != address(0));
|
||||
require((amount % _granularity) == 0);
|
||||
|
||||
_callTokensToSend(operator, from, to, amount, userData, operatorData);
|
||||
|
||||
// Update state variables
|
||||
_balances[from] = _balances[from].sub(amount);
|
||||
_balances[to] = _balances[to].add(amount);
|
||||
|
||||
_callTokensReceived(operator, from, to, amount, userData, operatorData);
|
||||
|
||||
emit Sent(operator, from, to, amount, userData, operatorData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Burn tokens
|
||||
* @param operator address operator requesting the operation
|
||||
* @param from address token holder address
|
||||
* @param amount uint256 amount of tokens to burn
|
||||
* @param data bytes extra information provided by the token holder
|
||||
* @param operatorData bytes extra information provided by the operator (if any)
|
||||
*/
|
||||
function _burn(
|
||||
address operator,
|
||||
address from,
|
||||
uint256 amount,
|
||||
bytes memory data,
|
||||
bytes memory operatorData
|
||||
)
|
||||
private
|
||||
{
|
||||
require(from != address(0));
|
||||
require((amount % _granularity) == 0);
|
||||
|
||||
_callTokensToSend(operator, from, address(0), amount, data, operatorData);
|
||||
|
||||
// Update state variables
|
||||
_totalSupply = _totalSupply.sub(amount);
|
||||
_balances[from] = _balances[from].sub(amount);
|
||||
|
||||
emit Burned(operator, from, amount, data, operatorData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Call from.tokensToSend() if the interface is registered
|
||||
* @param operator address operator requesting the transfer
|
||||
* @param from address token holder address
|
||||
* @param to address recipient address
|
||||
* @param amount uint256 amount of tokens to transfer
|
||||
* @param userData bytes extra information provided by the token holder (if any)
|
||||
* @param operatorData bytes extra information provided by the operator (if any)
|
||||
*/
|
||||
function _callTokensToSend(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes memory userData,
|
||||
bytes memory operatorData
|
||||
)
|
||||
private
|
||||
{
|
||||
address implementer = _erc1820.getInterfaceImplementer(from, TOKENS_SENDER_INTERFACE_HASH);
|
||||
if (implementer != address(0)) {
|
||||
IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but
|
||||
* tokensReceived() was not registered for the recipient
|
||||
* @param operator address operator requesting the transfer
|
||||
* @param from address token holder address
|
||||
* @param to address recipient address
|
||||
* @param amount uint256 amount of tokens to transfer
|
||||
* @param userData bytes extra information provided by the token holder (if any)
|
||||
* @param operatorData bytes extra information provided by the operator (if any)
|
||||
*/
|
||||
function _callTokensReceived(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes memory userData,
|
||||
bytes memory operatorData
|
||||
)
|
||||
private
|
||||
{
|
||||
address implementer = _erc1820.getInterfaceImplementer(to, TOKENS_RECIPIENT_INTERFACE_HASH);
|
||||
if (implementer != address(0)) {
|
||||
IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
|
||||
} else {
|
||||
require(!to.isContract());
|
||||
}
|
||||
}
|
||||
}
|
||||
61
contracts/drafts/ERC777/IERC777.sol
Normal file
61
contracts/drafts/ERC777/IERC777.sol
Normal file
@ -0,0 +1,61 @@
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title ERC777 token interface
|
||||
* @dev See https://eips.ethereum.org/EIPS/eip-777
|
||||
*/
|
||||
interface IERC777 {
|
||||
function authorizeOperator(address operator) external;
|
||||
|
||||
function revokeOperator(address operator) external;
|
||||
|
||||
function send(address to, uint256 amount, bytes calldata data) external;
|
||||
|
||||
function operatorSend(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes calldata data,
|
||||
bytes calldata operatorData
|
||||
) external;
|
||||
|
||||
function burn(uint256 amount, bytes calldata data) external;
|
||||
|
||||
function operatorBurn(
|
||||
address from,
|
||||
uint256 amount,
|
||||
bytes calldata data,
|
||||
bytes calldata operatorData
|
||||
) external;
|
||||
|
||||
function name() external view returns (string memory);
|
||||
|
||||
function symbol() external view returns (string memory);
|
||||
|
||||
function totalSupply() external view returns (uint256);
|
||||
|
||||
function balanceOf(address owner) external view returns (uint256);
|
||||
|
||||
function granularity() external view returns (uint256);
|
||||
|
||||
function defaultOperators() external view returns (address[] memory);
|
||||
|
||||
function isOperatorFor(address operator, address tokenHolder) external view returns (bool);
|
||||
|
||||
event Sent(
|
||||
address indexed operator,
|
||||
address indexed from,
|
||||
address indexed to,
|
||||
uint256 amount,
|
||||
bytes data,
|
||||
bytes operatorData
|
||||
);
|
||||
|
||||
event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
|
||||
|
||||
event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
|
||||
|
||||
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
|
||||
|
||||
event RevokedOperator(address indexed operator, address indexed tokenHolder);
|
||||
}
|
||||
16
contracts/drafts/ERC777/IERC777Recipient.sol
Normal file
16
contracts/drafts/ERC777/IERC777Recipient.sol
Normal file
@ -0,0 +1,16 @@
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title ERC777 token recipient interface
|
||||
* @dev See https://eips.ethereum.org/EIPS/eip-777
|
||||
*/
|
||||
interface IERC777Recipient {
|
||||
function tokensReceived(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint amount,
|
||||
bytes calldata userData,
|
||||
bytes calldata operatorData
|
||||
) external;
|
||||
}
|
||||
16
contracts/drafts/ERC777/IERC777Sender.sol
Normal file
16
contracts/drafts/ERC777/IERC777Sender.sol
Normal file
@ -0,0 +1,16 @@
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title ERC777 token sender interface
|
||||
* @dev See https://eips.ethereum.org/EIPS/eip-777
|
||||
*/
|
||||
interface IERC777Sender {
|
||||
function tokensToSend(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint amount,
|
||||
bytes calldata userData,
|
||||
bytes calldata operatorData
|
||||
) external;
|
||||
}
|
||||
17
contracts/drafts/IERC1820Implementer.sol
Normal file
17
contracts/drafts/IERC1820Implementer.sol
Normal file
@ -0,0 +1,17 @@
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title IERC1820Implementer
|
||||
* Interface for contracts that will be registered as implementers in the ERC1820 registry.
|
||||
* @notice For more details, see https://eips.ethereum.org/EIPS/eip-1820
|
||||
*/
|
||||
interface IERC1820Implementer {
|
||||
/**
|
||||
* @notice Indicates whether the contract implements the interface `interfaceHash` for the address `account` or
|
||||
* not.
|
||||
* @param interfaceHash keccak256 hash of the name of the interface
|
||||
* @param account Address for which the contract will implement the interface
|
||||
* @return ERC1820_ACCEPT_MAGIC only if the contract implements `interfaceHash` for the address `account`.
|
||||
*/
|
||||
function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32);
|
||||
}
|
||||
90
contracts/drafts/IERC1820Registry.sol
Normal file
90
contracts/drafts/IERC1820Registry.sol
Normal file
@ -0,0 +1,90 @@
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title ERC1820 Pseudo-introspection Registry Contract
|
||||
* @author Jordi Baylina and Jacques Dafflon
|
||||
* @notice For more details, see https://eips.ethereum.org/EIPS/eip-1820
|
||||
*/
|
||||
interface IERC1820Registry {
|
||||
/**
|
||||
* @notice Sets the contract which implements a specific interface for an address.
|
||||
* Only the manager defined for that address can set it.
|
||||
* (Each address is the manager for itself until it sets a new manager.)
|
||||
* @param account Address for which to set the interface.
|
||||
* (If 'account' is the zero address then 'msg.sender' is assumed.)
|
||||
* @param interfaceHash Keccak256 hash of the name of the interface as a string.
|
||||
* E.g., 'web3.utils.keccak256("ERC777TokensRecipient")' for the 'ERC777TokensRecipient' interface.
|
||||
* @param implementer Contract address implementing `interfaceHash` for `account.address()`.
|
||||
*/
|
||||
function setInterfaceImplementer(address account, bytes32 interfaceHash, address implementer) external;
|
||||
|
||||
/**
|
||||
* @notice Sets `newManager.address()` as manager for `account.address()`.
|
||||
* The new manager will be able to call 'setInterfaceImplementer' for `account.address()`.
|
||||
* @param account Address for which to set the new manager.
|
||||
* @param newManager Address of the new manager for `addr.address()`.
|
||||
* (Pass '0x0' to reset the manager to `account.address()`.)
|
||||
*/
|
||||
function setManager(address account, address newManager) external;
|
||||
|
||||
/**
|
||||
* @notice Updates the cache with whether the contract implements an ERC165 interface or not.
|
||||
* @param account Address of the contract for which to update the cache.
|
||||
* @param interfaceId ERC165 interface for which to update the cache.
|
||||
*/
|
||||
function updateERC165Cache(address account, bytes4 interfaceId) external;
|
||||
|
||||
/**
|
||||
* @notice Get the manager of an address.
|
||||
* @param account Address for which to return the manager.
|
||||
* @return Address of the manager for a given address.
|
||||
*/
|
||||
function getManager(address account) external view returns (address);
|
||||
|
||||
/**
|
||||
* @notice Query if an address implements an interface and through which contract.
|
||||
* @param account Address being queried for the implementer of an interface.
|
||||
* (If 'account' is the zero address then 'msg.sender' is assumed.)
|
||||
* @param interfaceHash Keccak256 hash of the name of the interface as a string.
|
||||
* E.g., 'web3.utils.keccak256("ERC777TokensRecipient")' for the 'ERC777TokensRecipient' interface.
|
||||
* @return The address of the contract which implements the interface `interfaceHash` for `account.address()`
|
||||
* or '0' if `account.address()` did not register an implementer for this interface.
|
||||
*/
|
||||
function getInterfaceImplementer(address account, bytes32 interfaceHash) external view returns (address);
|
||||
|
||||
/**
|
||||
* @notice Checks whether a contract implements an ERC165 interface or not.
|
||||
* If the result is not cached a direct lookup on the contract address is performed.
|
||||
* If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
|
||||
* 'updateERC165Cache' with the contract address.
|
||||
* @param account Address of the contract to check.
|
||||
* @param interfaceId ERC165 interface to check.
|
||||
* @return True if `account.address()` implements `interfaceId`, false otherwise.
|
||||
*/
|
||||
function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);
|
||||
|
||||
/**
|
||||
* @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
|
||||
* @param account Address of the contract to check.
|
||||
* @param interfaceId ERC165 interface to check.
|
||||
* @return True if `account.address()` implements `interfaceId`, false otherwise.
|
||||
*/
|
||||
function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);
|
||||
|
||||
/**
|
||||
* @notice Compute the keccak256 hash of an interface given its name.
|
||||
* @param interfaceName Name of the interface.
|
||||
* @return The keccak256 hash of an interface name.
|
||||
*/
|
||||
function interfaceHash(string calldata interfaceName) external pure returns (bytes32);
|
||||
|
||||
/**
|
||||
* @notice Indicates a contract is the `implementer` of `interfaceHash` for `account`.
|
||||
*/
|
||||
event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);
|
||||
|
||||
/**
|
||||
* @notice Indicates `newManager` is the address of the new manager for `account`.
|
||||
*/
|
||||
event ManagerChanged(address indexed account, address indexed newManager);
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../access/roles/SignerRole.sol";
|
||||
import "../cryptography/ECDSA.sol";
|
||||
@ -48,26 +48,28 @@ contract SignatureBouncer is SignerRole {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature of a signer was provided
|
||||
* @dev Requires that a valid signature of a signer was provided.
|
||||
*/
|
||||
modifier onlyValidSignature(bytes memory signature) {
|
||||
require(_isValidSignature(msg.sender, signature));
|
||||
require(_isValidSignature(msg.sender, signature), "SignatureBouncer: invalid signature for caller");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature with a specified method of a signer was provided
|
||||
* @dev Requires that a valid signature with a specified method of a signer was provided.
|
||||
*/
|
||||
modifier onlyValidSignatureAndMethod(bytes memory signature) {
|
||||
require(_isValidSignatureAndMethod(msg.sender, signature));
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(_isValidSignatureAndMethod(msg.sender, signature), "SignatureBouncer: invalid signature for caller and method");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature with a specified method and params of a signer was provided
|
||||
* @dev Requires that a valid signature with a specified method and params of a signer was provided.
|
||||
*/
|
||||
modifier onlyValidSignatureAndData(bytes memory signature) {
|
||||
require(_isValidSignatureAndData(msg.sender, signature));
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(_isValidSignatureAndData(msg.sender, signature), "SignatureBouncer: invalid signature for caller and data");
|
||||
_;
|
||||
}
|
||||
|
||||
@ -97,7 +99,7 @@ contract SignatureBouncer is SignerRole {
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) {
|
||||
require(msg.data.length > _SIGNATURE_SIZE);
|
||||
require(msg.data.length > _SIGNATURE_SIZE, "SignatureBouncer: data is too short");
|
||||
|
||||
bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE);
|
||||
for (uint i = 0; i < data.length; i++) {
|
||||
@ -108,8 +110,8 @@ contract SignatureBouncer is SignerRole {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev internal function to convert a hash to an eth signed message
|
||||
* and then recover the signature and check it against the signer role
|
||||
* @dev Internal function to convert a hash to an eth signed message
|
||||
* and then recover the signature and check it against the signer role.
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidDataHash(bytes32 hash, bytes memory signature) internal view returns (bool) {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title SignedSafeMath
|
||||
* @dev Signed math operations with safety checks that revert on error
|
||||
* @dev Signed math operations with safety checks that revert on error.
|
||||
*/
|
||||
library SignedSafeMath {
|
||||
int256 constant private INT256_MIN = -2**255;
|
||||
@ -18,10 +18,10 @@ library SignedSafeMath {
|
||||
return 0;
|
||||
}
|
||||
|
||||
require(!(a == -1 && b == INT256_MIN)); // This is the only case of overflow not detected by the check below
|
||||
require(!(a == -1 && b == INT256_MIN), "SignedSafeMath: multiplication overflow");
|
||||
|
||||
int256 c = a * b;
|
||||
require(c / a == b);
|
||||
require(c / a == b, "SignedSafeMath: multiplication overflow");
|
||||
|
||||
return c;
|
||||
}
|
||||
@ -30,8 +30,8 @@ library SignedSafeMath {
|
||||
* @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
|
||||
*/
|
||||
function div(int256 a, int256 b) internal pure returns (int256) {
|
||||
require(b != 0); // Solidity only automatically asserts when dividing by 0
|
||||
require(!(b == -1 && a == INT256_MIN)); // This is the only case of overflow
|
||||
require(b != 0, "SignedSafeMath: division by zero");
|
||||
require(!(b == -1 && a == INT256_MIN), "SignedSafeMath: division overflow");
|
||||
|
||||
int256 c = a / b;
|
||||
|
||||
@ -43,7 +43,7 @@ library SignedSafeMath {
|
||||
*/
|
||||
function sub(int256 a, int256 b) internal pure returns (int256) {
|
||||
int256 c = a - b;
|
||||
require((b >= 0 && c <= a) || (b < 0 && c > a));
|
||||
require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");
|
||||
|
||||
return c;
|
||||
}
|
||||
@ -53,7 +53,7 @@ library SignedSafeMath {
|
||||
*/
|
||||
function add(int256 a, int256 b) internal pure returns (int256) {
|
||||
int256 c = a + b;
|
||||
require((b >= 0 && c >= a) || (b < 0 && c < a));
|
||||
require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
import "../ownership/Ownable.sol";
|
||||
@ -47,10 +47,12 @@ contract TokenVesting is Ownable {
|
||||
* @param revocable whether the vesting is revocable or not
|
||||
*/
|
||||
constructor (address beneficiary, uint256 start, uint256 cliffDuration, uint256 duration, bool revocable) public {
|
||||
require(beneficiary != address(0));
|
||||
require(cliffDuration <= duration);
|
||||
require(duration > 0);
|
||||
require(start.add(duration) > block.timestamp);
|
||||
require(beneficiary != address(0), "TokenVesting: beneficiary is the zero address");
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(cliffDuration <= duration, "TokenVesting: cliff is longer than duration");
|
||||
require(duration > 0, "TokenVesting: duration is 0");
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(start.add(duration) > block.timestamp, "TokenVesting: final time is before current time");
|
||||
|
||||
_beneficiary = beneficiary;
|
||||
_revocable = revocable;
|
||||
@ -115,7 +117,7 @@ contract TokenVesting is Ownable {
|
||||
function release(IERC20 token) public {
|
||||
uint256 unreleased = _releasableAmount(token);
|
||||
|
||||
require(unreleased > 0);
|
||||
require(unreleased > 0, "TokenVesting: no tokens are due");
|
||||
|
||||
_released[address(token)] = _released[address(token)].add(unreleased);
|
||||
|
||||
@ -130,8 +132,8 @@ contract TokenVesting is Ownable {
|
||||
* @param token ERC20 token which is being vested
|
||||
*/
|
||||
function revoke(IERC20 token) public onlyOwner {
|
||||
require(_revocable);
|
||||
require(!_revoked[address(token)]);
|
||||
require(_revocable, "TokenVesting: cannot revoke");
|
||||
require(!_revoked[address(token)], "TokenVesting: token already revoked");
|
||||
|
||||
uint256 balance = token.balanceOf(address(this));
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||
@ -48,6 +48,6 @@ contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsal
|
||||
{
|
||||
//As goal needs to be met for a successful crowdsale
|
||||
//the value needs to less or equal than a cap which is limit for accepted funds
|
||||
require(goal <= cap);
|
||||
require(goal <= cap, "SampleCrowdSale: goal is greater than cap");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "./IERC165.sol";
|
||||
|
||||
@ -8,37 +8,36 @@ import "./IERC165.sol";
|
||||
* @dev Implements ERC165 using a lookup table.
|
||||
*/
|
||||
contract ERC165 is IERC165 {
|
||||
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
/*
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
|
||||
*/
|
||||
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
|
||||
/**
|
||||
* @dev a mapping of interface id to whether or not it's supported
|
||||
* @dev Mapping of interface ids to whether or not it's supported.
|
||||
*/
|
||||
mapping(bytes4 => bool) private _supportedInterfaces;
|
||||
|
||||
/**
|
||||
* @dev A contract implementing SupportsInterfaceWithLookup
|
||||
* implement ERC165 itself
|
||||
* implements ERC165 itself.
|
||||
*/
|
||||
constructor () internal {
|
||||
_registerInterface(_INTERFACE_ID_ERC165);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev implement supportsInterface(bytes4) using a lookup table
|
||||
* @dev Implement supportsInterface(bytes4) using a lookup table.
|
||||
*/
|
||||
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
|
||||
return _supportedInterfaces[interfaceId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev internal method for registering an interface
|
||||
* @dev Internal method for registering an interface.
|
||||
*/
|
||||
function _registerInterface(bytes4 interfaceId) internal {
|
||||
require(interfaceId != 0xffffffff);
|
||||
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
|
||||
_supportedInterfaces[interfaceId] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title ERC165Checker
|
||||
@ -9,11 +9,10 @@ library ERC165Checker {
|
||||
// As per the EIP-165 spec, no interface should ever match 0xffffffff
|
||||
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
|
||||
|
||||
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
/*
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
|
||||
*/
|
||||
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
|
||||
/**
|
||||
* @notice Query if a contract supports ERC165
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title IERC165
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../access/roles/PauserRole.sol";
|
||||
|
||||
@ -17,7 +17,7 @@ contract Pausable is PauserRole {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the contract is paused, false otherwise.
|
||||
* @return True if the contract is paused, false otherwise.
|
||||
*/
|
||||
function paused() public view returns (bool) {
|
||||
return _paused;
|
||||
@ -27,7 +27,7 @@ contract Pausable is PauserRole {
|
||||
* @dev Modifier to make a function callable only when the contract is not paused.
|
||||
*/
|
||||
modifier whenNotPaused() {
|
||||
require(!_paused);
|
||||
require(!_paused, "Pausable: paused");
|
||||
_;
|
||||
}
|
||||
|
||||
@ -35,12 +35,12 @@ contract Pausable is PauserRole {
|
||||
* @dev Modifier to make a function callable only when the contract is paused.
|
||||
*/
|
||||
modifier whenPaused() {
|
||||
require(_paused);
|
||||
require(_paused, "Pausable: not paused");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev called by the owner to pause, triggers stopped state
|
||||
* @dev Called by a pauser to pause, triggers stopped state.
|
||||
*/
|
||||
function pause() public onlyPauser whenNotPaused {
|
||||
_paused = true;
|
||||
@ -48,7 +48,7 @@ contract Pausable is PauserRole {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev called by the owner to unpause, returns to normal state
|
||||
* @dev Called by a pauser to unpause, returns to normal state.
|
||||
*/
|
||||
function unpause() public onlyPauser whenPaused {
|
||||
_paused = false;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title Math
|
||||
* @dev Assorted math operations
|
||||
* @dev Assorted math operations.
|
||||
*/
|
||||
library Math {
|
||||
/**
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
/**
|
||||
* @title SafeMath
|
||||
* @dev Unsigned math operations with safety checks that revert on error
|
||||
* @dev Unsigned math operations with safety checks that revert on error.
|
||||
*/
|
||||
library SafeMath {
|
||||
/**
|
||||
@ -17,7 +17,7 @@ library SafeMath {
|
||||
}
|
||||
|
||||
uint256 c = a * b;
|
||||
require(c / a == b);
|
||||
require(c / a == b, "SafeMath: multiplication overflow");
|
||||
|
||||
return c;
|
||||
}
|
||||
@ -27,7 +27,7 @@ library SafeMath {
|
||||
*/
|
||||
function div(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// Solidity only automatically asserts when dividing by 0
|
||||
require(b > 0);
|
||||
require(b > 0, "SafeMath: division by zero");
|
||||
uint256 c = a / b;
|
||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
||||
|
||||
@ -38,7 +38,7 @@ library SafeMath {
|
||||
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
|
||||
*/
|
||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b <= a);
|
||||
require(b <= a, "SafeMath: subtraction overflow");
|
||||
uint256 c = a - b;
|
||||
|
||||
return c;
|
||||
@ -49,7 +49,7 @@ library SafeMath {
|
||||
*/
|
||||
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
uint256 c = a + b;
|
||||
require(c >= a);
|
||||
require(c >= a, "SafeMath: addition overflow");
|
||||
|
||||
return c;
|
||||
}
|
||||
@ -59,7 +59,7 @@ library SafeMath {
|
||||
* reverts when dividing by zero.
|
||||
*/
|
||||
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b != 0);
|
||||
require(b != 0, "SafeMath: modulo by zero");
|
||||
return a % b;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
contract Acknowledger {
|
||||
event AcknowledgeFoo(uint256 a);
|
||||
event AcknowledgeBarSingle(uint256 a);
|
||||
event AcknowledgeBarDouble(uint256 a, uint256 b);
|
||||
|
||||
function foo(uint256 a) public {
|
||||
emit AcknowledgeFoo(a);
|
||||
}
|
||||
|
||||
function bar(uint256 a) public {
|
||||
emit AcknowledgeBarSingle(a);
|
||||
}
|
||||
|
||||
function bar(uint256 a, uint256 b) public {
|
||||
emit AcknowledgeBarDouble(a, b);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../utils/Address.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../crowdsale/emission/AllowanceCrowdsale.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../utils/Arrays.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../access/roles/CapperRole.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../payment/escrow/ConditionalEscrow.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../drafts/Counters.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../crowdsale/Crowdsale.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../cryptography/ECDSA.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../../introspection/IERC165.sol";
|
||||
|
||||
@ -13,37 +13,36 @@ import "../../introspection/IERC165.sol";
|
||||
* solidity-coverage ignores the /mocks folder, so we duplicate its implementation here to avoid instrumenting it
|
||||
*/
|
||||
contract SupportsInterfaceWithLookupMock is IERC165 {
|
||||
bytes4 public constant INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
/*
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
|
||||
*/
|
||||
bytes4 public constant INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
|
||||
/**
|
||||
* @dev a mapping of interface id to whether or not it's supported
|
||||
* @dev A mapping of interface id to whether or not it's supported.
|
||||
*/
|
||||
mapping(bytes4 => bool) private _supportedInterfaces;
|
||||
|
||||
/**
|
||||
* @dev A contract implementing SupportsInterfaceWithLookup
|
||||
* implement ERC165 itself
|
||||
* implement ERC165 itself.
|
||||
*/
|
||||
constructor () public {
|
||||
_registerInterface(INTERFACE_ID_ERC165);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev implement supportsInterface(bytes4) using a lookup table
|
||||
* @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
|
||||
* @dev Private method for registering an interface.
|
||||
*/
|
||||
function _registerInterface(bytes4 interfaceId) internal {
|
||||
require(interfaceId != 0xffffffff);
|
||||
require(interfaceId != 0xffffffff, "ERC165InterfacesSupported: invalid interface id");
|
||||
_supportedInterfaces[interfaceId] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
contract ERC165NotSupported {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../introspection/ERC165Checker.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../introspection/ERC165.sol";
|
||||
|
||||
|
||||
9
contracts/mocks/ERC1820ImplementerMock.sol
Normal file
9
contracts/mocks/ERC1820ImplementerMock.sol
Normal file
@ -0,0 +1,9 @@
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../drafts/ERC1820Implementer.sol";
|
||||
|
||||
contract ERC1820ImplementerMock is ERC1820Implementer {
|
||||
function registerInterfaceForAddress(bytes32 interfaceHash, address account) public {
|
||||
_registerInterfaceForAddress(interfaceHash, account);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/ERC20Burnable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../drafts/ERC1046/ERC20Metadata.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/ERC20Mintable.sol";
|
||||
import "./MinterRoleMock.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/ERC20Pausable.sol";
|
||||
import "./PauserRoleMock.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../drafts/ERC20Snapshot.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC721/ERC721Full.sol";
|
||||
import "../token/ERC721/ERC721Mintable.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC721/ERC721Full.sol";
|
||||
import "../token/ERC721/ERC721Mintable.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC721/ERC721.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC721/ERC721Pausable.sol";
|
||||
import "./PauserRoleMock.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC721/IERC721Receiver.sol";
|
||||
|
||||
@ -16,7 +16,7 @@ contract ERC721ReceiverMock is IERC721Receiver {
|
||||
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
|
||||
public returns (bytes4)
|
||||
{
|
||||
require(!_reverts);
|
||||
require(!_reverts, "ERC721ReceiverMock: reverting");
|
||||
emit Received(operator, from, tokenId, data, gasleft());
|
||||
return _retval;
|
||||
}
|
||||
|
||||
26
contracts/mocks/ERC777Mock.sol
Normal file
26
contracts/mocks/ERC777Mock.sol
Normal file
@ -0,0 +1,26 @@
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../drafts/ERC777/ERC777.sol";
|
||||
|
||||
contract ERC777Mock is ERC777 {
|
||||
constructor(
|
||||
address initialHolder,
|
||||
uint256 initialBalance,
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
uint256 granularity,
|
||||
address[] memory defaultOperators
|
||||
) public ERC777(name, symbol, granularity, defaultOperators) {
|
||||
_mint(msg.sender, initialHolder, initialBalance, "", "");
|
||||
}
|
||||
|
||||
function mintInternal (
|
||||
address operator,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes memory userData,
|
||||
bytes memory operatorData
|
||||
) public {
|
||||
_mint(operator, to, amount, userData, operatorData);
|
||||
}
|
||||
}
|
||||
147
contracts/mocks/ERC777SenderRecipientMock.sol
Normal file
147
contracts/mocks/ERC777SenderRecipientMock.sol
Normal file
@ -0,0 +1,147 @@
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../drafts/ERC777/IERC777.sol";
|
||||
import "../drafts/ERC777/IERC777Sender.sol";
|
||||
import "../drafts/ERC777/IERC777Recipient.sol";
|
||||
import "../drafts/IERC1820Registry.sol";
|
||||
import "../drafts/ERC1820Implementer.sol";
|
||||
|
||||
contract ERC777SenderRecipientMock is IERC777Sender, IERC777Recipient, ERC1820Implementer {
|
||||
event TokensToSendCalled(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes data,
|
||||
bytes operatorData,
|
||||
address token,
|
||||
uint256 fromBalance,
|
||||
uint256 toBalance
|
||||
);
|
||||
|
||||
event TokensReceivedCalled(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes data,
|
||||
bytes operatorData,
|
||||
address token,
|
||||
uint256 fromBalance,
|
||||
uint256 toBalance
|
||||
);
|
||||
|
||||
bool private _shouldRevertSend;
|
||||
bool private _shouldRevertReceive;
|
||||
|
||||
IERC1820Registry private _erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
|
||||
|
||||
bytes32 constant private TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
|
||||
bytes32 constant private TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");
|
||||
|
||||
function tokensToSend(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint amount,
|
||||
bytes calldata userData,
|
||||
bytes calldata operatorData
|
||||
) external {
|
||||
if (_shouldRevertSend) {
|
||||
revert();
|
||||
}
|
||||
|
||||
IERC777 token = IERC777(msg.sender);
|
||||
|
||||
uint256 fromBalance = token.balanceOf(from);
|
||||
// when called due to burn, to will be the zero address, which will have a balance of 0
|
||||
uint256 toBalance = token.balanceOf(to);
|
||||
|
||||
emit TokensToSendCalled(
|
||||
operator,
|
||||
from,
|
||||
to,
|
||||
amount,
|
||||
userData,
|
||||
operatorData,
|
||||
address(token),
|
||||
fromBalance,
|
||||
toBalance
|
||||
);
|
||||
}
|
||||
|
||||
function tokensReceived(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint amount,
|
||||
bytes calldata userData,
|
||||
bytes calldata operatorData
|
||||
) external{
|
||||
if (_shouldRevertReceive) {
|
||||
revert();
|
||||
}
|
||||
|
||||
IERC777 token = IERC777(msg.sender);
|
||||
|
||||
uint256 fromBalance = token.balanceOf(from);
|
||||
// when called due to burn, to will be the zero address, which will have a balance of 0
|
||||
uint256 toBalance = token.balanceOf(to);
|
||||
|
||||
emit TokensReceivedCalled(
|
||||
operator,
|
||||
from,
|
||||
to,
|
||||
amount,
|
||||
userData,
|
||||
operatorData,
|
||||
address(token),
|
||||
fromBalance,
|
||||
toBalance
|
||||
);
|
||||
}
|
||||
|
||||
function senderFor(address account) public {
|
||||
_registerInterfaceForAddress(TOKENS_SENDER_INTERFACE_HASH, account);
|
||||
|
||||
address self = address(this);
|
||||
if (account == self) {
|
||||
registerSender(self);
|
||||
}
|
||||
}
|
||||
|
||||
function registerSender(address sender) public {
|
||||
_erc1820.setInterfaceImplementer(address(this), TOKENS_SENDER_INTERFACE_HASH, sender);
|
||||
}
|
||||
|
||||
function recipientFor(address account) public {
|
||||
_registerInterfaceForAddress(TOKENS_RECIPIENT_INTERFACE_HASH, account);
|
||||
|
||||
address self = address(this);
|
||||
if (account == self) {
|
||||
registerRecipient(self);
|
||||
}
|
||||
}
|
||||
|
||||
function registerRecipient(address recipient) public {
|
||||
_erc1820.setInterfaceImplementer(address(this), TOKENS_RECIPIENT_INTERFACE_HASH, recipient);
|
||||
}
|
||||
|
||||
function setShouldRevertSend(bool shouldRevert) public {
|
||||
_shouldRevertSend = shouldRevert;
|
||||
}
|
||||
|
||||
function setShouldRevertReceive(bool shouldRevert) public {
|
||||
_shouldRevertReceive = shouldRevert;
|
||||
}
|
||||
|
||||
function send(IERC777 token, address to, uint256 amount, bytes memory data) public {
|
||||
// This is 777's send function, not the Solidity send function
|
||||
token.send(to, amount, data); // solhint-disable-line check-send-result
|
||||
}
|
||||
|
||||
function burn(IERC777 token, uint256 amount, bytes memory data) public {
|
||||
token.burn(amount, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,73 +0,0 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
contract EventEmitter {
|
||||
event Argumentless();
|
||||
event ShortUint(uint8 value);
|
||||
event ShortInt(int8 value);
|
||||
event LongUint(uint256 value);
|
||||
event LongInt(int256 value);
|
||||
event Address(address value);
|
||||
event Boolean(bool value);
|
||||
event String(string value);
|
||||
event LongUintBooleanString(uint256 uintValue, bool booleanValue, string stringValue);
|
||||
|
||||
constructor (uint8 uintValue, bool booleanValue, string memory stringValue) public {
|
||||
emit ShortUint(uintValue);
|
||||
emit Boolean(booleanValue);
|
||||
emit String(stringValue);
|
||||
}
|
||||
|
||||
function emitArgumentless() public {
|
||||
emit Argumentless();
|
||||
}
|
||||
|
||||
function emitShortUint(uint8 value) public {
|
||||
emit ShortUint(value);
|
||||
}
|
||||
|
||||
function emitShortInt(int8 value) public {
|
||||
emit ShortInt(value);
|
||||
}
|
||||
|
||||
function emitLongUint(uint256 value) public {
|
||||
emit LongUint(value);
|
||||
}
|
||||
|
||||
function emitLongInt(int256 value) public {
|
||||
emit LongInt(value);
|
||||
}
|
||||
|
||||
function emitAddress(address value) public {
|
||||
emit Address(value);
|
||||
}
|
||||
|
||||
function emitBoolean(bool value) public {
|
||||
emit Boolean(value);
|
||||
}
|
||||
|
||||
function emitString(string memory value) public {
|
||||
emit String(value);
|
||||
}
|
||||
|
||||
function emitLongUintBooleanString(uint256 uintValue, bool booleanValue, string memory stringValue) public {
|
||||
emit LongUintBooleanString(uintValue, booleanValue, stringValue);
|
||||
}
|
||||
|
||||
function emitLongUintAndBoolean(uint256 uintValue, bool boolValue) public {
|
||||
emit LongUint(uintValue);
|
||||
emit Boolean(boolValue);
|
||||
}
|
||||
|
||||
function emitStringAndEmitIndirectly(string memory value, IndirectEventEmitter emitter) public {
|
||||
emit String(value);
|
||||
emitter.emitStringIndirectly(value);
|
||||
}
|
||||
}
|
||||
|
||||
contract IndirectEventEmitter {
|
||||
event IndirectString(string value);
|
||||
|
||||
function emitStringIndirectly(string memory value) public {
|
||||
emit IndirectString(value);
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
contract Failer {
|
||||
uint256[] private array;
|
||||
|
||||
function dontFail() public pure {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
function failWithRevert() public pure {
|
||||
revert();
|
||||
}
|
||||
|
||||
function failWithThrow() public pure {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
function failWithOutOfGas() public {
|
||||
for (uint256 i = 0; i < 2**200; ++i) {
|
||||
array.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../crowdsale/distribution/FinalizableCrowdsale.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../crowdsale/price/IncreasingPriceCrowdsale.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../math/Math.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import { MerkleProof } from "../cryptography/MerkleProof.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/ERC20Mintable.sol";
|
||||
import "../crowdsale/emission/MintedCrowdsale.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../access/roles/MinterRole.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/PausableCrowdsale.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../lifecycle/Pausable.sol";
|
||||
import "./PauserRoleMock.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../access/roles/PauserRole.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../crowdsale/distribution/PostDeliveryCrowdsale.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.2;
|
||||
pragma solidity ^0.5.7;
|
||||
|
||||
import "../payment/PullPayment.sol";
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user