-
Notifications
You must be signed in to change notification settings - Fork 18
/
OptionToken.sol
112 lines (81 loc) · 3.1 KB
/
OptionToken.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
pragma solidity >=0.6.0;
import "../finance/OptionsExchange.sol";
import "../finance/RedeemableToken.sol";
import "../utils/ERC20.sol";
import "../utils/Arrays.sol";
import "../utils/SafeMath.sol";
contract OptionToken is RedeemableToken {
using SafeMath for uint;
mapping(address => uint) private _issued;
string private constant _prefix = "Option Redeemable Token: ";
string private _symbol;
uint private _unliquidatedVolume;
constructor(string memory _sb, address _issuer)
ERC20(string(abi.encodePacked(_prefix, _sb)))
public
{
_symbol = _sb;
exchange = OptionsExchange(_issuer);
}
function name() override external view returns (string memory) {
return string(abi.encodePacked(_prefix, _symbol));
}
function symbol() override external view returns (string memory) {
return _symbol;
}
function issue(address from, address to, uint value) external {
require(msg.sender == address(exchange), "issuance unallowed");
_issued[from] = _issued[from].add(value);
addBalance(to, value);
_totalSupply = _totalSupply.add(value);
_unliquidatedVolume = _unliquidatedVolume.add(value);
emit Transfer(address(0), to, value);
}
function burn(uint value) external {
burn(msg.sender, value);
}
function burn(address owner, uint value) public {
require(
msg.sender == owner || msg.sender == address(exchange),
"burn sender unallowed"
);
uint b = balanceOf(owner);
uint w = _issued[owner];
require(
b >= value && w >= value || (msg.sender == address(exchange) && w >= value),
"invalid burn value"
);
if (msg.sender == owner) {
removeBalance(owner, value);
_totalSupply = _totalSupply.sub(value);
}
uint uc = uncoveredVolume(owner);
uint coll = MoreMath.min(value, uc);
w = w.sub(value);
_issued[owner] = w;
_unliquidatedVolume = _unliquidatedVolume.sub(value);
uint udl = value > uc ? value.sub(uc) : 0;
exchange.release(owner, udl, coll);
exchange.cleanUp(owner, address(this));
emit Transfer(owner, address(0), value);
}
function writtenVolume(address owner) external view returns (uint) {
return _issued[owner];
}
function uncoveredVolume(address owner) public view returns (uint) {
uint covered = exchange.underlyingBalance(owner, address(this));
uint w = _issued[owner];
return w > covered ? w.sub(covered) : 0;
}
function redeemAllowed() override public view returns (bool) {
return _unliquidatedVolume == 0;
}
function afterRedeem(address owner, uint, uint value) override internal {
exchange.cleanUp(owner, address(this));
emit Transfer(owner, address(0), value);
}
function emitTransfer(address from, address to, uint value) override internal {
exchange.transferOwnership(_symbol, from, to, value);
emit Transfer(from, to, value);
}
}