/ contracts / finance / RedeemableToken.sol
RedeemableToken.sol
 1  pragma solidity >=0.6.0;
 2  pragma experimental ABIEncoderV2;
 3  
 4  import "../utils/Arrays.sol";
 5  import "../utils/ERC20.sol";
 6  import "../utils/MoreMath.sol";
 7  import "../interfaces/IOptionsExchange.sol";
 8  
 9  abstract contract RedeemableToken is ERC20 {
10  
11      using SafeMath for uint;
12  
13      IOptionsExchange internal exchange;
14  
15      function redeemAllowed() virtual public view returns(bool);
16  
17      function redeem(address owner) external returns (uint value) {
18  
19          address[] memory owners = new address[](1);
20          owners[0] = owner;
21          value = redeem(owners);
22      }
23  
24      function redeem(address[] memory owners) public returns (uint value) {
25  
26          require(redeemAllowed(), "redeem not allowed");
27  
28          uint valTotal = exchange.balanceOf(address(this));
29          uint supplyTotal = _totalSupply;
30          uint supplyRemaining = _totalSupply;
31          
32          for (uint i = 0; i < owners.length; i++) {
33              if (owners[i] != address(0)) {
34                  (uint bal, uint val) = redeem(valTotal, supplyTotal, owners[i]);
35                  value = value.add(val);
36                  supplyRemaining = supplyRemaining.sub(bal);
37              }
38          }
39  
40          _totalSupply = supplyRemaining;
41      }
42  
43      function redeem(uint valTotal, uint supplyTotal, address owner) 
44          private
45          returns (uint bal, uint val)
46      {
47          bal = balanceOf(owner);
48          
49          if (bal > 0) {
50              uint b = 1e3;
51              val = MoreMath.round(valTotal.mul(bal.mul(b)).div(supplyTotal), b);
52              removeBalance(owner, bal);
53              exchange.transferBalance(owner, val);
54          }
55  
56          afterRedeem(owner, bal, val);
57      }
58  
59      function afterRedeem(address owner, uint bal, uint) virtual internal {
60  
61          emitTransfer(owner, address(0), bal);
62      }
63  }