diff --git a/protocol/contracts/dao/Getters.sol b/protocol/contracts/dao/Getters.sol index 5b7cb549..f43d49cb 100644 --- a/protocol/contracts/dao/Getters.sol +++ b/protocol/contracts/dao/Getters.sol @@ -116,9 +116,6 @@ contract Getters is State { } function balanceOfCoupons(address account, uint256 epoch) public view returns (uint256) { - if (outstandingCoupons(epoch) == 0) { - return 0; - } return _state.accounts[account].coupons[epoch]; } @@ -150,6 +147,10 @@ contract Getters is State { * Epoch */ + function price() public view returns (uint256) { + return _state13.price.asUint256(); + } + function epoch() public view returns (uint256) { return _state.epoch.current; } diff --git a/protocol/contracts/dao/Implementation.sol b/protocol/contracts/dao/Implementation.sol index 7106869c..2f207ef2 100644 --- a/protocol/contracts/dao/Implementation.sol +++ b/protocol/contracts/dao/Implementation.sol @@ -35,7 +35,7 @@ contract Implementation is State, Bonding, Market, Regulator, Govern { mintToAccount(msg.sender, 150e18); // 150 DSD to committer // contributor rewards: mintToAccount(0xF414CFf71eCC35320Df0BB577E3Bc9B69c9E1f07, 1000e18); // 1000 DSD to devnull - mintToAccount(0x35F32d099fb9E08b706A6fa41D639EEB69F8A906, 2000e18); // 2000 DSD to degendegen9 + mintToAccount(0x35F32d099fb9E08b706A6fa41D639EEB69F8A906, 3000e18); // 3000 DSD to degendegen9 } function advance() external incentivized { diff --git a/protocol/contracts/dao/Market.sol b/protocol/contracts/dao/Market.sol index 47a94767..b53587b5 100644 --- a/protocol/contracts/dao/Market.sol +++ b/protocol/contracts/dao/Market.sol @@ -144,10 +144,20 @@ contract Market is Comptroller, Curve { function redeemCoupons(uint256 couponEpoch, uint256 amount) external { require(_state13.price.greaterThan(Decimal.one()), "Market: not in expansion"); require(epoch().sub(couponEpoch) >= 2, "Market: Too early to redeem"); - require(amount != 0, "Market: Amount too low"); + require(amount != 0, "Market: Amount too low"); - uint256 couponAmount = balanceOfCoupons(msg.sender, couponEpoch) - .mul(amount).div(balanceOfCouponUnderlying(msg.sender, couponEpoch), "Market: No underlying"); + uint256 underlying = balanceOfCouponUnderlying(msg.sender, couponEpoch); + require(underlying >= amount, "Market: Insufficient coupon underlying balance"); + + uint256 couponAmount; + if (outstandingCoupons(couponEpoch) == 0) { + // coupons have expired + _state.accounts[msg.sender].coupons[couponEpoch] = 0; + } else { + // coupons have not expired + couponAmount = _state.accounts[msg.sender].coupons[couponEpoch] + .mul(amount).div(underlying, "Market: No underlying"); + } uint256 totalAmount = couponAmount.add(amount); @@ -178,10 +188,20 @@ contract Market is Comptroller, Curve { function redeemCoupons(uint256 couponEpoch, uint256 amount, uint256 minOutput) external { require(_state13.price.greaterThan(Decimal.one()), "Market: not in expansion"); require(epoch().sub(couponEpoch) >= 2, "Market: Too early to redeem"); - require(amount != 0, "Market: Amount too low"); + require(amount != 0, "Market: Amount too low"); - uint256 couponAmount = balanceOfCoupons(msg.sender, couponEpoch) - .mul(amount).div(balanceOfCouponUnderlying(msg.sender, couponEpoch), "Market: No underlying"); + uint256 underlying = balanceOfCouponUnderlying(msg.sender, couponEpoch); + require(underlying >= amount, "Market: Insufficient coupon underlying balance"); + + uint256 couponAmount; + if (outstandingCoupons(couponEpoch) == 0) { + // coupons have expired + _state.accounts[msg.sender].coupons[couponEpoch] = 0; + } else { + // coupons have not expired + couponAmount = _state.accounts[msg.sender].coupons[couponEpoch] + .mul(amount).div(underlying, "Market: No underlying"); + } uint256 totalAmount = couponAmount.add(amount); @@ -226,9 +246,28 @@ contract Market is Comptroller, Curve { function transferCoupons(address sender, address recipient, uint256 epoch, uint256 amount) external { require(sender != address(0), "Market: Coupon transfer from the zero address"); require(recipient != address(0), "Market: Coupon transfer to the zero address"); + require(amount != 0, "Market: Amount too low"); + + uint256 underlying = balanceOfCouponUnderlying(sender, epoch); + require(underlying >= amount, "Market: Insufficient coupon underlying balance"); - decrementBalanceOfCoupons(sender, epoch, amount, "Market: Insufficient coupon balance"); - incrementBalanceOfCoupons(recipient, epoch, amount); + uint256 couponAmount; + if (outstandingCoupons(epoch) == 0) { + // coupons have expired + _state.accounts[sender].coupons[epoch] = 0; + } else { + // coupons have not expired + couponAmount = _state.accounts[sender].coupons[epoch] + .mul(amount).div(underlying, "Market: No underlying"); + } + + decrementBalanceOfCouponUnderlying(sender, epoch, amount, "Market: Insufficient coupon underlying balance"); + incrementBalanceOfCouponUnderlying(recipient, epoch, amount); + + if (couponAmount != 0) { + decrementBalanceOfCoupons(sender, epoch, couponAmount, "Market: Insufficient coupon balance"); + incrementBalanceOfCoupons(recipient, epoch, couponAmount); + } if (msg.sender != sender && allowanceCoupons(sender, msg.sender) != uint256(-1)) { decrementAllowanceCoupons(sender, msg.sender, amount, "Market: Insufficient coupon approval");