Compare commits
78 Commits
release-v2
...
v3.0.0-rc.
| Author | SHA1 | Date | |
|---|---|---|---|
| 63a3665a17 | |||
| 92a60b2587 | |||
| a0f6bd3926 | |||
| 402c6ab4cc | |||
| 6668a4d05c | |||
| bd0778461d | |||
| 0408e51ae6 | |||
| 5b5d91c9d4 | |||
| 1bc923b6a2 | |||
| d704b5257b | |||
| 06ae096586 | |||
| 0f9adc1749 | |||
| feb7ead005 | |||
| 7415ebe8bc | |||
| 24c37c1f9e | |||
| c8bef057f8 | |||
| 97894a140d | |||
| 4476a2d531 | |||
| 7554ea84a3 | |||
| 3118bb33ac | |||
| 7c3606a19b | |||
| d6616fdb0d | |||
| c8aab57d8c | |||
| 3ae631c81d | |||
| 0afba1fb9d | |||
| a65bcfdbe8 | |||
| 60a73c6365 | |||
| 5112b6b1b5 | |||
| 865aae0106 | |||
| 5ccecab631 | |||
| a3c6e5f088 | |||
| a8d6f13c94 | |||
| e7b22483af | |||
| 90058040f0 | |||
| 63c89c772b | |||
| 9975a1a0c2 | |||
| eb34ae67ff | |||
| f1db30955d | |||
| c173392e15 | |||
| c9630526e2 | |||
| 8176a901a9 | |||
| baaadde3c5 | |||
| 68ad1ed18f | |||
| d14007d035 | |||
| a949d4e2bf | |||
| ed2c289c2c | |||
| 7acd60d152 | |||
| 0449062126 | |||
| 65e4ffde58 | |||
| e2813df879 | |||
| ca19cea05e | |||
| 3296ca7219 | |||
| cb458f3250 | |||
| 21d2b90d74 | |||
| ab19138f1f | |||
| 970122a9d5 | |||
| 62065cf043 | |||
| 03b61e074e | |||
| 1350f49939 | |||
| 1c22c79a32 | |||
| 08cea10aa7 | |||
| 82147dc2ee | |||
| e4d2830f1d | |||
| 19417c7cd5 | |||
| 5dfe7215a9 | |||
| 04a1b21874 | |||
| f905a14f5f | |||
| 4a531fe588 | |||
| 25dec297bf | |||
| 8e58cda8c3 | |||
| e7bded655b | |||
| 5f357d85de | |||
| 7988c044e0 | |||
| 8975289c6b | |||
| 6102ddf675 | |||
| 5a67a69f80 | |||
| f2512a4f7b | |||
| 06be0ab39a |
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
contact_links:
|
||||
- name: Support request
|
||||
url: https://forum.openzeppelin.com/c/support/contracts/18
|
||||
about: Ask the community in the Community Forum
|
||||
@ -1,14 +1,10 @@
|
||||
{
|
||||
"extends": "solhint:recommended",
|
||||
"rules": {
|
||||
"indent": ["error", 4],
|
||||
"func-order": "off",
|
||||
"bracket-align": "off",
|
||||
"compiler-fixed": "off",
|
||||
"no-simple-event-func-name": "off",
|
||||
"separate-by-one-line-in-contract": "off",
|
||||
"two-lines-top-level-separator": "off",
|
||||
"mark-callable-contracts": "off",
|
||||
"compiler-version": ["error", "^0.5.0"]
|
||||
"no-empty-blocks": "off",
|
||||
"compiler-version": ["error", "^0.6.0"],
|
||||
"private-vars-leading-underscore": "error"
|
||||
}
|
||||
}
|
||||
|
||||
36
CHANGELOG.md
36
CHANGELOG.md
@ -1,5 +1,41 @@
|
||||
# Changelog
|
||||
|
||||
## 3.0.0 (unreleased)
|
||||
|
||||
### New features
|
||||
* `AccessControl`: new contract for managing permissions in a system, replacement for `Ownable` and `Roles`. ([#2112](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2112))
|
||||
* `SafeCast`: new functions to convert to and from signed and unsigned values: `toUint256` and `toInt256`. ([#2123](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2123))
|
||||
* `EnumerableMap`: a new data structure for key-value pairs (like `mapping`) that can be iterated over. ([#2160](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2160))
|
||||
|
||||
### Breaking changes
|
||||
* `ERC721`: `burn(owner, tokenId)` was removed, use `burn(tokenId)` instead. ([#2125](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2125))
|
||||
* `ERC721`: `_checkOnERC721Received` was removed. ([#2125](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2125))
|
||||
* `ERC721`: `_transferFrom` and `_safeTransferFrom` were renamed to `_transfer` and `_safeTransfer`. ([#2162](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2162))
|
||||
* `Ownable`: removed `_transferOwnership`. ([#2162](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2162))
|
||||
* `PullPayment`, `Escrow`: `withdrawWithGas` was removed. The old `withdraw` function now forwards all gas. ([#2125](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2125))
|
||||
* `Roles` was removed, use `AccessControl` as a replacement. ([#2112](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2112))
|
||||
* `ECDSA`: when receiving an invalid signature, `recover` now reverts instead of returning the zero address. ([#2114](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2114))
|
||||
* `Create2`: added an `amount` argument to `deploy` for contracts with `payable` constructors. ([#2117](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2117))
|
||||
* `Pausable`: moved to the `utils` directory. ([#2122](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2122))
|
||||
* `Strings`: moved to the `utils` directory. ([#2122](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2122))
|
||||
* `Counters`: moved to the `utils` directory. ([#2122](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2122))
|
||||
* `SignedSafeMath`: moved to the `math` directory. ([#2122](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2122))
|
||||
* `ERC20Snapshot`: moved to the `token/ERC20` directory. `snapshot` was changed into an `internal` function. ([#2122](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2122))
|
||||
* `Ownable`: moved to the `access` directory. ([#2120](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2120))
|
||||
* `Ownable`: removed `isOwner`. ([#2120](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2120))
|
||||
* `Secondary`: removed from the library, use `Ownable` instead. ([#2120](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2120))
|
||||
* `Escrow`, `ConditionalEscrow`, `RefundEscrow`: these now use `Ownable` instead of `Secondary`, their external API changed accordingly. ([#2120](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2120))
|
||||
* `ERC20`: removed `_burnFrom`. ([#2119](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2119))
|
||||
* `Address`: removed `toPayable`, use `payable(address)` instead. ([#2133](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2133))
|
||||
* `ERC777`: `_send`, `_mint` and `_burn` now use the caller as the operator. ([#2134](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2134))
|
||||
* `ERC777`: removed `_callsTokensToSend` and `_callTokensReceived`. ([#2134](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2134))
|
||||
* `EnumerableSet`: renamed `get` to `at`. ([#2151](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2151))
|
||||
* `ERC165Checker`: functions no longer have a leading underscore. ([#2150](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2150))
|
||||
* `ERC721Metadata`, `ERC721Enumerable`: these contracts were removed, and their functionality merged into `ERC721`. ([#2160](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2160))
|
||||
* `ERC721`: added a constructor for `name` and `symbol`. ([#2160](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2160))
|
||||
* `ERC20Detailed`: this contract was removed and its functionality merged into `ERC20`. ([#2161](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2161))
|
||||
* `ERC20`: added a constructor for `name` and `symbol`. `decimals` now defaults to 18. ([#2161](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2161))
|
||||
|
||||
## 2.5.0 (2020-02-04)
|
||||
|
||||
### New features
|
||||
|
||||
@ -38,9 +38,9 @@ contract MyNFT is ERC721Full, ERC721Mintable {
|
||||
}
|
||||
```
|
||||
|
||||
_If you're new to smart contract development, head to [Developing Smart Contracts](https://docs.openzeppelin.com/contracts/learn::developing-smart-contracts) to learn about creating a new project and compiling your contracts._
|
||||
_If you're new to smart contract development, head to [Developing Smart Contracts](https://docs.openzeppelin.com/learn/developing-smart-contracts) to learn about creating a new project and compiling your contracts._
|
||||
|
||||
To keep your system secure, you should **always** use the installed code as-is, and neither copy-paste it from online sources, nor modify it yourself.
|
||||
To keep your system secure, you should **always** use the installed code as-is, and neither copy-paste it from online sources, nor modify it yourself. The library is designed so that only the contracts and functions you use are deployed, so you don't need to worry about it needlessly increasing gas costs.
|
||||
|
||||
## Learn More
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/*
|
||||
* @dev Provides information about the current execution context, including the
|
||||
@ -14,13 +14,12 @@ contract Context {
|
||||
// Empty internal constructor, to prevent people from mistakenly deploying
|
||||
// an instance of this contract, which should be used via inheritance.
|
||||
constructor () internal { }
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
|
||||
function _msgSender() internal view returns (address payable) {
|
||||
function _msgSender() internal view virtual returns (address payable) {
|
||||
return msg.sender;
|
||||
}
|
||||
|
||||
function _msgData() internal view returns (bytes memory) {
|
||||
function _msgData() internal view virtual returns (bytes memory) {
|
||||
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
|
||||
return msg.data;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "./IRelayRecipient.sol";
|
||||
import "./IRelayHub.sol";
|
||||
@ -15,15 +15,15 @@ import "./Context.sol";
|
||||
* information on how to use the pre-built {GSNRecipientSignature} and
|
||||
* {GSNRecipientERC20Fee}, or how to write your own.
|
||||
*/
|
||||
contract GSNRecipient is IRelayRecipient, Context {
|
||||
abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
// Default RelayHub address, deployed on mainnet and all testnets at the same address
|
||||
address private _relayHub = 0xD216153c06E857cD7f72665E0aF1d7D82172F494;
|
||||
|
||||
uint256 constant private RELAYED_CALL_ACCEPTED = 0;
|
||||
uint256 constant private RELAYED_CALL_REJECTED = 11;
|
||||
uint256 constant private _RELAYED_CALL_ACCEPTED = 0;
|
||||
uint256 constant private _RELAYED_CALL_REJECTED = 11;
|
||||
|
||||
// How much gas is forwarded to postRelayedCall
|
||||
uint256 constant internal POST_RELAYED_CALL_MAX_GAS = 100000;
|
||||
uint256 constant internal _POST_RELAYED_CALL_MAX_GAS = 100000;
|
||||
|
||||
/**
|
||||
* @dev Emitted when a contract changes its {IRelayHub} contract to a new one.
|
||||
@ -33,7 +33,7 @@ contract GSNRecipient is IRelayRecipient, Context {
|
||||
/**
|
||||
* @dev Returns the address of the {IRelayHub} contract for this recipient.
|
||||
*/
|
||||
function getHubAddr() public view returns (address) {
|
||||
function getHubAddr() public view override returns (address) {
|
||||
return _relayHub;
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ contract GSNRecipient is IRelayRecipient, Context {
|
||||
* IMPORTANT: After upgrading, the {GSNRecipient} will no longer be able to receive relayed calls from the old
|
||||
* {IRelayHub} instance. Additionally, all funds should be previously withdrawn via {_withdrawDeposits}.
|
||||
*/
|
||||
function _upgradeRelayHub(address newRelayHub) internal {
|
||||
function _upgradeRelayHub(address newRelayHub) internal virtual {
|
||||
address currentRelayHub = _relayHub;
|
||||
require(newRelayHub != address(0), "GSNRecipient: new RelayHub is the zero address");
|
||||
require(newRelayHub != currentRelayHub, "GSNRecipient: new RelayHub is the current one");
|
||||
@ -70,7 +70,7 @@ contract GSNRecipient is IRelayRecipient, Context {
|
||||
*
|
||||
* Derived contracts should expose this in an external interface with proper access control.
|
||||
*/
|
||||
function _withdrawDeposits(uint256 amount, address payable payee) internal {
|
||||
function _withdrawDeposits(uint256 amount, address payable payee) internal virtual {
|
||||
IRelayHub(_relayHub).withdraw(amount, payee);
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ contract GSNRecipient is IRelayRecipient, Context {
|
||||
*
|
||||
* IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.sender`, and use {_msgSender} instead.
|
||||
*/
|
||||
function _msgSender() internal view returns (address payable) {
|
||||
function _msgSender() internal view virtual override returns (address payable) {
|
||||
if (msg.sender != _relayHub) {
|
||||
return msg.sender;
|
||||
} else {
|
||||
@ -99,7 +99,7 @@ contract GSNRecipient is IRelayRecipient, Context {
|
||||
*
|
||||
* IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.data`, and use {_msgData} instead.
|
||||
*/
|
||||
function _msgData() internal view returns (bytes memory) {
|
||||
function _msgData() internal view virtual override returns (bytes memory) {
|
||||
if (msg.sender != _relayHub) {
|
||||
return msg.data;
|
||||
} else {
|
||||
@ -119,7 +119,7 @@ contract GSNRecipient is IRelayRecipient, Context {
|
||||
*
|
||||
* - the caller must be the `RelayHub` contract.
|
||||
*/
|
||||
function preRelayedCall(bytes calldata context) external returns (bytes32) {
|
||||
function preRelayedCall(bytes memory context) public virtual override returns (bytes32) {
|
||||
require(msg.sender == getHubAddr(), "GSNRecipient: caller is not RelayHub");
|
||||
return _preRelayedCall(context);
|
||||
}
|
||||
@ -131,7 +131,7 @@ contract GSNRecipient is IRelayRecipient, Context {
|
||||
* must implement this function with any relayed-call preprocessing they may wish to do.
|
||||
*
|
||||
*/
|
||||
function _preRelayedCall(bytes memory context) internal returns (bytes32);
|
||||
function _preRelayedCall(bytes memory context) internal virtual returns (bytes32);
|
||||
|
||||
/**
|
||||
* @dev See `IRelayRecipient.postRelayedCall`.
|
||||
@ -142,7 +142,7 @@ contract GSNRecipient is IRelayRecipient, Context {
|
||||
*
|
||||
* - the caller must be the `RelayHub` contract.
|
||||
*/
|
||||
function postRelayedCall(bytes calldata context, bool success, uint256 actualCharge, bytes32 preRetVal) external {
|
||||
function postRelayedCall(bytes memory context, bool success, uint256 actualCharge, bytes32 preRetVal) public virtual override {
|
||||
require(msg.sender == getHubAddr(), "GSNRecipient: caller is not RelayHub");
|
||||
_postRelayedCall(context, success, actualCharge, preRetVal);
|
||||
}
|
||||
@ -154,7 +154,7 @@ contract GSNRecipient is IRelayRecipient, Context {
|
||||
* must implement this function with any relayed-call postprocessing they may wish to do.
|
||||
*
|
||||
*/
|
||||
function _postRelayedCall(bytes memory context, bool success, uint256 actualCharge, bytes32 preRetVal) internal;
|
||||
function _postRelayedCall(bytes memory context, bool success, uint256 actualCharge, bytes32 preRetVal) internal virtual;
|
||||
|
||||
/**
|
||||
* @dev Return this in acceptRelayedCall to proceed with the execution of a relayed call. Note that this contract
|
||||
@ -170,14 +170,14 @@ contract GSNRecipient is IRelayRecipient, Context {
|
||||
* This overload forwards `context` to _preRelayedCall and _postRelayedCall.
|
||||
*/
|
||||
function _approveRelayedCall(bytes memory context) internal pure returns (uint256, bytes memory) {
|
||||
return (RELAYED_CALL_ACCEPTED, context);
|
||||
return (_RELAYED_CALL_ACCEPTED, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return this in acceptRelayedCall to impede execution of a relayed call. No fees will be charged.
|
||||
*/
|
||||
function _rejectRelayedCall(uint256 errorCode) internal pure returns (uint256, bytes memory) {
|
||||
return (RELAYED_CALL_REJECTED + errorCode, "");
|
||||
return (_RELAYED_CALL_REJECTED + errorCode, "");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "./GSNRecipient.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
import "../ownership/Secondary.sol";
|
||||
import "../access/Ownable.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
|
||||
/**
|
||||
* @dev A xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategy] that charges transaction fees in a special purpose ERC20
|
||||
@ -17,20 +16,20 @@ import "../token/ERC20/ERC20Detailed.sol";
|
||||
* internal {_mint} function.
|
||||
*/
|
||||
contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
using SafeERC20 for __unstable__ERC20PrimaryAdmin;
|
||||
using SafeERC20 for __unstable__ERC20Owned;
|
||||
using SafeMath for uint256;
|
||||
|
||||
enum GSNRecipientERC20FeeErrorCodes {
|
||||
INSUFFICIENT_BALANCE
|
||||
}
|
||||
|
||||
__unstable__ERC20PrimaryAdmin private _token;
|
||||
__unstable__ERC20Owned private _token;
|
||||
|
||||
/**
|
||||
* @dev The arguments to the constructor are the details that the gas payment token will have: `name` and `symbol`. `decimals` is hard-coded to 18.
|
||||
*/
|
||||
constructor(string memory name, string memory symbol) public {
|
||||
_token = new __unstable__ERC20PrimaryAdmin(name, symbol, 18);
|
||||
_token = new __unstable__ERC20Owned(name, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,7 +42,7 @@ contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
/**
|
||||
* @dev Internal function that mints the gas payment token. Derived contracts should expose this function in their public API, with proper access control mechanisms.
|
||||
*/
|
||||
function _mint(address account, uint256 amount) internal {
|
||||
function _mint(address account, uint256 amount) internal virtual {
|
||||
_token.mint(account, amount);
|
||||
}
|
||||
|
||||
@ -53,16 +52,18 @@ contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
function acceptRelayedCall(
|
||||
address,
|
||||
address from,
|
||||
bytes calldata,
|
||||
bytes memory,
|
||||
uint256 transactionFee,
|
||||
uint256 gasPrice,
|
||||
uint256,
|
||||
uint256,
|
||||
bytes calldata,
|
||||
bytes memory,
|
||||
uint256 maxPossibleCharge
|
||||
)
|
||||
external
|
||||
public
|
||||
view
|
||||
virtual
|
||||
override
|
||||
returns (uint256, bytes memory)
|
||||
{
|
||||
if (_token.balanceOf(from) < maxPossibleCharge) {
|
||||
@ -78,7 +79,7 @@ contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
* actual charge, necessary because we cannot predict how much gas the execution will actually need. The remainder
|
||||
* is returned to the user in {_postRelayedCall}.
|
||||
*/
|
||||
function _preRelayedCall(bytes memory context) internal returns (bytes32) {
|
||||
function _preRelayedCall(bytes memory context) internal virtual override returns (bytes32) {
|
||||
(address from, uint256 maxPossibleCharge) = abi.decode(context, (address, uint256));
|
||||
|
||||
// The maximum token charge is pre-charged from the user
|
||||
@ -88,14 +89,14 @@ contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
/**
|
||||
* @dev Returns to the user the extra amount that was previously charged, once the actual execution cost is known.
|
||||
*/
|
||||
function _postRelayedCall(bytes memory context, bool, uint256 actualCharge, bytes32) internal {
|
||||
function _postRelayedCall(bytes memory context, bool, uint256 actualCharge, bytes32) internal virtual override {
|
||||
(address from, uint256 maxPossibleCharge, uint256 transactionFee, uint256 gasPrice) =
|
||||
abi.decode(context, (address, uint256, uint256, uint256));
|
||||
|
||||
// actualCharge is an _estimated_ charge, which assumes postRelayedCall will use all available gas.
|
||||
// This implementation's gas cost can be roughly estimated as 10k gas, for the two SSTORE operations in an
|
||||
// ERC20 transfer.
|
||||
uint256 overestimation = _computeCharge(POST_RELAYED_CALL_MAX_GAS.sub(10000), gasPrice, transactionFee);
|
||||
uint256 overestimation = _computeCharge(_POST_RELAYED_CALL_MAX_GAS.sub(10000), gasPrice, transactionFee);
|
||||
actualCharge = actualCharge.sub(overestimation);
|
||||
|
||||
// After the relayed call has been executed and the actual charge estimated, the excess pre-charge is returned
|
||||
@ -104,44 +105,42 @@ contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
}
|
||||
|
||||
/**
|
||||
* @title __unstable__ERC20PrimaryAdmin
|
||||
* @title __unstable__ERC20Owned
|
||||
* @dev An ERC20 token owned by another contract, which has minting permissions and can use transferFrom to receive
|
||||
* anyone's tokens. This contract is an internal helper for GSNRecipientERC20Fee, and should not be used
|
||||
* outside of this context.
|
||||
*/
|
||||
// solhint-disable-next-line contract-name-camelcase
|
||||
contract __unstable__ERC20PrimaryAdmin is ERC20, ERC20Detailed, Secondary {
|
||||
uint256 private constant UINT256_MAX = 2**256 - 1;
|
||||
contract __unstable__ERC20Owned is ERC20, Ownable {
|
||||
uint256 private constant _UINT256_MAX = 2**256 - 1;
|
||||
|
||||
constructor(string memory name, string memory symbol, uint8 decimals) public ERC20Detailed(name, symbol, decimals) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
constructor(string memory name, string memory symbol) public ERC20(name, symbol) { }
|
||||
|
||||
// The primary account (GSNRecipientERC20Fee) can mint tokens
|
||||
function mint(address account, uint256 amount) public onlyPrimary {
|
||||
// The owner (GSNRecipientERC20Fee) can mint tokens
|
||||
function mint(address account, uint256 amount) public onlyOwner {
|
||||
_mint(account, amount);
|
||||
}
|
||||
|
||||
// The primary account has 'infinite' allowance for all token holders
|
||||
function allowance(address owner, address spender) public view returns (uint256) {
|
||||
if (spender == primary()) {
|
||||
return UINT256_MAX;
|
||||
// The owner has 'infinite' allowance for all token holders
|
||||
function allowance(address tokenOwner, address spender) public view override returns (uint256) {
|
||||
if (spender == owner()) {
|
||||
return _UINT256_MAX;
|
||||
} else {
|
||||
return super.allowance(owner, spender);
|
||||
return super.allowance(tokenOwner, spender);
|
||||
}
|
||||
}
|
||||
|
||||
// Allowance for the primary account cannot be changed (it is always 'infinite')
|
||||
function _approve(address owner, address spender, uint256 value) internal {
|
||||
if (spender == primary()) {
|
||||
// Allowance for the owner cannot be changed (it is always 'infinite')
|
||||
function _approve(address tokenOwner, address spender, uint256 value) internal override {
|
||||
if (spender == owner()) {
|
||||
return;
|
||||
} else {
|
||||
super._approve(owner, spender, value);
|
||||
super._approve(tokenOwner, spender, value);
|
||||
}
|
||||
}
|
||||
|
||||
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
|
||||
if (recipient == primary()) {
|
||||
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
|
||||
if (recipient == owner()) {
|
||||
_transfer(sender, recipient, amount);
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "./GSNRecipient.sol";
|
||||
import "../cryptography/ECDSA.sol";
|
||||
@ -32,16 +32,18 @@ contract GSNRecipientSignature is GSNRecipient {
|
||||
function acceptRelayedCall(
|
||||
address relay,
|
||||
address from,
|
||||
bytes calldata encodedFunction,
|
||||
bytes memory encodedFunction,
|
||||
uint256 transactionFee,
|
||||
uint256 gasPrice,
|
||||
uint256 gasLimit,
|
||||
uint256 nonce,
|
||||
bytes calldata approvalData,
|
||||
bytes memory approvalData,
|
||||
uint256
|
||||
)
|
||||
external
|
||||
public
|
||||
view
|
||||
virtual
|
||||
override
|
||||
returns (uint256, bytes memory)
|
||||
{
|
||||
bytes memory blob = abi.encodePacked(
|
||||
@ -62,11 +64,7 @@ contract GSNRecipientSignature is GSNRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
function _preRelayedCall(bytes memory) internal returns (bytes32) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
function _preRelayedCall(bytes memory) internal virtual override returns (bytes32) { }
|
||||
|
||||
function _postRelayedCall(bytes memory, bool, uint256, bytes32) internal {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
function _postRelayedCall(bytes memory, bool, uint256, bytes32) internal virtual override { }
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @dev Interface for `RelayHub`, the core contract of the GSN. Users should not need to interact with this contract
|
||||
@ -207,7 +207,7 @@ interface IRelayHub {
|
||||
event CanRelayFailed(address indexed relay, address indexed from, address indexed to, bytes4 selector, uint256 reason);
|
||||
|
||||
/**
|
||||
* @dev Emitted when a transaction is relayed.
|
||||
* @dev Emitted when a transaction is relayed.
|
||||
* Useful when monitoring a relay's operation and relayed calls to a contract
|
||||
*
|
||||
* Note that the actual encoded function might be reverted: this is indicated in the `status` parameter.
|
||||
@ -236,7 +236,7 @@ interface IRelayHub {
|
||||
*/
|
||||
function maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee) external view returns (uint256);
|
||||
|
||||
// Relay penalization.
|
||||
// Relay penalization.
|
||||
// Any account can penalize relays, removing them from the system immediately, and rewarding the
|
||||
// reporter with half of the relay's stake. The other half is burned so that, even if the relay penalizes itself, it
|
||||
// still loses half of its stake.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @dev Base interface for a contract that will be called via the GSN from {IRelayHub}.
|
||||
|
||||
194
contracts/access/AccessControl.sol
Normal file
194
contracts/access/AccessControl.sol
Normal file
@ -0,0 +1,194 @@
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../utils/EnumerableSet.sol";
|
||||
import "../utils/Address.sol";
|
||||
import "../GSN/Context.sol";
|
||||
|
||||
/**
|
||||
* @dev Contract module that allows children to implement role-based access
|
||||
* control mechanisms.
|
||||
*
|
||||
* Roles are referred to by their `bytes32` identifier. These should be exposed
|
||||
* in the external API and be unique. The best way to achieve this is by
|
||||
* using `public constant` hash digests:
|
||||
*
|
||||
* ```
|
||||
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
|
||||
* ```
|
||||
*
|
||||
* Roles can be used to represent a set of permissions. To restrict access to a
|
||||
* function call, use {hasRole}:
|
||||
*
|
||||
* ```
|
||||
* function foo() public {
|
||||
* require(hasRole(MY_ROLE, _msgSender()));
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Roles can be granted and revoked dynamically via the {grantRole} and
|
||||
* {revokeRole} functions. Each role has an associated admin role, and only
|
||||
* accounts that have a role's admin role can call {grantRole} and {revokeRoke}.
|
||||
*
|
||||
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
|
||||
* that only accounts with this role will be able to grant or revoke other
|
||||
* roles. More complex role relationships can be created by using
|
||||
* {_setRoleAdmin}.
|
||||
*/
|
||||
abstract contract AccessControl is Context {
|
||||
using EnumerableSet for EnumerableSet.AddressSet;
|
||||
using Address for address;
|
||||
|
||||
struct RoleData {
|
||||
EnumerableSet.AddressSet members;
|
||||
bytes32 adminRole;
|
||||
}
|
||||
|
||||
mapping (bytes32 => RoleData) private _roles;
|
||||
|
||||
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
|
||||
|
||||
/**
|
||||
* @dev Emitted when `account` is granted `role`.
|
||||
*
|
||||
* `sender` is the account that originated the contract call, an admin role
|
||||
* bearer except when using {_setupRole}.
|
||||
*/
|
||||
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
|
||||
|
||||
/**
|
||||
* @dev Emitted when `account` is revoked `role`.
|
||||
*
|
||||
* `sender` is the account that originated the contract call:
|
||||
* - if using `revokeRole`, it is the admin role bearer
|
||||
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
|
||||
*/
|
||||
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
|
||||
|
||||
/**
|
||||
* @dev Returns `true` if `account` has been granted `role`.
|
||||
*/
|
||||
function hasRole(bytes32 role, address account) public view returns (bool) {
|
||||
return _roles[role].members.contains(account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the number of accounts that have `role`. Can be used
|
||||
* together with {getRoleMember} to enumerate all bearers of a role.
|
||||
*/
|
||||
function getRoleMemberCount(bytes32 role) public view returns (uint256) {
|
||||
return _roles[role].members.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns one of the accounts that have `role`. `index` must be a
|
||||
* value between 0 and {getRoleMemberCount}, non-inclusive.
|
||||
*
|
||||
* Role bearers are not sorted in any particular way, and their ordering may
|
||||
* change at any point.
|
||||
*
|
||||
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
|
||||
* you perform all queries on the same block. See the following
|
||||
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
|
||||
* for more information.
|
||||
*/
|
||||
function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
|
||||
return _roles[role].members.at(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the admin role that controls `role`. See {grantRole} and
|
||||
* {revokeRole}.
|
||||
*
|
||||
* To change a role's admin, use {_setRoleAdmin}.
|
||||
*/
|
||||
function getRoleAdmin(bytes32 role) public view returns (bytes32) {
|
||||
return _roles[role].adminRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Grants `role` to `account`.
|
||||
*
|
||||
* If `account` had not been already granted `role`, emits a {RoleGranted}
|
||||
* event.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must have `role`'s admin role.
|
||||
*/
|
||||
function grantRole(bytes32 role, address account) public virtual {
|
||||
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");
|
||||
|
||||
_grantRole(role, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Revokes `role` from `account`.
|
||||
*
|
||||
* If `account` had been granted `role`, emits a {RoleRevoked} event.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must have `role`'s admin role.
|
||||
*/
|
||||
function revokeRole(bytes32 role, address account) public virtual {
|
||||
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");
|
||||
|
||||
_revokeRole(role, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Revokes `role` from the calling account.
|
||||
*
|
||||
* Roles are often managed via {grantRole} and {revokeRole}: this function's
|
||||
* purpose is to provide a mechanism for accounts to lose their privileges
|
||||
* if they are compromised (such as when a trusted device is misplaced).
|
||||
*
|
||||
* If the calling account had been granted `role`, emits a {RoleRevoked}
|
||||
* event.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be `account`.
|
||||
*/
|
||||
function renounceRole(bytes32 role, address account) public virtual {
|
||||
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
|
||||
|
||||
_revokeRole(role, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Grants `role` to `account`.
|
||||
*
|
||||
* If `account` had not been already granted `role`, emits a {RoleGranted}
|
||||
* event. Note that unlike {grantRole}, this function doesn't perform any
|
||||
* checks on the calling account.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - this function can only be called from a constructor.
|
||||
*/
|
||||
function _setupRole(bytes32 role, address account) internal virtual {
|
||||
require(!address(this).isContract(), "AccessControl: roles cannot be setup after construction");
|
||||
_grantRole(role, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sets `adminRole` as `role`'s admin role.
|
||||
*/
|
||||
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
|
||||
_roles[role].adminRole = adminRole;
|
||||
}
|
||||
|
||||
function _grantRole(bytes32 role, address account) private {
|
||||
if (_roles[role].members.add(account)) {
|
||||
emit RoleGranted(role, account, _msgSender());
|
||||
}
|
||||
}
|
||||
|
||||
function _revokeRole(bytes32 role, address account) private {
|
||||
if (_roles[role].members.remove(account)) {
|
||||
emit RoleRevoked(role, account, _msgSender());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
/**
|
||||
@ -6,6 +6,9 @@ import "../GSN/Context.sol";
|
||||
* there is an account (an owner) that can be granted exclusive access to
|
||||
* specific functions.
|
||||
*
|
||||
* By default, the owner account will be the one that deploys the contract. This
|
||||
* can later be changed with {transferOwnership}.
|
||||
*
|
||||
* This module is used through inheritance. It will make available the modifier
|
||||
* `onlyOwner`, which can be applied to your functions to restrict their use to
|
||||
* the owner.
|
||||
@ -35,17 +38,10 @@ contract Ownable is Context {
|
||||
* @dev Throws if called by any account other than the owner.
|
||||
*/
|
||||
modifier onlyOwner() {
|
||||
require(isOwner(), "Ownable: caller is not the owner");
|
||||
require(_owner == _msgSender(), "Ownable: caller is not the owner");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns true if the caller is the current owner.
|
||||
*/
|
||||
function isOwner() public view returns (bool) {
|
||||
return _msgSender() == _owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Leaves the contract without owner. It will not be possible to call
|
||||
* `onlyOwner` functions anymore. Can only be called by the current owner.
|
||||
@ -53,7 +49,7 @@ contract Ownable is Context {
|
||||
* NOTE: Renouncing ownership will leave the contract without an owner,
|
||||
* thereby removing any functionality that is only available to the owner.
|
||||
*/
|
||||
function renounceOwnership() public onlyOwner {
|
||||
function renounceOwnership() public virtual onlyOwner {
|
||||
emit OwnershipTransferred(_owner, address(0));
|
||||
_owner = address(0);
|
||||
}
|
||||
@ -62,14 +58,7 @@ contract Ownable is Context {
|
||||
* @dev Transfers ownership of the contract to a new account (`newOwner`).
|
||||
* Can only be called by the current owner.
|
||||
*/
|
||||
function transferOwnership(address newOwner) public onlyOwner {
|
||||
_transferOwnership(newOwner);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers ownership of the contract to a new account (`newOwner`).
|
||||
*/
|
||||
function _transferOwnership(address newOwner) internal {
|
||||
function transferOwnership(address newOwner) public virtual onlyOwner {
|
||||
require(newOwner != address(0), "Ownable: new owner is the zero address");
|
||||
emit OwnershipTransferred(_owner, newOwner);
|
||||
_owner = newOwner;
|
||||
@ -1,21 +1,9 @@
|
||||
= Access
|
||||
|
||||
NOTE: This page is incomplete. We're working to improve it for the next release. Stay tuned!
|
||||
Contract modules for authorization and access control mechanisms.
|
||||
|
||||
== Library
|
||||
== Contracts
|
||||
|
||||
{{Roles}}
|
||||
{{Ownable}}
|
||||
|
||||
== Roles
|
||||
|
||||
{{CapperRole}}
|
||||
|
||||
{{MinterRole}}
|
||||
|
||||
{{PauserRole}}
|
||||
|
||||
{{SignerRole}}
|
||||
|
||||
{{WhitelistAdminRole}}
|
||||
|
||||
{{WhitelistedRole}}
|
||||
{{AccessControl}}
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
/**
|
||||
* @title Roles
|
||||
* @dev Library for managing addresses assigned to a Role.
|
||||
*/
|
||||
library Roles {
|
||||
struct Role {
|
||||
mapping (address => bool) bearer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Give an account access to this role.
|
||||
*/
|
||||
function add(Role storage role, address account) internal {
|
||||
require(!has(role, account), "Roles: account already has role");
|
||||
role.bearer[account] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Remove an account's access to this role.
|
||||
*/
|
||||
function remove(Role storage role, address account) internal {
|
||||
require(has(role, account), "Roles: account does not have role");
|
||||
role.bearer[account] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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), "Roles: account is the zero address");
|
||||
return role.bearer[account];
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../GSN/Context.sol";
|
||||
import "../Roles.sol";
|
||||
|
||||
contract CapperRole is Context {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event CapperAdded(address indexed account);
|
||||
event CapperRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _cappers;
|
||||
|
||||
constructor () internal {
|
||||
_addCapper(_msgSender());
|
||||
}
|
||||
|
||||
modifier onlyCapper() {
|
||||
require(isCapper(_msgSender()), "CapperRole: caller does not have the Capper role");
|
||||
_;
|
||||
}
|
||||
|
||||
function isCapper(address account) public view returns (bool) {
|
||||
return _cappers.has(account);
|
||||
}
|
||||
|
||||
function addCapper(address account) public onlyCapper {
|
||||
_addCapper(account);
|
||||
}
|
||||
|
||||
function renounceCapper() public {
|
||||
_removeCapper(_msgSender());
|
||||
}
|
||||
|
||||
function _addCapper(address account) internal {
|
||||
_cappers.add(account);
|
||||
emit CapperAdded(account);
|
||||
}
|
||||
|
||||
function _removeCapper(address account) internal {
|
||||
_cappers.remove(account);
|
||||
emit CapperRemoved(account);
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../GSN/Context.sol";
|
||||
import "../Roles.sol";
|
||||
|
||||
contract MinterRole is Context {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event MinterAdded(address indexed account);
|
||||
event MinterRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _minters;
|
||||
|
||||
constructor () internal {
|
||||
_addMinter(_msgSender());
|
||||
}
|
||||
|
||||
modifier onlyMinter() {
|
||||
require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role");
|
||||
_;
|
||||
}
|
||||
|
||||
function isMinter(address account) public view returns (bool) {
|
||||
return _minters.has(account);
|
||||
}
|
||||
|
||||
function addMinter(address account) public onlyMinter {
|
||||
_addMinter(account);
|
||||
}
|
||||
|
||||
function renounceMinter() public {
|
||||
_removeMinter(_msgSender());
|
||||
}
|
||||
|
||||
function _addMinter(address account) internal {
|
||||
_minters.add(account);
|
||||
emit MinterAdded(account);
|
||||
}
|
||||
|
||||
function _removeMinter(address account) internal {
|
||||
_minters.remove(account);
|
||||
emit MinterRemoved(account);
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../GSN/Context.sol";
|
||||
import "../Roles.sol";
|
||||
|
||||
contract PauserRole is Context {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event PauserAdded(address indexed account);
|
||||
event PauserRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _pausers;
|
||||
|
||||
constructor () internal {
|
||||
_addPauser(_msgSender());
|
||||
}
|
||||
|
||||
modifier onlyPauser() {
|
||||
require(isPauser(_msgSender()), "PauserRole: caller does not have the Pauser role");
|
||||
_;
|
||||
}
|
||||
|
||||
function isPauser(address account) public view returns (bool) {
|
||||
return _pausers.has(account);
|
||||
}
|
||||
|
||||
function addPauser(address account) public onlyPauser {
|
||||
_addPauser(account);
|
||||
}
|
||||
|
||||
function renouncePauser() public {
|
||||
_removePauser(_msgSender());
|
||||
}
|
||||
|
||||
function _addPauser(address account) internal {
|
||||
_pausers.add(account);
|
||||
emit PauserAdded(account);
|
||||
}
|
||||
|
||||
function _removePauser(address account) internal {
|
||||
_pausers.remove(account);
|
||||
emit PauserRemoved(account);
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../GSN/Context.sol";
|
||||
import "../Roles.sol";
|
||||
|
||||
contract SignerRole is Context {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event SignerAdded(address indexed account);
|
||||
event SignerRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _signers;
|
||||
|
||||
constructor () internal {
|
||||
_addSigner(_msgSender());
|
||||
}
|
||||
|
||||
modifier onlySigner() {
|
||||
require(isSigner(_msgSender()), "SignerRole: caller does not have the Signer role");
|
||||
_;
|
||||
}
|
||||
|
||||
function isSigner(address account) public view returns (bool) {
|
||||
return _signers.has(account);
|
||||
}
|
||||
|
||||
function addSigner(address account) public onlySigner {
|
||||
_addSigner(account);
|
||||
}
|
||||
|
||||
function renounceSigner() public {
|
||||
_removeSigner(_msgSender());
|
||||
}
|
||||
|
||||
function _addSigner(address account) internal {
|
||||
_signers.add(account);
|
||||
emit SignerAdded(account);
|
||||
}
|
||||
|
||||
function _removeSigner(address account) internal {
|
||||
_signers.remove(account);
|
||||
emit SignerRemoved(account);
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../GSN/Context.sol";
|
||||
import "../Roles.sol";
|
||||
|
||||
/**
|
||||
* @title WhitelistAdminRole
|
||||
* @dev WhitelistAdmins are responsible for assigning and removing Whitelisted accounts.
|
||||
*/
|
||||
contract WhitelistAdminRole is Context {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event WhitelistAdminAdded(address indexed account);
|
||||
event WhitelistAdminRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _whitelistAdmins;
|
||||
|
||||
constructor () internal {
|
||||
_addWhitelistAdmin(_msgSender());
|
||||
}
|
||||
|
||||
modifier onlyWhitelistAdmin() {
|
||||
require(isWhitelistAdmin(_msgSender()), "WhitelistAdminRole: caller does not have the WhitelistAdmin role");
|
||||
_;
|
||||
}
|
||||
|
||||
function isWhitelistAdmin(address account) public view returns (bool) {
|
||||
return _whitelistAdmins.has(account);
|
||||
}
|
||||
|
||||
function addWhitelistAdmin(address account) public onlyWhitelistAdmin {
|
||||
_addWhitelistAdmin(account);
|
||||
}
|
||||
|
||||
function renounceWhitelistAdmin() public {
|
||||
_removeWhitelistAdmin(_msgSender());
|
||||
}
|
||||
|
||||
function _addWhitelistAdmin(address account) internal {
|
||||
_whitelistAdmins.add(account);
|
||||
emit WhitelistAdminAdded(account);
|
||||
}
|
||||
|
||||
function _removeWhitelistAdmin(address account) internal {
|
||||
_whitelistAdmins.remove(account);
|
||||
emit WhitelistAdminRemoved(account);
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../GSN/Context.sol";
|
||||
import "../Roles.sol";
|
||||
import "./WhitelistAdminRole.sol";
|
||||
|
||||
/**
|
||||
* @title WhitelistedRole
|
||||
* @dev Whitelisted accounts have been approved by a WhitelistAdmin to perform certain actions (e.g. participate in a
|
||||
* crowdsale). This role is special in that the only accounts that can add it are WhitelistAdmins (who can also remove
|
||||
* it), and not Whitelisteds themselves.
|
||||
*/
|
||||
contract WhitelistedRole is Context, WhitelistAdminRole {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event WhitelistedAdded(address indexed account);
|
||||
event WhitelistedRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _whitelisteds;
|
||||
|
||||
modifier onlyWhitelisted() {
|
||||
require(isWhitelisted(_msgSender()), "WhitelistedRole: caller does not have the Whitelisted role");
|
||||
_;
|
||||
}
|
||||
|
||||
function isWhitelisted(address account) public view returns (bool) {
|
||||
return _whitelisteds.has(account);
|
||||
}
|
||||
|
||||
function addWhitelisted(address account) public onlyWhitelistAdmin {
|
||||
_addWhitelisted(account);
|
||||
}
|
||||
|
||||
function removeWhitelisted(address account) public onlyWhitelistAdmin {
|
||||
_removeWhitelisted(account);
|
||||
}
|
||||
|
||||
function renounceWhitelisted() public {
|
||||
_removeWhitelisted(_msgSender());
|
||||
}
|
||||
|
||||
function _addWhitelisted(address account) internal {
|
||||
_whitelisteds.add(account);
|
||||
emit WhitelistedAdded(account);
|
||||
}
|
||||
|
||||
function _removeWhitelisted(address account) internal {
|
||||
_whitelisteds.remove(account);
|
||||
emit WhitelistedRemoved(account);
|
||||
}
|
||||
}
|
||||
@ -1,200 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
import "../utils/ReentrancyGuard.sol";
|
||||
|
||||
/**
|
||||
* @title Crowdsale
|
||||
* @dev Crowdsale is a base contract for managing a token crowdsale,
|
||||
* allowing investors to purchase tokens with ether. This contract implements
|
||||
* such functionality in its most fundamental form and can be extended to provide additional
|
||||
* functionality and/or custom behavior.
|
||||
* The external interface represents the basic interface for purchasing tokens, and conforms
|
||||
* the base architecture for crowdsales. It is *not* intended to be modified / overridden.
|
||||
* The internal interface conforms the extensible and modifiable surface of crowdsales. Override
|
||||
* the methods to add functionality. Consider using 'super' where appropriate to concatenate
|
||||
* behavior.
|
||||
*/
|
||||
contract Crowdsale is Context, ReentrancyGuard {
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
// The token being sold
|
||||
IERC20 private _token;
|
||||
|
||||
// Address where funds are collected
|
||||
address payable private _wallet;
|
||||
|
||||
// How many token units a buyer gets per wei.
|
||||
// The rate is the conversion between wei and the smallest and indivisible token unit.
|
||||
// So, if you are using a rate of 1 with a ERC20Detailed token with 3 decimals called TOK
|
||||
// 1 wei will give you 1 unit, or 0.001 TOK.
|
||||
uint256 private _rate;
|
||||
|
||||
// Amount of wei raised
|
||||
uint256 private _weiRaised;
|
||||
|
||||
/**
|
||||
* Event for token purchase logging
|
||||
* @param purchaser who paid for the tokens
|
||||
* @param beneficiary who got the tokens
|
||||
* @param value weis paid for purchase
|
||||
* @param amount amount of tokens purchased
|
||||
*/
|
||||
event TokensPurchased(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
|
||||
|
||||
/**
|
||||
* @param rate Number of token units a buyer gets per wei
|
||||
* @dev The rate is the conversion between wei and the smallest and indivisible
|
||||
* token unit. So, if you are using a rate of 1 with a ERC20Detailed token
|
||||
* with 3 decimals called TOK, 1 wei will give you 1 unit, or 0.001 TOK.
|
||||
* @param wallet Address where collected funds will be forwarded to
|
||||
* @param token Address of the token being sold
|
||||
*/
|
||||
constructor (uint256 rate, address payable wallet, IERC20 token) public {
|
||||
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;
|
||||
_token = token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev fallback function ***DO NOT OVERRIDE***
|
||||
* Note that other contracts will transfer funds with a base gas stipend
|
||||
* of 2300, which is not enough to call buyTokens. Consider calling
|
||||
* buyTokens directly when purchasing tokens from a contract.
|
||||
*/
|
||||
function () external payable {
|
||||
buyTokens(_msgSender());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the token being sold.
|
||||
*/
|
||||
function token() public view returns (IERC20) {
|
||||
return _token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the address where funds are collected.
|
||||
*/
|
||||
function wallet() public view returns (address payable) {
|
||||
return _wallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of token units a buyer gets per wei.
|
||||
*/
|
||||
function rate() public view returns (uint256) {
|
||||
return _rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the amount of wei raised.
|
||||
*/
|
||||
function weiRaised() public view returns (uint256) {
|
||||
return _weiRaised;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev low level token purchase ***DO NOT OVERRIDE***
|
||||
* This function has a non-reentrancy guard, so it shouldn't be called by
|
||||
* another `nonReentrant` function.
|
||||
* @param beneficiary Recipient of the token purchase
|
||||
*/
|
||||
function buyTokens(address beneficiary) public nonReentrant payable {
|
||||
uint256 weiAmount = msg.value;
|
||||
_preValidatePurchase(beneficiary, weiAmount);
|
||||
|
||||
// calculate token amount to be created
|
||||
uint256 tokens = _getTokenAmount(weiAmount);
|
||||
|
||||
// update state
|
||||
_weiRaised = _weiRaised.add(weiAmount);
|
||||
|
||||
_processPurchase(beneficiary, tokens);
|
||||
emit TokensPurchased(_msgSender(), beneficiary, weiAmount, tokens);
|
||||
|
||||
_updatePurchasingState(beneficiary, weiAmount);
|
||||
|
||||
_forwardFunds();
|
||||
_postValidatePurchase(beneficiary, weiAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met.
|
||||
* Use `super` in contracts that inherit from Crowdsale to extend their validations.
|
||||
* Example from CappedCrowdsale.sol's _preValidatePurchase method:
|
||||
* super._preValidatePurchase(beneficiary, weiAmount);
|
||||
* require(weiRaised().add(weiAmount) <= cap);
|
||||
* @param beneficiary Address performing the token purchase
|
||||
* @param weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
require(beneficiary != address(0), "Crowdsale: beneficiary is the zero address");
|
||||
require(weiAmount != 0, "Crowdsale: weiAmount is 0");
|
||||
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid
|
||||
* conditions are not met.
|
||||
* @param beneficiary Address performing the token purchase
|
||||
* @param weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _postValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends
|
||||
* its tokens.
|
||||
* @param beneficiary Address performing the token purchase
|
||||
* @param tokenAmount Number of tokens to be emitted
|
||||
*/
|
||||
function _deliverTokens(address beneficiary, uint256 tokenAmount) internal {
|
||||
_token.safeTransfer(beneficiary, tokenAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send
|
||||
* tokens.
|
||||
* @param beneficiary Address receiving the tokens
|
||||
* @param tokenAmount Number of tokens to be purchased
|
||||
*/
|
||||
function _processPurchase(address beneficiary, uint256 tokenAmount) internal {
|
||||
_deliverTokens(beneficiary, tokenAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Override for extensions that require an internal state to check for validity (current user contributions,
|
||||
* etc.)
|
||||
* @param beneficiary Address receiving the tokens
|
||||
* @param weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _updatePurchasingState(address beneficiary, uint256 weiAmount) internal {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Override to extend the way in which ether is converted to tokens.
|
||||
* @param weiAmount Value in wei to be converted into tokens
|
||||
* @return Number of tokens that can be purchased with the specified _weiAmount
|
||||
*/
|
||||
function _getTokenAmount(uint256 weiAmount) internal view returns (uint256) {
|
||||
return weiAmount.mul(_rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Determines how ETH is stored/forwarded on purchases.
|
||||
*/
|
||||
function _forwardFunds() internal {
|
||||
_wallet.transfer(msg.value);
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
= Crowdsales
|
||||
|
||||
NOTE: This page is incomplete. We're working to improve it for the next release. Stay tuned!
|
||||
|
||||
== Core
|
||||
|
||||
{{Crowdsale}}
|
||||
|
||||
== Emission
|
||||
|
||||
{{AllowanceCrowdsale}}
|
||||
|
||||
{{MintedCrowdsale}}
|
||||
|
||||
== Validation
|
||||
|
||||
{{CappedCrowdsale}}
|
||||
|
||||
{{IndividuallyCappedCrowdsale}}
|
||||
|
||||
{{PausableCrowdsale}}
|
||||
|
||||
{{TimedCrowdsale}}
|
||||
|
||||
{{WhitelistCrowdsale}}
|
||||
|
||||
== Distribution
|
||||
|
||||
{{FinalizableCrowdsale}}
|
||||
|
||||
{{PostDeliveryCrowdsale}}
|
||||
|
||||
{{RefundableCrowdsale}}
|
||||
|
||||
{{RefundablePostDeliveryCrowdsale}}
|
||||
@ -1,51 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
|
||||
/**
|
||||
* @title FinalizableCrowdsale
|
||||
* @dev Extension of TimedCrowdsale with a one-off finalization action, where one
|
||||
* can do extra work after finishing.
|
||||
*/
|
||||
contract FinalizableCrowdsale is TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
bool private _finalized;
|
||||
|
||||
event CrowdsaleFinalized();
|
||||
|
||||
constructor () internal {
|
||||
_finalized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the crowdsale is finalized, false otherwise.
|
||||
*/
|
||||
function finalized() public view returns (bool) {
|
||||
return _finalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Must be called after crowdsale ends, to do some extra finalization
|
||||
* work. Calls the contract's finalization function.
|
||||
*/
|
||||
function finalize() public {
|
||||
require(!_finalized, "FinalizableCrowdsale: already finalized");
|
||||
require(hasClosed(), "FinalizableCrowdsale: not closed");
|
||||
|
||||
_finalized = true;
|
||||
|
||||
_finalization();
|
||||
emit CrowdsaleFinalized();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Can be overridden to add finalization logic. The overriding function
|
||||
* should call super._finalization() to ensure the chain of finalization is
|
||||
* executed entirely.
|
||||
*/
|
||||
function _finalization() internal {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../../ownership/Secondary.sol";
|
||||
import "../../token/ERC20/IERC20.sol";
|
||||
|
||||
/**
|
||||
* @title PostDeliveryCrowdsale
|
||||
* @dev Crowdsale that locks tokens from withdrawal until it ends.
|
||||
*/
|
||||
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(), "PostDeliveryCrowdsale: not closed");
|
||||
uint256 amount = _balances[beneficiary];
|
||||
require(amount > 0, "PostDeliveryCrowdsale: beneficiary is not due any tokens");
|
||||
|
||||
_balances[beneficiary] = 0;
|
||||
_vault.transfer(token(), beneficiary, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the balance of an account.
|
||||
*/
|
||||
function balanceOf(address account) public view returns (uint256) {
|
||||
return _balances[account];
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,83 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../GSN/Context.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "./FinalizableCrowdsale.sol";
|
||||
import "../../payment/escrow/RefundEscrow.sol";
|
||||
|
||||
/**
|
||||
* @title RefundableCrowdsale
|
||||
* @dev Extension of `FinalizableCrowdsale` contract that adds a funding goal, and the possibility of users
|
||||
* getting a refund if goal is not met.
|
||||
*
|
||||
* Deprecated, use `RefundablePostDeliveryCrowdsale` instead. Note that if you allow tokens to be traded before the goal
|
||||
* is met, then an attack is possible in which the attacker purchases tokens from the crowdsale and when they sees that
|
||||
* the goal is unlikely to be met, they sell their tokens (possibly at a discount). The attacker will be refunded when
|
||||
* the crowdsale is finalized, and the users that purchased from them will be left with worthless tokens.
|
||||
*/
|
||||
contract RefundableCrowdsale is Context, FinalizableCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
// minimum amount of funds to be raised in weis
|
||||
uint256 private _goal;
|
||||
|
||||
// refund escrow used to hold funds while crowdsale is running
|
||||
RefundEscrow private _escrow;
|
||||
|
||||
/**
|
||||
* @dev Constructor, creates RefundEscrow.
|
||||
* @param goal Funding goal
|
||||
*/
|
||||
constructor (uint256 goal) public {
|
||||
require(goal > 0, "RefundableCrowdsale: goal is 0");
|
||||
_escrow = new RefundEscrow(wallet());
|
||||
_goal = goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return minimum amount of funds to be raised in wei.
|
||||
*/
|
||||
function goal() public view returns (uint256) {
|
||||
return _goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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(), "RefundableCrowdsale: not finalized");
|
||||
require(!goalReached(), "RefundableCrowdsale: goal reached");
|
||||
|
||||
_escrow.withdraw(refundee);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether funding goal was reached.
|
||||
* @return Whether funding goal was reached
|
||||
*/
|
||||
function goalReached() public view returns (bool) {
|
||||
return weiRaised() >= _goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Escrow finalization task, called when finalize() is called.
|
||||
*/
|
||||
function _finalization() internal {
|
||||
if (goalReached()) {
|
||||
_escrow.close();
|
||||
_escrow.beneficiaryWithdraw();
|
||||
} else {
|
||||
_escrow.enableRefunds();
|
||||
}
|
||||
|
||||
super._finalization();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides Crowdsale fund forwarding, sending funds to escrow.
|
||||
*/
|
||||
function _forwardFunds() internal {
|
||||
_escrow.deposit.value(msg.value)(_msgSender());
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "./RefundableCrowdsale.sol";
|
||||
import "./PostDeliveryCrowdsale.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title RefundablePostDeliveryCrowdsale
|
||||
* @dev Extension of RefundableCrowdsale contract that only delivers the tokens
|
||||
* once the crowdsale has closed and the goal met, preventing refunds to be issued
|
||||
* to token holders.
|
||||
*/
|
||||
contract RefundablePostDeliveryCrowdsale is RefundableCrowdsale, PostDeliveryCrowdsale {
|
||||
function withdrawTokens(address beneficiary) public {
|
||||
require(finalized(), "RefundablePostDeliveryCrowdsale: not finalized");
|
||||
require(goalReached(), "RefundablePostDeliveryCrowdsale: goal not reached");
|
||||
|
||||
super.withdrawTokens(beneficiary);
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/IERC20.sol";
|
||||
import "../../token/ERC20/SafeERC20.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../../math/Math.sol";
|
||||
|
||||
/**
|
||||
* @title AllowanceCrowdsale
|
||||
* @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale.
|
||||
*/
|
||||
contract AllowanceCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
address private _tokenWallet;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes token wallet address.
|
||||
* @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale.
|
||||
*/
|
||||
constructor (address tokenWallet) public {
|
||||
require(tokenWallet != address(0), "AllowanceCrowdsale: token wallet is the zero address");
|
||||
_tokenWallet = tokenWallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the address of the wallet that will hold the tokens.
|
||||
*/
|
||||
function tokenWallet() public view returns (address) {
|
||||
return _tokenWallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks the amount of tokens left in the allowance.
|
||||
* @return Amount of tokens left in the allowance
|
||||
*/
|
||||
function remainingTokens() public view returns (uint256) {
|
||||
return Math.min(token().balanceOf(_tokenWallet), token().allowance(_tokenWallet, address(this)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent behavior by transferring tokens from wallet.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param tokenAmount Amount of tokens purchased
|
||||
*/
|
||||
function _deliverTokens(address beneficiary, uint256 tokenAmount) internal {
|
||||
token().safeTransferFrom(_tokenWallet, beneficiary, tokenAmount);
|
||||
}
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/ERC20Mintable.sol";
|
||||
|
||||
/**
|
||||
* @title MintedCrowdsale
|
||||
* @dev Extension of Crowdsale contract whose tokens are minted in each purchase.
|
||||
* Token ownership should be transferred to MintedCrowdsale for minting.
|
||||
*/
|
||||
contract MintedCrowdsale is Crowdsale {
|
||||
/**
|
||||
* @dev Overrides delivery by minting tokens upon purchase.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param tokenAmount Number of tokens to be minted
|
||||
*/
|
||||
function _deliverTokens(address beneficiary, uint256 tokenAmount) internal {
|
||||
// Potentially dangerous assumption about the type of the token.
|
||||
require(
|
||||
ERC20Mintable(address(token())).mint(beneficiary, tokenAmount),
|
||||
"MintedCrowdsale: minting failed"
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
/**
|
||||
* @title IncreasingPriceCrowdsale
|
||||
* @dev Extension of Crowdsale contract that increases the price of tokens linearly in time.
|
||||
* Note that what should be provided to the constructor is the initial and final _rates_, that is,
|
||||
* the amount of tokens per wei contributed. Thus, the initial rate must be greater than the final rate.
|
||||
*/
|
||||
contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 private _initialRate;
|
||||
uint256 private _finalRate;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes initial and final rates of tokens received per wei contributed.
|
||||
* @param initialRate Number of tokens a buyer gets per wei at the start of the crowdsale
|
||||
* @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale
|
||||
*/
|
||||
constructor (uint256 initialRate, uint256 finalRate) public {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* The base rate function is overridden to revert, since this crowdsale doesn't use it, and
|
||||
* all calls to it are a mistake.
|
||||
*/
|
||||
function rate() public view returns (uint256) {
|
||||
revert("IncreasingPriceCrowdsale: rate() called");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the initial rate of the crowdsale.
|
||||
*/
|
||||
function initialRate() public view returns (uint256) {
|
||||
return _initialRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the final rate of the crowdsale.
|
||||
*/
|
||||
function finalRate() public view returns (uint256) {
|
||||
return _finalRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the rate of tokens per wei at the present time.
|
||||
* Note that, as price _increases_ with time, the rate _decreases_.
|
||||
* @return The number of tokens a buyer gets per wei at a given time
|
||||
*/
|
||||
function getCurrentRate() public view returns (uint256) {
|
||||
if (!isOpen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
uint256 elapsedTime = block.timestamp.sub(openingTime());
|
||||
uint256 timeRange = closingTime().sub(openingTime());
|
||||
uint256 rateRange = _initialRate.sub(_finalRate);
|
||||
return _initialRate.sub(elapsedTime.mul(rateRange).div(timeRange));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent method taking into account variable rate.
|
||||
* @param weiAmount The value in wei to be converted into tokens
|
||||
* @return The number of tokens _weiAmount wei will buy at present time
|
||||
*/
|
||||
function _getTokenAmount(uint256 weiAmount) internal view returns (uint256) {
|
||||
uint256 currentRate = getCurrentRate();
|
||||
return currentRate.mul(weiAmount);
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
|
||||
/**
|
||||
* @title CappedCrowdsale
|
||||
* @dev Crowdsale with a limit for total contributions.
|
||||
*/
|
||||
contract CappedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 private _cap;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes maximum amount of wei accepted in the crowdsale.
|
||||
* @param cap Max amount of wei to be contributed
|
||||
*/
|
||||
constructor (uint256 cap) public {
|
||||
require(cap > 0, "CappedCrowdsale: cap is 0");
|
||||
_cap = cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cap of the crowdsale.
|
||||
*/
|
||||
function cap() public view returns (uint256) {
|
||||
return _cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether the cap has been reached.
|
||||
* @return Whether the cap was reached
|
||||
*/
|
||||
function capReached() public view returns (bool) {
|
||||
return weiRaised() >= _cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring purchase to respect the funding cap.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
require(weiRaised().add(weiAmount) <= _cap, "CappedCrowdsale: cap exceeded");
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
import "../../access/roles/CapperRole.sol";
|
||||
|
||||
/**
|
||||
* @title IndividuallyCappedCrowdsale
|
||||
* @dev Crowdsale with per-beneficiary caps.
|
||||
*/
|
||||
contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping(address => uint256) private _contributions;
|
||||
mapping(address => uint256) private _caps;
|
||||
|
||||
/**
|
||||
* @dev Sets a specific beneficiary's maximum contribution.
|
||||
* @param beneficiary Address to be capped
|
||||
* @param cap Wei limit for individual contribution
|
||||
*/
|
||||
function setCap(address beneficiary, uint256 cap) external onlyCapper {
|
||||
_caps[beneficiary] = cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the cap of a specific beneficiary.
|
||||
* @param beneficiary Address whose cap is to be checked
|
||||
* @return Current cap for individual beneficiary
|
||||
*/
|
||||
function getCap(address beneficiary) public view returns (uint256) {
|
||||
return _caps[beneficiary];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the amount contributed so far by a specific beneficiary.
|
||||
* @param beneficiary Address of contributor
|
||||
* @return Beneficiary contribution so far
|
||||
*/
|
||||
function getContribution(address beneficiary) public view returns (uint256) {
|
||||
return _contributions[beneficiary];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring purchase to respect the beneficiary's funding cap.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
// 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.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _updatePurchasingState(address beneficiary, uint256 weiAmount) internal {
|
||||
super._updatePurchasingState(beneficiary, weiAmount);
|
||||
_contributions[beneficiary] = _contributions[beneficiary].add(weiAmount);
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../lifecycle/Pausable.sol";
|
||||
|
||||
/**
|
||||
* @title PausableCrowdsale
|
||||
* @dev Extension of Crowdsale contract where purchases can be paused and unpaused by the pauser role.
|
||||
*/
|
||||
contract PausableCrowdsale is Crowdsale, Pausable {
|
||||
/**
|
||||
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met.
|
||||
* Use super to concatenate validations.
|
||||
* Adds the validation that the crowdsale must not be paused.
|
||||
* @param _beneficiary Address performing the token purchase
|
||||
* @param _weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal view whenNotPaused {
|
||||
return super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
}
|
||||
@ -1,98 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
|
||||
/**
|
||||
* @title TimedCrowdsale
|
||||
* @dev Crowdsale accepting contributions only within a time frame.
|
||||
*/
|
||||
contract TimedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 private _openingTime;
|
||||
uint256 private _closingTime;
|
||||
|
||||
/**
|
||||
* Event for crowdsale extending
|
||||
* @param newClosingTime new closing time
|
||||
* @param prevClosingTime old closing time
|
||||
*/
|
||||
event TimedCrowdsaleExtended(uint256 prevClosingTime, uint256 newClosingTime);
|
||||
|
||||
/**
|
||||
* @dev Reverts if not in crowdsale time range.
|
||||
*/
|
||||
modifier onlyWhileOpen {
|
||||
require(isOpen(), "TimedCrowdsale: not open");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes crowdsale opening and closing times.
|
||||
* @param openingTime Crowdsale opening time
|
||||
* @param closingTime Crowdsale closing time
|
||||
*/
|
||||
constructor (uint256 openingTime, uint256 closingTime) public {
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the crowdsale opening time.
|
||||
*/
|
||||
function openingTime() public view returns (uint256) {
|
||||
return _openingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the crowdsale closing time.
|
||||
*/
|
||||
function closingTime() public view returns (uint256) {
|
||||
return _closingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the crowdsale is open, false otherwise.
|
||||
*/
|
||||
function isOpen() public view returns (bool) {
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
return block.timestamp >= _openingTime && block.timestamp <= _closingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether the period in which the crowdsale is open has already elapsed.
|
||||
* @return Whether crowdsale period has elapsed
|
||||
*/
|
||||
function hasClosed() public view returns (bool) {
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
return block.timestamp > _closingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring to be within contributing period.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal onlyWhileOpen view {
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend crowdsale.
|
||||
* @param newClosingTime Crowdsale closing time
|
||||
*/
|
||||
function _extendTime(uint256 newClosingTime) internal {
|
||||
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,21 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
import "../Crowdsale.sol";
|
||||
import "../../access/roles/WhitelistedRole.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title WhitelistCrowdsale
|
||||
* @dev Crowdsale in which only whitelisted users can contribute.
|
||||
*/
|
||||
contract WhitelistCrowdsale is WhitelistedRole, Crowdsale {
|
||||
/**
|
||||
* @dev Extend parent behavior requiring beneficiary to be whitelisted. Note that no
|
||||
* restriction is imposed on the account sending the transaction.
|
||||
* @param _beneficiary Token beneficiary
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal view {
|
||||
require(isWhitelisted(_beneficiary), "WhitelistCrowdsale: beneficiary doesn't have the Whitelisted role");
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
|
||||
@ -15,10 +15,6 @@ library ECDSA {
|
||||
* this function rejects them by requiring the `s` value to be in the lower
|
||||
* half order, and the `v` value to be either 27 or 28.
|
||||
*
|
||||
* NOTE: This call _does not revert_ if the signature is invalid, or
|
||||
* if the signer is otherwise unable to be retrieved. In those scenarios,
|
||||
* the zero address is returned.
|
||||
*
|
||||
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
|
||||
* verification to be secure: it is possible to craft signatures that
|
||||
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
|
||||
@ -28,7 +24,7 @@ library ECDSA {
|
||||
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
|
||||
// Check the signature length
|
||||
if (signature.length != 65) {
|
||||
return (address(0));
|
||||
revert("ECDSA: invalid signature length");
|
||||
}
|
||||
|
||||
// Divide the signature in r, s and v variables
|
||||
@ -55,15 +51,18 @@ library ECDSA {
|
||||
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
|
||||
// these malleable signatures as well.
|
||||
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
|
||||
return address(0);
|
||||
revert("ECDSA: invalid signature 's' value");
|
||||
}
|
||||
|
||||
if (v != 27 && v != 28) {
|
||||
return address(0);
|
||||
revert("ECDSA: invalid signature 'v' value");
|
||||
}
|
||||
|
||||
// If the signature is valid (and not malleable), return the signer address
|
||||
return ecrecover(hash, v, r, s);
|
||||
address signer = ecrecover(hash, v, r, s);
|
||||
require(signer != address(0), "ECDSA: invalid signature");
|
||||
|
||||
return signer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @dev These functions deal with verification of Merkle trees (hash trees),
|
||||
|
||||
85
contracts/deploy-ready/ERC20MinterPauser.sol
Normal file
85
contracts/deploy-ready/ERC20MinterPauser.sol
Normal file
@ -0,0 +1,85 @@
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../access/AccessControl.sol";
|
||||
import "../GSN/Context.sol";
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/ERC20Burnable.sol";
|
||||
import "../token/ERC20/ERC20Pausable.sol";
|
||||
|
||||
/**
|
||||
* @dev {ERC20} token, including:
|
||||
*
|
||||
* - ability for holders to burn (destroy) their tokens
|
||||
* - a minter role that allows for token minting (creation)
|
||||
* - a pauser role that allows to stop all token transfers
|
||||
*
|
||||
* This contract uses {AccessControl} to lock permissioned functions using the
|
||||
* different roles - head to its documentation for details.
|
||||
*
|
||||
* The account that deploys the contract will be granted the minter role, the
|
||||
* pauser role, and the default admin role, meaning it will be able to grant
|
||||
* both the minter and pauser roles.
|
||||
*/
|
||||
contract ERC20MinterPauser is Context, AccessControl, ERC20Burnable, ERC20Pausable {
|
||||
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
|
||||
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
|
||||
|
||||
/**
|
||||
* @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
|
||||
* account that deploys the contract.
|
||||
*
|
||||
* See {ERC20-constructor}.
|
||||
*/
|
||||
constructor(string memory name, string memory symbol) public ERC20(name, symbol) {
|
||||
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
|
||||
|
||||
_setupRole(MINTER_ROLE, _msgSender());
|
||||
_setupRole(PAUSER_ROLE, _msgSender());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Creates `amount` new tokens for `to`.
|
||||
*
|
||||
* See {ERC20-_mint}.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must have the `MINTER_ROLE`.
|
||||
*/
|
||||
function mint(address to, uint256 amount) public {
|
||||
require(hasRole(MINTER_ROLE, _msgSender()), "ERC20MinterPauser: must have minter role to mint");
|
||||
_mint(to, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Pauses all token transfers.
|
||||
*
|
||||
* See {ERC20Pausable} and {Pausable-_pause}.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must have the `PAUSER_ROLE`.
|
||||
*/
|
||||
function pause() public {
|
||||
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20MinterPauser: must have pauser role to pause");
|
||||
_pause();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Unpauses all token transfers.
|
||||
*
|
||||
* See {ERC20Pausable} and {Pausable-_unpause}.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must have the `PAUSER_ROLE`.
|
||||
*/
|
||||
function unpause() public {
|
||||
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20MinterPauser: must have pauser role to unpause");
|
||||
_unpause();
|
||||
}
|
||||
|
||||
function _beforeTokenTransfer(address from, address to, uint256 amount) internal override(ERC20, ERC20Pausable) {
|
||||
super._beforeTokenTransfer(from, to, amount);
|
||||
}
|
||||
}
|
||||
85
contracts/deploy-ready/ERC721MinterPauser.sol
Normal file
85
contracts/deploy-ready/ERC721MinterPauser.sol
Normal file
@ -0,0 +1,85 @@
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../access/AccessControl.sol";
|
||||
import "../GSN/Context.sol";
|
||||
import "../token/ERC721/ERC721.sol";
|
||||
import "../token/ERC721/ERC721Burnable.sol";
|
||||
import "../token/ERC721/ERC721Pausable.sol";
|
||||
|
||||
/**
|
||||
* @dev {ERC721} token, including:
|
||||
*
|
||||
* - ability for holders to burn (destroy) their tokens
|
||||
* - a minter role that allows for token minting (creation)
|
||||
* - a pauser role that allows to stop all token transfers
|
||||
*
|
||||
* This contract uses {AccessControl} to lock permissioned functions using the
|
||||
* different roles - head to its documentation for details.
|
||||
*
|
||||
* The account that deploys the contract will be granted the minter role, the
|
||||
* pauser role, and the default admin role, meaning it will be able to grant
|
||||
* both the minter and pauser roles.
|
||||
*/
|
||||
contract ERC721MinterPauser is Context, AccessControl, ERC721Burnable, ERC721Pausable {
|
||||
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
|
||||
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
|
||||
|
||||
/**
|
||||
* @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
|
||||
* account that deploys the contract.
|
||||
*
|
||||
* See {ERC721-constructor}.
|
||||
*/
|
||||
constructor(string memory name, string memory symbol) public ERC721(name, symbol) {
|
||||
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
|
||||
|
||||
_setupRole(MINTER_ROLE, _msgSender());
|
||||
_setupRole(PAUSER_ROLE, _msgSender());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Creates the `tokenId` tokens for `to`.
|
||||
*
|
||||
* See {ERC721-_mint}.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must have the `MINTER_ROLE`.
|
||||
*/
|
||||
function mint(address to, uint256 tokenId) public {
|
||||
require(hasRole(MINTER_ROLE, _msgSender()), "ERC721MinterPauser: must have minter role to mint");
|
||||
_mint(to, tokenId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Pauses all token transfers.
|
||||
*
|
||||
* See {ERC721Pausable} and {Pausable-_pause}.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must have the `PAUSER_ROLE`.
|
||||
*/
|
||||
function pause() public {
|
||||
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721MinterPauser: must have pauser role to pause");
|
||||
_pause();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Unpauses all token transfers.
|
||||
*
|
||||
* See {ERC20Pausable} and {Pausable-_unpause}.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must have the `PAUSER_ROLE`.
|
||||
*/
|
||||
function unpause() public {
|
||||
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721MinterPauser: must have pauser role to unpause");
|
||||
_unpause();
|
||||
}
|
||||
|
||||
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721Pausable) {
|
||||
super._beforeTokenTransfer(from, to, tokenId);
|
||||
}
|
||||
}
|
||||
13
contracts/deploy-ready/README.adoc
Normal file
13
contracts/deploy-ready/README.adoc
Normal file
@ -0,0 +1,13 @@
|
||||
= Deploy Ready
|
||||
|
||||
These contracts integrate different Ethereum standards (ERCs) with custom extensions and modules, showcasing common configurations that are ready to deploy **without having to write any Solidity code**.
|
||||
|
||||
They can be used as-is for quick prototyping and testing, but are **also suitable for production environments**.
|
||||
|
||||
TIP: Intermediate and advanced users can use these as starting points when writing their own contracts, extending them with custom functionality as they see fit.
|
||||
|
||||
== Tokens
|
||||
|
||||
{{ERC20MinterPauser}}
|
||||
|
||||
{{ERC721MinterPauser}}
|
||||
@ -1,24 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../../token/ERC20/IERC20.sol";
|
||||
|
||||
/**
|
||||
* @title ERC-1047 Token Metadata
|
||||
* @dev See https://eips.ethereum.org/EIPS/eip-1046
|
||||
* @dev {tokenURI} must respond with a URI that implements https://eips.ethereum.org/EIPS/eip-1047
|
||||
*/
|
||||
contract ERC20Metadata {
|
||||
string private _tokenURI;
|
||||
|
||||
constructor (string memory tokenURI_) public {
|
||||
_setTokenURI(tokenURI_);
|
||||
}
|
||||
|
||||
function tokenURI() external view returns (string memory) {
|
||||
return _tokenURI;
|
||||
}
|
||||
|
||||
function _setTokenURI(string memory tokenURI_) internal {
|
||||
_tokenURI = tokenURI_;
|
||||
}
|
||||
}
|
||||
@ -1,103 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../token/ERC20/ERC20Mintable.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
import "../math/Math.sol";
|
||||
|
||||
/**
|
||||
* @title ERC20Migrator
|
||||
* @dev This contract can be used to migrate an ERC20 token from one
|
||||
* contract to another, where each token holder has to opt-in to the migration.
|
||||
* To opt-in, users must approve for this contract the number of tokens they
|
||||
* want to migrate. Once the allowance is set up, anyone can trigger the
|
||||
* migration to the new token contract. In this way, token holders "turn in"
|
||||
* their old balance and will be minted an equal amount in the new token.
|
||||
* The new token contract must be mintable. For the precise interface refer to
|
||||
* OpenZeppelin's {ERC20Mintable}, but the only functions that are needed are
|
||||
* {MinterRole-isMinter} and {ERC20Mintable-mint}. The migrator will check
|
||||
* that it is a minter for the token.
|
||||
* The balance from the legacy token will be transferred to the migrator, as it
|
||||
* is migrated, and remain there forever.
|
||||
* Although this contract can be used in many different scenarios, the main
|
||||
* motivation was to provide a way to migrate ERC20 tokens into an upgradeable
|
||||
* version of it using ZeppelinOS. To read more about how this can be done
|
||||
* using this implementation, please follow the official documentation site of
|
||||
* ZeppelinOS: https://docs.zeppelinos.org/docs/erc20_onboarding.html
|
||||
*
|
||||
* Example of usage:
|
||||
* ```
|
||||
* const migrator = await ERC20Migrator.new(legacyToken.address);
|
||||
* await newToken.addMinter(migrator.address);
|
||||
* await migrator.beginMigration(newToken.address);
|
||||
* ```
|
||||
*/
|
||||
contract ERC20Migrator {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
/// Address of the old token contract
|
||||
IERC20 private _legacyToken;
|
||||
|
||||
/// Address of the new token contract
|
||||
ERC20Mintable private _newToken;
|
||||
|
||||
/**
|
||||
* @param legacyToken address of the old token contract
|
||||
*/
|
||||
constructor (IERC20 legacyToken) public {
|
||||
require(address(legacyToken) != address(0), "ERC20Migrator: legacy token is the zero address");
|
||||
_legacyToken = legacyToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the legacy token that is being migrated.
|
||||
*/
|
||||
function legacyToken() public view returns (IERC20) {
|
||||
return _legacyToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the new token to which we are migrating.
|
||||
*/
|
||||
function newToken() public view returns (IERC20) {
|
||||
return _newToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Begins the migration by setting which is the new token that will be
|
||||
* minted. This contract must be a minter for the new token.
|
||||
* @param newToken_ the token that will be minted
|
||||
*/
|
||||
function beginMigration(ERC20Mintable newToken_) public {
|
||||
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_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers part of an account's balance in the old token to this
|
||||
* contract, and mints the same amount of new tokens for that account.
|
||||
* @param account whose tokens will be migrated
|
||||
* @param amount amount of tokens to be migrated
|
||||
*/
|
||||
function migrate(address account, uint256 amount) public {
|
||||
require(address(_newToken) != address(0), "ERC20Migrator: migration not started");
|
||||
_legacyToken.safeTransferFrom(account, address(this), amount);
|
||||
_newToken.mint(account, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers all of an account's allowed balance in the old token to
|
||||
* this contract, and mints the same amount of new tokens for that account.
|
||||
* @param account whose tokens will be migrated
|
||||
*/
|
||||
function migrateAll(address account) public {
|
||||
uint256 balance = _legacyToken.balanceOf(account);
|
||||
uint256 allowance = _legacyToken.allowance(account, address(this));
|
||||
uint256 amount = Math.min(balance, allowance);
|
||||
migrate(account, amount);
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
= Drafts
|
||||
|
||||
Contracts in this category should be considered unstable. They are as thoroughly reviewed as everything else in OpenZeppelin Contracts, but we have doubts about their API so we don't commit to backwards compatibility. This means these contracts can receive breaking changes in a minor version, so you should pay special attention to the changelog when upgrading. For anything that is outside of this category you can read more about xref:ROOT:api-stability.adoc[API Stability].
|
||||
|
||||
NOTE: This page is incomplete. We're working to improve it for the next release. Stay tuned!
|
||||
|
||||
== ERC 20
|
||||
|
||||
{{ERC20Migrator}}
|
||||
|
||||
{{ERC20Snapshot}}
|
||||
|
||||
{{TokenVesting}}
|
||||
|
||||
== Miscellaneous
|
||||
|
||||
{{Counters}}
|
||||
|
||||
{{SignedSafeMath}}
|
||||
|
||||
== ERC 1046
|
||||
|
||||
{{ERC1046}}
|
||||
@ -1,7 +1,7 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../access/Ownable.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
/**
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||
import "../crowdsale/emission/MintedCrowdsale.sol";
|
||||
import "../token/ERC20/ERC20Mintable.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
|
||||
/**
|
||||
* @title SampleCrowdsaleToken
|
||||
* @dev Very simple ERC20 Token that can be minted.
|
||||
* It is meant to be used in a crowdsale contract.
|
||||
*/
|
||||
contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed {
|
||||
constructor () public ERC20Detailed("Sample Crowdsale Token", "SCT", 18) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @title SampleCrowdsale
|
||||
* @dev This is an example of a fully fledged crowdsale.
|
||||
* The way to add new features to a base crowdsale is by multiple inheritance.
|
||||
* In this example we are providing following extensions:
|
||||
* CappedCrowdsale - sets a max boundary for raised funds
|
||||
* RefundableCrowdsale - set a min goal to be reached and returns funds if it's not met
|
||||
* MintedCrowdsale - assumes the token can be minted by the crowdsale, which does so
|
||||
* when receiving purchases.
|
||||
*
|
||||
* After adding multiple features it's good practice to run integration tests
|
||||
* to ensure that subcontracts works together as intended.
|
||||
*/
|
||||
contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsale {
|
||||
constructor (
|
||||
uint256 openingTime,
|
||||
uint256 closingTime,
|
||||
uint256 rate,
|
||||
address payable wallet,
|
||||
uint256 cap,
|
||||
ERC20Mintable token,
|
||||
uint256 goal
|
||||
)
|
||||
public
|
||||
Crowdsale(rate, wallet, token)
|
||||
CappedCrowdsale(cap)
|
||||
TimedCrowdsale(openingTime, closingTime)
|
||||
RefundableCrowdsale(goal)
|
||||
{
|
||||
//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, "SampleCrowdSale: goal is greater than cap");
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
|
||||
/**
|
||||
* @title SimpleToken
|
||||
* @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
|
||||
* Note they can later distribute these tokens as they wish using `transfer` and other
|
||||
* `ERC20` functions.
|
||||
*/
|
||||
contract SimpleToken is Context, ERC20, ERC20Detailed {
|
||||
|
||||
/**
|
||||
* @dev Constructor that gives _msgSender() all of existing tokens.
|
||||
*/
|
||||
constructor () public ERC20Detailed("SimpleToken", "SIM", 18) {
|
||||
_mint(_msgSender(), 10000 * (10 ** uint256(decimals())));
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "./IERC165.sol";
|
||||
|
||||
@ -30,7 +30,7 @@ contract ERC165 is IERC165 {
|
||||
*
|
||||
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
|
||||
*/
|
||||
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
|
||||
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
|
||||
return _supportedInterfaces[interfaceId];
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ contract ERC165 is IERC165 {
|
||||
*
|
||||
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
|
||||
*/
|
||||
function _registerInterface(bytes4 interfaceId) internal {
|
||||
function _registerInterface(bytes4 interfaceId) internal virtual {
|
||||
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
|
||||
_supportedInterfaces[interfaceId] = true;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.10;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @dev Library used to query support of an interface declared via {IERC165}.
|
||||
@ -19,7 +19,7 @@ library ERC165Checker {
|
||||
/**
|
||||
* @dev Returns true if `account` supports the {IERC165} interface,
|
||||
*/
|
||||
function _supportsERC165(address account) internal view returns (bool) {
|
||||
function supportsERC165(address account) internal view returns (bool) {
|
||||
// Any contract that implements ERC165 must explicitly indicate support of
|
||||
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
|
||||
return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) &&
|
||||
@ -32,9 +32,9 @@ library ERC165Checker {
|
||||
*
|
||||
* See {IERC165-supportsInterface}.
|
||||
*/
|
||||
function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
|
||||
function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
|
||||
// query support of both ERC165 as per the spec and support of _interfaceId
|
||||
return _supportsERC165(account) &&
|
||||
return supportsERC165(account) &&
|
||||
_supportsERC165Interface(account, interfaceId);
|
||||
}
|
||||
|
||||
@ -47,9 +47,9 @@ library ERC165Checker {
|
||||
*
|
||||
* See {IERC165-supportsInterface}.
|
||||
*/
|
||||
function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
|
||||
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
|
||||
// query support of ERC165 itself
|
||||
if (!_supportsERC165(account)) {
|
||||
if (!supportsERC165(account)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ library ERC165Checker {
|
||||
* identifier interfaceId, false otherwise
|
||||
* @dev Assumes that account contains a contract that supports ERC165, otherwise
|
||||
* the behavior of this method is undefined. This precondition can be checked
|
||||
* with the `supportsERC165` method in this library.
|
||||
* with {supportsERC165}.
|
||||
* Interface identification is specified in ERC-165.
|
||||
*/
|
||||
function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "./IERC1820Implementer.sol";
|
||||
|
||||
@ -11,15 +11,15 @@ import "./IERC1820Implementer.sol";
|
||||
* registration to be complete.
|
||||
*/
|
||||
contract ERC1820Implementer is IERC1820Implementer {
|
||||
bytes32 constant private ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"));
|
||||
bytes32 constant private _ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"));
|
||||
|
||||
mapping(bytes32 => mapping(address => bool)) private _supportedInterfaces;
|
||||
|
||||
/**
|
||||
* See {IERC1820Implementer-canImplementInterfaceForAddress}.
|
||||
*/
|
||||
function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32) {
|
||||
return _supportedInterfaces[interfaceHash][account] ? ERC1820_ACCEPT_MAGIC : bytes32(0x00);
|
||||
function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) public view override returns (bytes32) {
|
||||
return _supportedInterfaces[interfaceHash][account] ? _ERC1820_ACCEPT_MAGIC : bytes32(0x00);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -29,7 +29,7 @@ contract ERC1820Implementer is IERC1820Implementer {
|
||||
* See {IERC1820Registry-setInterfaceImplementer} and
|
||||
* {IERC1820Registry-interfaceHash}.
|
||||
*/
|
||||
function _registerInterfaceForAddress(bytes32 interfaceHash, address account) internal {
|
||||
function _registerInterfaceForAddress(bytes32 interfaceHash, address account) internal virtual {
|
||||
_supportedInterfaces[interfaceHash][account] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @dev Interface of the ERC165 standard, as defined in the
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @dev Interface for an ERC1820 implementer, as defined in the
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @dev Interface of the global ERC1820 Registry, as defined in the
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
= Introspection
|
||||
|
||||
This set of interfaces and contracts deal with [type introspection](https://en.wikipedia.org/wiki/Type_introspection) of contracts, that is, examining which functions can be called on them. This is usually referred to as a contract's _interface_.
|
||||
This set of interfaces and contracts deal with https://en.wikipedia.org/wiki/Type_introspection[type introspection] of contracts, that is, examining which functions can be called on them. This is usually referred to as a contract's _interface_.
|
||||
|
||||
Ethereum contracts have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. `ERC20` tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract _declaring_ its interface can be very helpful in preventing errors.
|
||||
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
= Lifecycle
|
||||
|
||||
== Pausable
|
||||
|
||||
{{Pausable}}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @dev Standard math utilities missing in the Solidity language.
|
||||
|
||||
@ -6,4 +6,6 @@ These are math-related utilities.
|
||||
|
||||
{{SafeMath}}
|
||||
|
||||
{{SignedSafeMath}}
|
||||
|
||||
{{Math}}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @dev Wrappers over Solidity's arithmetic operations with added overflow
|
||||
@ -51,8 +51,6 @@ library SafeMath {
|
||||
*
|
||||
* Requirements:
|
||||
* - Subtraction cannot overflow.
|
||||
*
|
||||
* _Available since v2.4.0._
|
||||
*/
|
||||
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
|
||||
require(b <= a, errorMessage);
|
||||
@ -109,8 +107,6 @@ library SafeMath {
|
||||
*
|
||||
* Requirements:
|
||||
* - The divisor cannot be zero.
|
||||
*
|
||||
* _Available since v2.4.0._
|
||||
*/
|
||||
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
|
||||
// Solidity only automatically asserts when dividing by 0
|
||||
@ -146,8 +142,6 @@ library SafeMath {
|
||||
*
|
||||
* Requirements:
|
||||
* - The divisor cannot be zero.
|
||||
*
|
||||
* _Available since v2.4.0._
|
||||
*/
|
||||
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
|
||||
require(b != 0, errorMessage);
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
/**
|
||||
* @title SignedSafeMath
|
||||
* @dev Signed math operations with safety checks that revert on error.
|
||||
*/
|
||||
library SignedSafeMath {
|
||||
int256 constant private INT256_MIN = -2**255;
|
||||
int256 constant private _INT256_MIN = -2**255;
|
||||
|
||||
/**
|
||||
* @dev Multiplies two signed integers, reverts on overflow.
|
||||
@ -18,7 +18,7 @@ library SignedSafeMath {
|
||||
return 0;
|
||||
}
|
||||
|
||||
require(!(a == -1 && b == INT256_MIN), "SignedSafeMath: multiplication overflow");
|
||||
require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");
|
||||
|
||||
int256 c = a * b;
|
||||
require(c / a == b, "SignedSafeMath: multiplication overflow");
|
||||
@ -31,7 +31,7 @@ library SignedSafeMath {
|
||||
*/
|
||||
function div(int256 a, int256 b) internal pure returns (int256) {
|
||||
require(b != 0, "SignedSafeMath: division by zero");
|
||||
require(!(b == -1 && a == INT256_MIN), "SignedSafeMath: division overflow");
|
||||
require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");
|
||||
|
||||
int256 c = a / b;
|
||||
|
||||
17
contracts/mocks/AccessControlMock.sol
Normal file
17
contracts/mocks/AccessControlMock.sol
Normal file
@ -0,0 +1,17 @@
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../access/AccessControl.sol";
|
||||
|
||||
contract AccessControlMock is AccessControl {
|
||||
constructor() public {
|
||||
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
|
||||
}
|
||||
|
||||
function setRoleAdmin(bytes32 roleId, bytes32 adminRoleId) public {
|
||||
_setRoleAdmin(roleId, adminRoleId);
|
||||
}
|
||||
|
||||
function setupRole(bytes32 roleId, address account) public {
|
||||
_setupRole(roleId, account);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../utils/Address.sol";
|
||||
|
||||
@ -7,13 +7,10 @@ contract AddressImpl {
|
||||
return Address.isContract(account);
|
||||
}
|
||||
|
||||
function toPayable(address account) external pure returns (address payable) {
|
||||
return Address.toPayable(account);
|
||||
}
|
||||
|
||||
function sendValue(address payable receiver, uint256 amount) external {
|
||||
Address.sendValue(receiver, amount);
|
||||
}
|
||||
|
||||
function () external payable { } // sendValue's tests require the contract to hold Ether
|
||||
// sendValue's tests require the contract to hold Ether
|
||||
receive () external payable { }
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../crowdsale/emission/AllowanceCrowdsale.sol";
|
||||
|
||||
contract AllowanceCrowdsaleImpl is AllowanceCrowdsale {
|
||||
constructor (uint256 rate, address payable wallet, IERC20 token, address tokenWallet)
|
||||
public
|
||||
Crowdsale(rate, wallet, token)
|
||||
AllowanceCrowdsale(tokenWallet)
|
||||
{
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,17 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../utils/Arrays.sol";
|
||||
|
||||
contract ArraysImpl {
|
||||
using Arrays for uint256[];
|
||||
|
||||
uint256[] private array;
|
||||
uint256[] private _array;
|
||||
|
||||
constructor (uint256[] memory _array) public {
|
||||
array = _array;
|
||||
constructor (uint256[] memory array) public {
|
||||
_array = array;
|
||||
}
|
||||
|
||||
function findUpperBound(uint256 _element) external view returns (uint256) {
|
||||
return array.findUpperBound(_element);
|
||||
function findUpperBound(uint256 element) external view returns (uint256) {
|
||||
return _array.findUpperBound(element);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
|
||||
contract CappedCrowdsaleImpl is CappedCrowdsale {
|
||||
constructor (uint256 rate, address payable wallet, IERC20 token, uint256 cap)
|
||||
public
|
||||
Crowdsale(rate, wallet, token)
|
||||
CappedCrowdsale(cap)
|
||||
{
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../access/roles/CapperRole.sol";
|
||||
|
||||
contract CapperRoleMock is CapperRole {
|
||||
function removeCapper(address account) public {
|
||||
_removeCapper(account);
|
||||
}
|
||||
|
||||
function onlyCapperMock() public view onlyCapper {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
// Causes a compilation error if super._removeCapper is not internal
|
||||
function _removeCapper(address account) internal {
|
||||
super._removeCapper(account);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../payment/escrow/ConditionalEscrow.sol";
|
||||
|
||||
@ -10,7 +10,7 @@ contract ConditionalEscrowMock is ConditionalEscrow {
|
||||
_allowed[payee] = allowed;
|
||||
}
|
||||
|
||||
function withdrawalAllowed(address payee) public view returns (bool) {
|
||||
function withdrawalAllowed(address payee) public view override returns (bool) {
|
||||
return _allowed[payee];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../drafts/Counters.sol";
|
||||
import "../utils/Counters.sol";
|
||||
|
||||
contract CountersImpl {
|
||||
using Counters for Counters.Counter;
|
||||
|
||||
@ -1,23 +1,25 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../utils/Create2.sol";
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../introspection/ERC1820Implementer.sol";
|
||||
|
||||
contract Create2Impl {
|
||||
function deploy(bytes32 salt, bytes memory code) public {
|
||||
Create2.deploy(salt, code);
|
||||
function deploy(uint256 value, bytes32 salt, bytes memory code) public {
|
||||
Create2.deploy(value, salt, code);
|
||||
}
|
||||
|
||||
function deployERC20(bytes32 salt) public {
|
||||
function deployERC1820Implementer(uint256 value, bytes32 salt) public {
|
||||
// solhint-disable-next-line indent
|
||||
Create2.deploy(salt, type(ERC20).creationCode);
|
||||
Create2.deploy(value, salt, type(ERC1820Implementer).creationCode);
|
||||
}
|
||||
|
||||
function computeAddress(bytes32 salt, bytes memory code) public view returns (address) {
|
||||
return Create2.computeAddress(salt, code);
|
||||
function computeAddress(bytes32 salt, bytes32 codeHash) public view returns (address) {
|
||||
return Create2.computeAddress(salt, codeHash);
|
||||
}
|
||||
|
||||
function computeAddress(bytes32 salt, bytes memory code, address deployer) public pure returns (address) {
|
||||
return Create2.computeAddress(salt, code, deployer);
|
||||
function computeAddressWithDeployer(bytes32 salt, bytes32 codeHash, address deployer) public pure returns (address) {
|
||||
return Create2.computeAddress(salt, codeHash, deployer);
|
||||
}
|
||||
|
||||
receive() payable external {}
|
||||
}
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../crowdsale/Crowdsale.sol";
|
||||
|
||||
contract CrowdsaleMock is Crowdsale {
|
||||
constructor (uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../cryptography/ECDSA.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../../introspection/IERC165.sol";
|
||||
|
||||
@ -34,7 +34,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 {
|
||||
/**
|
||||
* @dev Implement supportsInterface(bytes4) using a lookup table.
|
||||
*/
|
||||
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
|
||||
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
|
||||
return _supportedInterfaces[interfaceId];
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
contract ERC165NotSupported {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
contract ERC165NotSupported { }
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../introspection/ERC165Checker.sol";
|
||||
|
||||
@ -6,14 +6,14 @@ contract ERC165CheckerMock {
|
||||
using ERC165Checker for address;
|
||||
|
||||
function supportsERC165(address account) public view returns (bool) {
|
||||
return account._supportsERC165();
|
||||
return account.supportsERC165();
|
||||
}
|
||||
|
||||
function supportsInterface(address account, bytes4 interfaceId) public view returns (bool) {
|
||||
return account._supportsInterface(interfaceId);
|
||||
return account.supportsInterface(interfaceId);
|
||||
}
|
||||
|
||||
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) public view returns (bool) {
|
||||
return account._supportsAllInterfaces(interfaceIds);
|
||||
return account.supportsAllInterfaces(interfaceIds);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../introspection/ERC165.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../introspection/ERC1820Implementer.sol";
|
||||
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC20/ERC20Burnable.sol";
|
||||
|
||||
contract ERC20BurnableMock is ERC20Burnable {
|
||||
constructor (address initialAccount, uint256 initialBalance) public {
|
||||
constructor (
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
address initialAccount,
|
||||
uint256 initialBalance
|
||||
) public ERC20(name, symbol) {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
}
|
||||
|
||||
13
contracts/mocks/ERC20CappedMock.sol
Normal file
13
contracts/mocks/ERC20CappedMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC20/ERC20Capped.sol";
|
||||
|
||||
contract ERC20CappedMock is ERC20Capped {
|
||||
constructor (string memory name, string memory symbol, uint256 cap)
|
||||
public ERC20(name, symbol) ERC20Capped(cap)
|
||||
{ }
|
||||
|
||||
function mint(address to, uint256 tokenId) public {
|
||||
_mint(to, tokenId);
|
||||
}
|
||||
}
|
||||
13
contracts/mocks/ERC20DecimalsMock.sol
Normal file
13
contracts/mocks/ERC20DecimalsMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
|
||||
contract ERC20DecimalsMock is ERC20 {
|
||||
constructor (string memory name, string memory symbol, uint8 decimals) public ERC20(name, symbol) {
|
||||
_setupDecimals(decimals);
|
||||
}
|
||||
|
||||
function setupDecimals(uint8 decimals) public {
|
||||
_setupDecimals(decimals);
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
|
||||
contract ERC20DetailedMock is ERC20, ERC20Detailed {
|
||||
constructor (string memory name, string memory symbol, uint8 decimals)
|
||||
public
|
||||
ERC20Detailed(name, symbol, decimals)
|
||||
{
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../drafts/ERC1046/ERC20Metadata.sol";
|
||||
|
||||
contract ERC20MetadataMock is ERC20, ERC20Metadata {
|
||||
constructor (string memory tokenURI) public ERC20Metadata(tokenURI) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
function setTokenURI(string memory tokenURI) public {
|
||||
_setTokenURI(tokenURI);
|
||||
}
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC20/ERC20Mintable.sol";
|
||||
import "./MinterRoleMock.sol";
|
||||
|
||||
contract ERC20MintableMock is ERC20Mintable, MinterRoleMock {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
@ -1,10 +1,15 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
|
||||
// mock class using ERC20
|
||||
contract ERC20Mock is ERC20 {
|
||||
constructor (address initialAccount, uint256 initialBalance) public {
|
||||
constructor (
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
address initialAccount,
|
||||
uint256 initialBalance
|
||||
) public payable ERC20(name, symbol) {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
|
||||
@ -16,10 +21,6 @@ contract ERC20Mock is ERC20 {
|
||||
_burn(account, amount);
|
||||
}
|
||||
|
||||
function burnFrom(address account, uint256 amount) public {
|
||||
_burnFrom(account, amount);
|
||||
}
|
||||
|
||||
function transferInternal(address from, address to, uint256 value) public {
|
||||
_transfer(from, to, value);
|
||||
}
|
||||
|
||||
@ -1,11 +1,23 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC20/ERC20Pausable.sol";
|
||||
import "./PauserRoleMock.sol";
|
||||
|
||||
// mock class using ERC20Pausable
|
||||
contract ERC20PausableMock is ERC20Pausable, PauserRoleMock {
|
||||
constructor (address initialAccount, uint256 initialBalance) public {
|
||||
contract ERC20PausableMock is ERC20Pausable {
|
||||
constructor (
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
address initialAccount,
|
||||
uint256 initialBalance
|
||||
) public ERC20(name, symbol) {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
|
||||
function pause() external {
|
||||
_pause();
|
||||
}
|
||||
|
||||
function unpause() external {
|
||||
_unpause();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,22 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../drafts/ERC20Snapshot.sol";
|
||||
import "../token/ERC20/ERC20Snapshot.sol";
|
||||
|
||||
|
||||
contract ERC20SnapshotMock is ERC20Snapshot {
|
||||
constructor(address initialAccount, uint256 initialBalance) public {
|
||||
constructor(
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
address initialAccount,
|
||||
uint256 initialBalance
|
||||
) public ERC20(name, symbol) {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
|
||||
function snapshot() public {
|
||||
_snapshot();
|
||||
}
|
||||
|
||||
function mint(address account, uint256 amount) public {
|
||||
_mint(account, amount);
|
||||
}
|
||||
|
||||
11
contracts/mocks/ERC721BurnableMock.sol
Normal file
11
contracts/mocks/ERC721BurnableMock.sol
Normal file
@ -0,0 +1,11 @@
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC721/ERC721Burnable.sol";
|
||||
|
||||
contract ERC721BurnableMock is ERC721Burnable {
|
||||
constructor(string memory name, string memory symbol) public ERC721(name, symbol) { }
|
||||
|
||||
function mint(address to, uint256 tokenId) public {
|
||||
_mint(to, tokenId);
|
||||
}
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC721/ERC721Full.sol";
|
||||
import "../token/ERC721/ERC721Mintable.sol";
|
||||
import "../token/ERC721/ERC721MetadataMintable.sol";
|
||||
import "../token/ERC721/ERC721Burnable.sol";
|
||||
|
||||
/**
|
||||
* @title ERC721FullMock
|
||||
* This mock just provides public functions for setting metadata URI, getting all tokens of an owner,
|
||||
* checking token existence, removal of a token from an address
|
||||
*/
|
||||
contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable {
|
||||
constructor (string memory name, string memory symbol) public ERC721Mintable() ERC721Full(name, symbol) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
function exists(uint256 tokenId) public view returns (bool) {
|
||||
return _exists(tokenId);
|
||||
}
|
||||
|
||||
function tokensOfOwner(address owner) public view returns (uint256[] memory) {
|
||||
return _tokensOfOwner(owner);
|
||||
}
|
||||
|
||||
function setTokenURI(uint256 tokenId, string memory uri) public {
|
||||
_setTokenURI(tokenId, uri);
|
||||
}
|
||||
|
||||
function setBaseURI(string memory baseURI) public {
|
||||
_setBaseURI(baseURI);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC721/ERC721.sol";
|
||||
import "../GSN/GSNRecipient.sol";
|
||||
@ -9,10 +9,21 @@ import "../GSN/GSNRecipientSignature.sol";
|
||||
* A simple ERC721 mock that has GSN support enabled
|
||||
*/
|
||||
contract ERC721GSNRecipientMock is ERC721, GSNRecipient, GSNRecipientSignature {
|
||||
constructor(address trustedSigner) public GSNRecipientSignature(trustedSigner) { }
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
constructor(string memory name, string memory symbol, address trustedSigner)
|
||||
public
|
||||
ERC721(name, symbol)
|
||||
GSNRecipientSignature(trustedSigner)
|
||||
{ }
|
||||
|
||||
function mint(uint256 tokenId) public {
|
||||
_mint(_msgSender(), tokenId);
|
||||
}
|
||||
|
||||
function _msgSender() internal view override(Context, GSNRecipient) returns (address payable) {
|
||||
return GSNRecipient._msgSender();
|
||||
}
|
||||
|
||||
function _msgData() internal view override(Context, GSNRecipient) returns (bytes memory) {
|
||||
return GSNRecipient._msgData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC721/ERC721Full.sol";
|
||||
import "../token/ERC721/ERC721Mintable.sol";
|
||||
import "../token/ERC721/ERC721MetadataMintable.sol";
|
||||
import "../token/ERC721/ERC721Burnable.sol";
|
||||
|
||||
/**
|
||||
* @title ERC721MintableBurnableImpl
|
||||
*/
|
||||
contract ERC721MintableBurnableImpl is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable {
|
||||
constructor () public ERC721Mintable() ERC721Full("Test", "TEST") {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC721/ERC721.sol";
|
||||
|
||||
@ -7,6 +7,24 @@ import "../token/ERC721/ERC721.sol";
|
||||
* This mock just provides a public safeMint, mint, and burn functions for testing purposes
|
||||
*/
|
||||
contract ERC721Mock is ERC721 {
|
||||
constructor (string memory name, string memory symbol) public ERC721(name, symbol) { }
|
||||
|
||||
function exists(uint256 tokenId) public view returns (bool) {
|
||||
return _exists(tokenId);
|
||||
}
|
||||
|
||||
function setTokenURI(uint256 tokenId, string memory uri) public {
|
||||
_setTokenURI(tokenId, uri);
|
||||
}
|
||||
|
||||
function setBaseURI(string memory baseURI) public {
|
||||
_setBaseURI(baseURI);
|
||||
}
|
||||
|
||||
function mint(address to, uint256 tokenId) public {
|
||||
_mint(to, tokenId);
|
||||
}
|
||||
|
||||
function safeMint(address to, uint256 tokenId) public {
|
||||
_safeMint(to, tokenId);
|
||||
}
|
||||
@ -15,14 +33,6 @@ contract ERC721Mock is ERC721 {
|
||||
_safeMint(to, tokenId, _data);
|
||||
}
|
||||
|
||||
function mint(address to, uint256 tokenId) public {
|
||||
_mint(to, tokenId);
|
||||
}
|
||||
|
||||
function burn(address owner, uint256 tokenId) public {
|
||||
_burn(owner, tokenId);
|
||||
}
|
||||
|
||||
function burn(uint256 tokenId) public {
|
||||
_burn(tokenId);
|
||||
}
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC721/ERC721Pausable.sol";
|
||||
import "./PauserRoleMock.sol";
|
||||
|
||||
/**
|
||||
* @title ERC721PausableMock
|
||||
* This mock just provides a public mint, burn and exists functions for testing purposes
|
||||
*/
|
||||
contract ERC721PausableMock is ERC721Pausable, PauserRoleMock {
|
||||
contract ERC721PausableMock is ERC721Pausable {
|
||||
constructor (string memory name, string memory symbol) public ERC721(name, symbol) { }
|
||||
|
||||
function mint(address to, uint256 tokenId) public {
|
||||
super._mint(to, tokenId);
|
||||
}
|
||||
@ -19,4 +20,12 @@ contract ERC721PausableMock is ERC721Pausable, PauserRoleMock {
|
||||
function exists(uint256 tokenId) public view returns (bool) {
|
||||
return super._exists(tokenId);
|
||||
}
|
||||
|
||||
function pause() external {
|
||||
_pause();
|
||||
}
|
||||
|
||||
function unpause() external {
|
||||
_unpause();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC721/IERC721Receiver.sol";
|
||||
|
||||
@ -14,7 +14,7 @@ contract ERC721ReceiverMock is IERC721Receiver {
|
||||
}
|
||||
|
||||
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
|
||||
public returns (bytes4)
|
||||
public override returns (bytes4)
|
||||
{
|
||||
require(!_reverts, "ERC721ReceiverMock: reverting");
|
||||
emit Received(operator, from, tokenId, data, gasleft());
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
import "../token/ERC777/ERC777.sol";
|
||||
@ -11,16 +11,15 @@ contract ERC777Mock is Context, ERC777 {
|
||||
string memory symbol,
|
||||
address[] memory defaultOperators
|
||||
) public ERC777(name, symbol, defaultOperators) {
|
||||
_mint(_msgSender(), initialHolder, initialBalance, "", "");
|
||||
_mint(initialHolder, initialBalance, "", "");
|
||||
}
|
||||
|
||||
function mintInternal (
|
||||
address operator,
|
||||
address to,
|
||||
uint256 amount,
|
||||
bytes memory userData,
|
||||
bytes memory operatorData
|
||||
) public {
|
||||
_mint(operator, to, amount, userData, operatorData);
|
||||
_mint(to, amount, userData, operatorData);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
import "../token/ERC777/IERC777.sol";
|
||||
@ -37,8 +37,8 @@ contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient,
|
||||
|
||||
IERC1820Registry private _erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
|
||||
|
||||
bytes32 constant private TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
|
||||
bytes32 constant private TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");
|
||||
bytes32 constant private _TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
|
||||
bytes32 constant private _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");
|
||||
|
||||
function tokensToSend(
|
||||
address operator,
|
||||
@ -47,7 +47,7 @@ contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient,
|
||||
uint256 amount,
|
||||
bytes calldata userData,
|
||||
bytes calldata operatorData
|
||||
) external {
|
||||
) external override {
|
||||
if (_shouldRevertSend) {
|
||||
revert();
|
||||
}
|
||||
@ -78,7 +78,7 @@ contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient,
|
||||
uint256 amount,
|
||||
bytes calldata userData,
|
||||
bytes calldata operatorData
|
||||
) external{
|
||||
) external override {
|
||||
if (_shouldRevertReceive) {
|
||||
revert();
|
||||
}
|
||||
@ -103,7 +103,7 @@ contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient,
|
||||
}
|
||||
|
||||
function senderFor(address account) public {
|
||||
_registerInterfaceForAddress(TOKENS_SENDER_INTERFACE_HASH, account);
|
||||
_registerInterfaceForAddress(_TOKENS_SENDER_INTERFACE_HASH, account);
|
||||
|
||||
address self = address(this);
|
||||
if (account == self) {
|
||||
@ -112,11 +112,11 @@ contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient,
|
||||
}
|
||||
|
||||
function registerSender(address sender) public {
|
||||
_erc1820.setInterfaceImplementer(address(this), TOKENS_SENDER_INTERFACE_HASH, sender);
|
||||
_erc1820.setInterfaceImplementer(address(this), _TOKENS_SENDER_INTERFACE_HASH, sender);
|
||||
}
|
||||
|
||||
function recipientFor(address account) public {
|
||||
_registerInterfaceForAddress(TOKENS_RECIPIENT_INTERFACE_HASH, account);
|
||||
_registerInterfaceForAddress(_TOKENS_RECIPIENT_INTERFACE_HASH, account);
|
||||
|
||||
address self = address(this);
|
||||
if (account == self) {
|
||||
@ -125,7 +125,7 @@ contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient,
|
||||
}
|
||||
|
||||
function registerRecipient(address recipient) public {
|
||||
_erc1820.setInterfaceImplementer(address(this), TOKENS_RECIPIENT_INTERFACE_HASH, recipient);
|
||||
_erc1820.setInterfaceImplementer(address(this), _TOKENS_RECIPIENT_INTERFACE_HASH, recipient);
|
||||
}
|
||||
|
||||
function setShouldRevertSend(bool shouldRevert) public {
|
||||
|
||||
38
contracts/mocks/EnumerableMapMock.sol
Normal file
38
contracts/mocks/EnumerableMapMock.sol
Normal file
@ -0,0 +1,38 @@
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../utils/EnumerableMap.sol";
|
||||
|
||||
contract EnumerableMapMock {
|
||||
using EnumerableMap for EnumerableMap.UintToAddressMap;
|
||||
|
||||
event OperationResult(bool result);
|
||||
|
||||
EnumerableMap.UintToAddressMap private _map;
|
||||
|
||||
function contains(uint256 key) public view returns (bool) {
|
||||
return _map.contains(key);
|
||||
}
|
||||
|
||||
function set(uint256 key, address value) public {
|
||||
bool result = _map.set(key, value);
|
||||
emit OperationResult(result);
|
||||
}
|
||||
|
||||
function remove(uint256 key) public {
|
||||
bool result = _map.remove(key);
|
||||
emit OperationResult(result);
|
||||
}
|
||||
|
||||
function length() public view returns (uint256) {
|
||||
return _map.length();
|
||||
}
|
||||
|
||||
function at(uint256 index) public view returns (uint256 key, address value) {
|
||||
return _map.at(index);
|
||||
}
|
||||
|
||||
|
||||
function get(uint256 key) public view returns (address) {
|
||||
return _map.get(key);
|
||||
}
|
||||
}
|
||||
@ -1,37 +1,33 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../utils/EnumerableSet.sol";
|
||||
|
||||
contract EnumerableSetMock{
|
||||
contract EnumerableSetMock {
|
||||
using EnumerableSet for EnumerableSet.AddressSet;
|
||||
|
||||
event TransactionResult(bool result);
|
||||
event OperationResult(bool result);
|
||||
|
||||
EnumerableSet.AddressSet private set;
|
||||
EnumerableSet.AddressSet private _set;
|
||||
|
||||
function contains(address value) public view returns (bool) {
|
||||
return set.contains(value);
|
||||
return _set.contains(value);
|
||||
}
|
||||
|
||||
function add(address value) public {
|
||||
bool result = set.add(value);
|
||||
emit TransactionResult(result);
|
||||
bool result = _set.add(value);
|
||||
emit OperationResult(result);
|
||||
}
|
||||
|
||||
function remove(address value) public {
|
||||
bool result = set.remove(value);
|
||||
emit TransactionResult(result);
|
||||
}
|
||||
|
||||
function enumerate() public view returns (address[] memory) {
|
||||
return set.enumerate();
|
||||
bool result = _set.remove(value);
|
||||
emit OperationResult(result);
|
||||
}
|
||||
|
||||
function length() public view returns (uint256) {
|
||||
return set.length();
|
||||
return _set.length();
|
||||
}
|
||||
|
||||
function get(uint256 index) public view returns (address) {
|
||||
return set.get(index);
|
||||
function at(uint256 index) public view returns (address) {
|
||||
return _set.at(index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
contract EtherReceiverMock {
|
||||
bool private _acceptEther;
|
||||
@ -7,7 +7,7 @@ contract EtherReceiverMock {
|
||||
_acceptEther = acceptEther;
|
||||
}
|
||||
|
||||
function () external payable {
|
||||
receive () external payable {
|
||||
if (!_acceptEther) {
|
||||
revert();
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../crowdsale/distribution/FinalizableCrowdsale.sol";
|
||||
|
||||
contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
|
||||
constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address payable wallet, IERC20 token)
|
||||
public
|
||||
Crowdsale(rate, wallet, token)
|
||||
TimedCrowdsale(openingTime, closingTime)
|
||||
{
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,10 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../GSN/GSNRecipient.sol";
|
||||
import "../GSN/GSNRecipientERC20Fee.sol";
|
||||
|
||||
contract GSNRecipientERC20FeeMock is GSNRecipient, GSNRecipientERC20Fee {
|
||||
constructor(string memory name, string memory symbol) public GSNRecipientERC20Fee(name, symbol) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
constructor(string memory name, string memory symbol) public GSNRecipientERC20Fee(name, symbol) { }
|
||||
|
||||
function mint(address account, uint256 amount) public {
|
||||
_mint(account, amount);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "./ContextMock.sol";
|
||||
import "../GSN/GSNRecipient.sol";
|
||||
@ -12,20 +12,25 @@ contract GSNRecipientMock is ContextMock, GSNRecipient {
|
||||
function acceptRelayedCall(address, address, bytes calldata, uint256, uint256, uint256, uint256, bytes calldata, uint256)
|
||||
external
|
||||
view
|
||||
override
|
||||
returns (uint256, bytes memory)
|
||||
{
|
||||
return (0, "");
|
||||
}
|
||||
|
||||
function _preRelayedCall(bytes memory) internal returns (bytes32) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
function _preRelayedCall(bytes memory) internal override returns (bytes32) { }
|
||||
|
||||
function _postRelayedCall(bytes memory, bool, uint256, bytes32) internal {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
function _postRelayedCall(bytes memory, bool, uint256, bytes32) internal override { }
|
||||
|
||||
function upgradeRelayHub(address newRelayHub) public {
|
||||
return _upgradeRelayHub(newRelayHub);
|
||||
}
|
||||
|
||||
function _msgSender() internal override(Context, GSNRecipient) view virtual returns (address payable) {
|
||||
return GSNRecipient._msgSender();
|
||||
}
|
||||
|
||||
function _msgData() internal override(Context, GSNRecipient) view virtual returns (bytes memory) {
|
||||
return GSNRecipient._msgData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../GSN/GSNRecipient.sol";
|
||||
import "../GSN/GSNRecipientSignature.sol";
|
||||
|
||||
contract GSNRecipientSignatureMock is GSNRecipient, GSNRecipientSignature {
|
||||
constructor(address trustedSigner) public GSNRecipientSignature(trustedSigner) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
constructor(address trustedSigner) public GSNRecipientSignature(trustedSigner) { }
|
||||
|
||||
event MockFunctionCalled();
|
||||
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../crowdsale/price/IncreasingPriceCrowdsale.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale {
|
||||
constructor (
|
||||
uint256 openingTime,
|
||||
uint256 closingTime,
|
||||
address payable wallet,
|
||||
IERC20 token,
|
||||
uint256 initialRate,
|
||||
uint256 finalRate
|
||||
)
|
||||
public
|
||||
Crowdsale(initialRate, wallet, token)
|
||||
TimedCrowdsale(openingTime, closingTime)
|
||||
IncreasingPriceCrowdsale(initialRate, finalRate)
|
||||
{
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user