|
@@ -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
|
|
@@ -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.
|
|
@@ -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);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -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);
|
|
|
+ }
|
|
|
}
|