Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a vault to PostDeliveryCrowdsale. #1721

Merged
merged 7 commits into from
Apr 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
### Improvements:
* Upgraded the minimum compiler version to v0.5.7: this prevents users from encountering compiler bugs that were fixed in this version. ([#1724](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1724))

### Bugfixes:
* `PostDeliveryCrowdsale`: some validations where skipped when paired with other crowdsale flavors, such as `AllowanceCrowdsale`, or `MintableCrowdsale` and `ERC20Capped`, which could cause buyers to not be able to claim their purchased tokens. ([#1721](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1721))

## 2.2.0 (2019-03-14)

### New features:
Expand Down
26 changes: 24 additions & 2 deletions contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ pragma solidity ^0.5.7;

import "../validation/TimedCrowdsale.sol";
import "../../math/SafeMath.sol";
import "../../ownership/Secondary.sol";
import "../../token/ERC20/IERC20.sol";

/**
* @title PostDeliveryCrowdsale
Expand All @@ -11,6 +13,11 @@ 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.
Expand All @@ -20,8 +27,9 @@ contract PostDeliveryCrowdsale is TimedCrowdsale {
require(hasClosed());
uint256 amount = _balances[beneficiary];
require(amount > 0);

_balances[beneficiary] = 0;
_deliverTokens(beneficiary, amount);
_vault.transfer(token(), beneficiary, amount);
}

/**
Expand All @@ -32,12 +40,26 @@ contract PostDeliveryCrowdsale is TimedCrowdsale {
}

/**
* @dev Overrides parent by storing balances instead of issuing tokens right away.
* @dev Overrides parent by storing due balances, and delivering tokens to the vault instead of the end user. This
* ensures that the tokens will be available by the time they are withdrawn (which may not be the case if
* `_deliverTokens` was called later).
* @param beneficiary Token purchaser
* @param tokenAmount Amount of tokens purchased
*/
function _processPurchase(address beneficiary, uint256 tokenAmount) internal {
_balances[beneficiary] = _balances[beneficiary].add(tokenAmount);
_deliverTokens(address(_vault), tokenAmount);
}
}

/**
* @title __unstable__TokenVault
* @dev Similar to an Escrow for tokens, this contract allows its primary account to spend its tokens as it sees fit.
* This contract is an internal helper for PostDeliveryCrowdsale, and should not be used outside of this context.
*/
// solhint-disable-next-line contract-name-camelcase
contract __unstable__TokenVault is Secondary {
function transfer(IERC20 token, address to, uint256 amount) public onlyPrimary {
token.transfer(to, amount);
}
}