Forráskód Böngészése

Add a vault to PostDeliveryCrowdsale. (#1721)

* Add a vault to PostDeliveryCrowdsale.

* Add changelog entry.

* Apply suggestions from code review

Co-Authored-By: nventuro <nicolas.venturo@gmail.com>

* Rename TokenVault.

* add solhint ignore directive
Nicolás Venturo 6 éve
szülő
commit
97a9ca5681

+ 3 - 0
CHANGELOG.md

@@ -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:

+ 24 - 2
contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol

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