SHOW:
|
|
- or go back to the newest paste.
1 | - | pragma solidity ^0.4.13; |
1 | + | pragma solidity ^0.4.13; |
2 | - | |
2 | + | |
3 | - | contract VeritaseumToken { |
3 | + | contract VeritaseumToken { |
4 | - | |
4 | + | |
5 | - | string public name = "Veritaseum"; // name of the token |
5 | + | string public name = "Veritaseum"; // name of the token |
6 | - | string public symbol = "VERI"; // ERC20 compliant 4 digit token code |
6 | + | string public symbol = "VERI"; // ERC20 compliant 4 digit token code |
7 | - | uint public decimals = 18; // token has 18 digit precision |
7 | + | uint public decimals = 18; // token has 18 digit precision |
8 | - | |
8 | + | |
9 | - | uint public totalSupply = 100000000 ether; // total supply of 100 Million Tokens |
9 | + | uint public totalSupply = 100000000 ether; // total supply of 100 Million Tokens |
10 | - | |
10 | + | |
11 | - | function balanceOf(address who) constant returns (uint); |
11 | + | function balanceOf(address who) constant returns (uint); |
12 | - | function allowance(address owner, address spender) constant returns (uint); |
12 | + | function allowance(address owner, address spender) constant returns (uint); |
13 | - | |
13 | + | |
14 | - | function transfer(address to, uint value) returns (bool ok); |
14 | + | function transfer(address to, uint value) returns (bool ok); |
15 | - | function transferFrom(address from, address to, uint value) returns (bool ok); |
15 | + | function transferFrom(address from, address to, uint value) returns (bool ok); |
16 | - | function approve(address spender, uint value) returns (bool ok); |
16 | + | function approve(address spender, uint value) returns (bool ok); |
17 | - | event Transfer(address indexed from, address indexed to, uint value); |
17 | + | event Transfer(address indexed from, address indexed to, uint value); |
18 | - | event Approval(address indexed owner, address indexed spender, uint value); |
18 | + | event Approval(address indexed owner, address indexed spender, uint value); |
19 | } | |
20 | - | |
20 | + | |
21 | - | library SafeMath { |
21 | + | library SafeMath { |
22 | - | function mul(uint256 a, uint256 b) internal constant returns (uint256) { |
22 | + | function mul(uint256 a, uint256 b) internal constant returns (uint256) { |
23 | - | uint256 c = a * b; |
23 | + | uint256 c = a * b; |
24 | - | assert(a == 0 || c / a == b); |
24 | + | assert(a == 0 || c / a == b); |
25 | - | return c; |
25 | + | return c; |
26 | - | } |
26 | + | } |
27 | - | |
27 | + | |
28 | - | function div(uint256 a, uint256 b) internal constant returns (uint256) { |
28 | + | function div(uint256 a, uint256 b) internal constant returns (uint256) { |
29 | - | // assert(b > 0); // Solidity automatically throws when dividing by 0 |
29 | + | // assert(b > 0); // Solidity automatically throws when dividing by 0 |
30 | - | uint256 c = a / b; |
30 | + | uint256 c = a / b; |
31 | - | // assert(a == b * c + a % b); // There is no case in which this doesn't hold |
31 | + | // assert(a == b * c + a % b); // There is no case in which this doesn't hold |
32 | - | return c; |
32 | + | return c; |
33 | - | } |
33 | + | } |
34 | - | |
34 | + | |
35 | - | function sub(uint256 a, uint256 b) internal constant returns (uint256) { |
35 | + | function sub(uint256 a, uint256 b) internal constant returns (uint256) { |
36 | - | assert(b <= a); |
36 | + | assert(b <= a); |
37 | - | return a - b; |
37 | + | return a - b; |
38 | - | } |
38 | + | } |
39 | - | |
39 | + | |
40 | - | function add(uint256 a, uint256 b) internal constant returns (uint256) { |
40 | + | function add(uint256 a, uint256 b) internal constant returns (uint256) { |
41 | - | uint256 c = a + b; |
41 | + | uint256 c = a + b; |
42 | - | assert(c >= a); |
42 | + | assert(c >= a); |
43 | - | return c; |
43 | + | return c; |
44 | - | } |
44 | + | } |
45 | } | |
46 | - | |
46 | + | |
47 | - | contract Ownable { |
47 | + | contract Ownable { |
48 | - | address public owner; |
48 | + | address public owner; |
49 | - | |
49 | + | |
50 | - | |
50 | + | |
51 | - | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); |
51 | + | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); |
52 | - | |
52 | + | |
53 | - | |
53 | + | |
54 | - | /** |
54 | + | /** |
55 | - | * @dev The Ownable constructor sets the original `owner` of the contract to the sender |
55 | + | * @dev The Ownable constructor sets the original `owner` of the contract to the sender |
56 | - | * account. |
56 | + | * account. |
57 | - | */ |
57 | + | */ |
58 | - | function Ownable() { |
58 | + | function Ownable() { |
59 | - | owner = msg.sender; |
59 | + | owner = msg.sender; |
60 | - | } |
60 | + | } |
61 | - | |
61 | + | |
62 | - | |
62 | + | |
63 | - | /** |
63 | + | /** |
64 | - | * @dev Throws if called by any account other than the owner. |
64 | + | * @dev Throws if called by any account other than the owner. |
65 | - | */ |
65 | + | */ |
66 | - | modifier onlyOwner() { |
66 | + | modifier onlyOwner() { |
67 | - | require(msg.sender == owner); |
67 | + | require(msg.sender == owner); |
68 | - | _; |
68 | + | _; |
69 | - | } |
69 | + | } |
70 | - | |
70 | + | |
71 | - | |
71 | + | |
72 | - | /** |
72 | + | /** |
73 | - | * @dev Allows the current owner to transfer control of the contract to a newOwner. |
73 | + | * @dev Allows the current owner to transfer control of the contract to a newOwner. |
74 | - | * @param newOwner The address to transfer ownership to. |
74 | + | * @param newOwner The address to transfer ownership to. |
75 | - | */ |
75 | + | */ |
76 | - | function transferOwnership(address newOwner) onlyOwner public { |
76 | + | function transferOwnership(address newOwner) onlyOwner public { |
77 | - | require(newOwner != address(0)); |
77 | + | require(newOwner != address(0)); |
78 | - | OwnershipTransferred(owner, newOwner); |
78 | + | OwnershipTransferred(owner, newOwner); |
79 | - | owner = newOwner; |
79 | + | owner = newOwner; |
80 | - | } |
80 | + | } |
81 | - | |
81 | + | |
82 | } | |
83 | - | |
83 | + | |
84 | - | contract TokenDestructible is Ownable { |
84 | + | contract TokenDestructible is Ownable { |
85 | - | |
85 | + | |
86 | - | function TokenDestructible() payable { } |
86 | + | function TokenDestructible() payable { } |
87 | - | |
87 | + | |
88 | - | /** |
88 | + | /** |
89 | - | * @notice Terminate contract and refund to owner |
89 | + | * @notice Terminate contract and refund to owner |
90 | - | * @param tokens List of addresses of ERC20 or ERC20Basic token contracts to |
90 | + | * @param tokens List of addresses of ERC20 or ERC20Basic token contracts to |
91 | - | refund. |
91 | + | refund. |
92 | - | * @notice The called token contracts could try to re-enter this contract. Only |
92 | + | * @notice The called token contracts could try to re-enter this contract. Only |
93 | - | supply token contracts you trust. |
93 | + | supply token contracts you trust. |
94 | - | */ |
94 | + | */ |
95 | - | function destroy(address[] tokens) onlyOwner public { |
95 | + | function destroy(address[] tokens) onlyOwner public { |
96 | - | |
96 | + | |
97 | - | // Transfer tokens to owner |
97 | + | // Transfer tokens to owner |
98 | - | for(uint256 i = 0; i < tokens.length; i++) { |
98 | + | for(uint256 i = 0; i < tokens.length; i++) { |
99 | - | ERC20Basic token = ERC20Basic(tokens[i]); |
99 | + | ERC20Basic token = ERC20Basic(tokens[i]); |
100 | - | uint256 balance = token.balanceOf(this); |
100 | + | uint256 balance = token.balanceOf(this); |
101 | - | token.transfer(owner, balance); |
101 | + | token.transfer(owner, balance); |
102 | - | } |
102 | + | } |
103 | - | |
103 | + | |
104 | - | // Transfer Eth to owner and terminate contract |
104 | + | // Transfer Eth to owner and terminate contract |
105 | - | selfdestruct(owner); |
105 | + | selfdestruct(owner); |
106 | - | } |
106 | + | } |
107 | } | |
108 | - | |
108 | + | |
109 | - | contract VeExposure is TokenDestructible { |
109 | + | contract VeExposure is TokenDestructible { |
110 | - | |
110 | + | |
111 | - | //--- Definitions |
111 | + | //--- Definitions |
112 | - | |
112 | + | |
113 | - | using SafeMath for uint256; |
113 | + | using SafeMath for uint256; |
114 | - | |
114 | + | |
115 | - | enum State { None, Open, Collected, Closing, Closed } |
115 | + | enum State { None, Open, Collected, Closing, Closed } |
116 | - | |
116 | + | |
117 | - | struct Exposure { |
117 | + | struct Exposure { |
118 | - | address account; |
118 | + | address account; |
119 | - | uint256 veriAmount; |
119 | + | uint256 veriAmount; |
120 | - | uint256 initialValue; |
120 | + | uint256 initialValue; |
121 | - | uint256 finalValue; |
121 | + | uint256 finalValue; |
122 | - | uint64 creationTime; |
122 | + | uint64 creationTime; |
123 | - | uint64 closingTime; |
123 | + | uint64 closingTime; |
124 | - | State state; |
124 | + | State state; |
125 | - | } |
125 | + | } |
126 | - | |
126 | + | |
127 | - | //--- Storage |
127 | + | //--- Storage |
128 | - | |
128 | + | |
129 | - | VeritaseumToken public veToken; |
129 | + | VeritaseumToken public veToken; |
130 | - | address public portfolio; |
130 | + | address public portfolio; |
131 | - | |
131 | + | |
132 | - | uint256 public ratio; |
132 | + | uint256 public ratio; |
133 | - | uint32 public minDuration; |
133 | + | uint32 public minDuration; |
134 | - | uint32 public maxDuration; |
134 | + | uint32 public maxDuration; |
135 | - | uint256 public minVeriAmount; |
135 | + | uint256 public minVeriAmount; |
136 | - | uint256 public maxVeriAmount; |
136 | + | uint256 public maxVeriAmount; |
137 | - | |
137 | + | |
138 | - | mapping (bytes32 => Exposure) exposures; |
138 | + | mapping (bytes32 => Exposure) exposures; |
139 | - | |
139 | + | |
140 | - | //--- Constructor |
140 | + | //--- Constructor |
141 | - | |
141 | + | |
142 | - | function VeExposure( |
142 | + | function VeExposure( |
143 | - | VeritaseumToken _veToken, |
143 | + | VeritaseumToken _veToken, |
144 | - | uint256 _ratio, |
144 | + | uint256 _ratio, |
145 | - | uint32 _minDuration, |
145 | + | uint32 _minDuration, |
146 | - | uint32 _maxDuration, |
146 | + | uint32 _maxDuration, |
147 | - | uint256 _minVeriAmount, |
147 | + | uint256 _minVeriAmount, |
148 | - | uint256 _maxVeriAmount |
148 | + | uint256 _maxVeriAmount |
149 | - | ) { |
149 | + | ) { |
150 | - | require(_veToken != address(0)); |
150 | + | require(_veToken != address(0)); |
151 | - | require(_minDuration > 0 && _minDuration <= _maxDuration); |
151 | + | require(_minDuration > 0 && _minDuration <= _maxDuration); |
152 | - | require(_minVeriAmount > 0 && _minVeriAmount <= _maxVeriAmount); |
152 | + | require(_minVeriAmount > 0 && _minVeriAmount <= _maxVeriAmount); |
153 | - | |
153 | + | |
154 | - | veToken = _veToken; |
154 | + | veToken = _veToken; |
155 | - | ratio = _ratio; |
155 | + | ratio = _ratio; |
156 | - | minDuration = _minDuration; |
156 | + | minDuration = _minDuration; |
157 | - | maxDuration = _maxDuration; |
157 | + | maxDuration = _maxDuration; |
158 | - | minVeriAmount = _minVeriAmount; |
158 | + | minVeriAmount = _minVeriAmount; |
159 | - | maxVeriAmount = _maxVeriAmount; |
159 | + | maxVeriAmount = _maxVeriAmount; |
160 | - | } |
160 | + | } |
161 | - | |
161 | + | |
162 | - | //--- Modifiers |
162 | + | //--- Modifiers |
163 | - | modifier onlyPortfolio { |
163 | + | modifier onlyPortfolio { |
164 | - | require(msg.sender == portfolio); |
164 | + | require(msg.sender == portfolio); |
165 | - | _; |
165 | + | _; |
166 | - | } |
166 | + | } |
167 | - | |
167 | + | |
168 | - | //--- Accessors |
168 | + | //--- Accessors |
169 | - | |
169 | + | |
170 | - | function setPortfolio(address _portfolio) public onlyOwner { |
170 | + | function setPortfolio(address _portfolio) public onlyOwner { |
171 | - | require(_portfolio != address(0)); |
171 | + | require(_portfolio != address(0)); |
172 | - | |
172 | + | |
173 | - | portfolio = _portfolio; |
173 | + | portfolio = _portfolio; |
174 | - | } |
174 | + | } |
175 | - | |
175 | + | |
176 | - | function setMinDuration(uint32 _minDuration) public onlyOwner { |
176 | + | function setMinDuration(uint32 _minDuration) public onlyOwner { |
177 | - | require(_minDuration > 0 && _minDuration <= maxDuration); |
177 | + | require(_minDuration > 0 && _minDuration <= maxDuration); |
178 | - | |
178 | + | |
179 | - | minDuration = _minDuration; |
179 | + | minDuration = _minDuration; |
180 | - | } |
180 | + | } |
181 | - | |
181 | + | |
182 | - | function setMaxDuration(uint32 _maxDuration) public onlyOwner { |
182 | + | function setMaxDuration(uint32 _maxDuration) public onlyOwner { |
183 | - | require(_maxDuration >= minDuration); |
183 | + | require(_maxDuration >= minDuration); |
184 | - | |
184 | + | |
185 | - | maxDuration = _maxDuration; |
185 | + | maxDuration = _maxDuration; |
186 | - | } |
186 | + | } |
187 | - | |
187 | + | |
188 | - | function setMinVeriAmount(uint32 _minVeriAmount) public onlyOwner { |
188 | + | function setMinVeriAmount(uint32 _minVeriAmount) public onlyOwner { |
189 | - | require(_minVeriAmount > 0 && _minVeriAmount <= maxVeriAmount); |
189 | + | require(_minVeriAmount > 0 && _minVeriAmount <= maxVeriAmount); |
190 | - | |
190 | + | |
191 | - | minVeriAmount = _minVeriAmount; |
191 | + | minVeriAmount = _minVeriAmount; |
192 | - | } |
192 | + | } |
193 | - | |
193 | + | |
194 | - | function setMaxVeriAmount(uint32 _maxVeriAmount) public onlyOwner { |
194 | + | function setMaxVeriAmount(uint32 _maxVeriAmount) public onlyOwner { |
195 | - | require(_maxVeriAmount >= minVeriAmount); |
195 | + | require(_maxVeriAmount >= minVeriAmount); |
196 | - | |
196 | + | |
197 | - | maxVeriAmount = _maxVeriAmount; |
197 | + | maxVeriAmount = _maxVeriAmount; |
198 | - | } |
198 | + | } |
199 | - | |
199 | + | |
200 | - | //--- Events |
200 | + | //--- Events |
201 | - | |
201 | + | |
202 | - | event ExposureOpened( |
202 | + | event ExposureOpened( |
203 | - | bytes32 indexed id, |
203 | + | bytes32 indexed id, |
204 | - | address indexed account, |
204 | + | address indexed account, |
205 | - | uint256 veriAmount, |
205 | + | uint256 veriAmount, |
206 | - | uint256 value, |
206 | + | uint256 value, |
207 | - | uint64 creationTime, |
207 | + | uint64 creationTime, |
208 | - | uint64 closingTime |
208 | + | uint64 closingTime |
209 | - | ); |
209 | + | ); |
210 | - | |
210 | + | |
211 | - | event ExposureCollected( |
211 | + | event ExposureCollected( |
212 | - | bytes32 indexed id, |
212 | + | bytes32 indexed id, |
213 | - | address indexed account, |
213 | + | address indexed account, |
214 | - | uint256 value |
214 | + | uint256 value |
215 | - | ); |
215 | + | ); |
216 | - | |
216 | + | |
217 | - | event ExposureClosed( |
217 | + | event ExposureClosed( |
218 | - | bytes32 indexed id, |
218 | + | bytes32 indexed id, |
219 | - | address indexed account, |
219 | + | address indexed account, |
220 | - | uint256 initialValue, |
220 | + | uint256 initialValue, |
221 | - | uint256 finalValue |
221 | + | uint256 finalValue |
222 | - | ); |
222 | + | ); |
223 | - | |
223 | + | |
224 | - | event ExposureSettled( |
224 | + | event ExposureSettled( |
225 | - | bytes32 indexed id, |
225 | + | bytes32 indexed id, |
226 | - | address indexed account, |
226 | + | address indexed account, |
227 | - | uint256 value |
227 | + | uint256 value |
228 | - | ); |
228 | + | ); |
229 | - | |
229 | + | |
230 | - | //--- Public functions |
230 | + | //--- Public functions |
231 | - | |
231 | + | |
232 | - | function open(uint256 veriAmount, uint32 duration, uint256 nonce) public payable { |
232 | + | function open(uint256 veriAmount, uint32 duration, uint256 nonce) public payable { |
233 | - | require(veriAmount >= minVeriAmount && veriAmount <= maxVeriAmount); |
233 | + | require(veriAmount >= minVeriAmount && veriAmount <= maxVeriAmount); |
234 | - | require(duration >= minDuration && duration <= maxDuration); |
234 | + | require(duration >= minDuration && duration <= maxDuration); |
235 | - | require(checkRatio(veriAmount, msg.value)); |
235 | + | require(checkRatio(veriAmount, msg.value)); |
236 | - | |
236 | + | |
237 | - | bytes32 id = calculateId({ |
237 | + | bytes32 id = calculateId({ |
238 | - | veriAmount: veriAmount, |
238 | + | veriAmount: veriAmount, |
239 | - | value: msg.value, |
239 | + | value: msg.value, |
240 | - | duration: duration, |
240 | + | duration: duration, |
241 | - | nonce: nonce |
241 | + | nonce: nonce |
242 | - | }); |
242 | + | }); |
243 | - | require(!exists(id)); |
243 | + | require(!exists(id)); |
244 | - | |
244 | + | |
245 | - | openExposure(id, veriAmount, duration); |
245 | + | openExposure(id, veriAmount, duration); |
246 | - | forwardTokens(veriAmount); |
246 | + | forwardTokens(veriAmount); |
247 | - | } |
247 | + | } |
248 | - | |
248 | + | |
249 | - | function collect(bytes32 id) public onlyPortfolio returns (uint256 value) { |
249 | + | function collect(bytes32 id) public onlyPortfolio returns (uint256 value) { |
250 | - | Exposure storage exposure = exposures[id]; |
250 | + | Exposure storage exposure = exposures[id]; |
251 | - | require(exposure.state == State.Open); |
251 | + | require(exposure.state == State.Open); |
252 | - | |
252 | + | |
253 | - | value = exposure.initialValue; |
253 | + | value = exposure.initialValue; |
254 | - | |
254 | + | |
255 | - | exposure.state = State.Collected; |
255 | + | exposure.state = State.Collected; |
256 | - | msg.sender.transfer(value); |
256 | + | msg.sender.transfer(value); |
257 | - | |
257 | + | |
258 | - | ExposureCollected({ |
258 | + | ExposureCollected({ |
259 | - | id: id, |
259 | + | id: id, |
260 | - | account: exposure.account, |
260 | + | account: exposure.account, |
261 | - | value: value |
261 | + | value: value |
262 | - | }); |
262 | + | }); |
263 | - | } |
263 | + | } |
264 | - | |
264 | + | |
265 | - | function close(bytes32 id) public payable onlyPortfolio { |
265 | + | function close(bytes32 id) public payable onlyPortfolio { |
266 | - | Exposure storage exposure = exposures[id]; |
266 | + | Exposure storage exposure = exposures[id]; |
267 | - | require(exposure.state == State.Collected); |
267 | + | require(exposure.state == State.Collected); |
268 | - | require(hasPassed(exposure.closingTime)); |
268 | + | require(hasPassed(exposure.closingTime)); |
269 | - | |
269 | + | |
270 | - | exposure.state = State.Closed; |
270 | + | exposure.state = State.Closed; |
271 | - | exposure.finalValue = msg.value; |
271 | + | exposure.finalValue = msg.value; |
272 | - | |
272 | + | |
273 | - | ExposureClosed({ |
273 | + | ExposureClosed({ |
274 | - | id: id, |
274 | + | id: id, |
275 | - | account: exposure.account, |
275 | + | account: exposure.account, |
276 | - | initialValue: exposure.initialValue, |
276 | + | initialValue: exposure.initialValue, |
277 | - | finalValue: exposure.finalValue |
277 | + | finalValue: exposure.finalValue |
278 | - | }); |
278 | + | }); |
279 | - | } |
279 | + | } |
280 | - | |
280 | + | |
281 | - | function settle(bytes32 id) public returns (uint256 finalValue) { |
281 | + | function settle(bytes32 id) public returns (uint256 finalValue) { |
282 | - | Exposure storage exposure = exposures[id]; |
282 | + | Exposure storage exposure = exposures[id]; |
283 | - | require(msg.sender == exposure.account); |
283 | + | require(msg.sender == exposure.account); |
284 | - | require(exposure.state == State.Closed); |
284 | + | require(exposure.state == State.Closed); |
285 | - | |
285 | + | |
286 | - | finalValue = exposure.finalValue; |
286 | + | finalValue = exposure.finalValue; |
287 | - | delete exposures[id]; |
287 | + | delete exposures[id]; |
288 | - | |
288 | + | |
289 | - | msg.sender.transfer(finalValue); |
289 | + | msg.sender.transfer(finalValue); |
290 | - | |
290 | + | |
291 | - | ExposureSettled({ |
291 | + | ExposureSettled({ |
292 | - | id: id, |
292 | + | id: id, |
293 | - | account: msg.sender, |
293 | + | account: msg.sender, |
294 | - | value: finalValue |
294 | + | value: finalValue |
295 | - | }); |
295 | + | }); |
296 | - | } |
296 | + | } |
297 | - | |
297 | + | |
298 | - | //--- Public constant functions |
298 | + | //--- Public constant functions |
299 | - | |
299 | + | |
300 | - | function status(bytes32 id) |
300 | + | function status(bytes32 id) |
301 | - | public |
301 | + | public |
302 | - | constant |
302 | + | constant |
303 | - | returns (uint8 state) |
303 | + | returns (uint8 state) |
304 | - | { |
304 | + | { |
305 | - | Exposure storage exposure = exposures[id]; |
305 | + | Exposure storage exposure = exposures[id]; |
306 | - | state = uint8(exposure.state); |
306 | + | state = uint8(exposure.state); |
307 | - | |
307 | + | |
308 | - | if (exposure.state == State.Collected && hasPassed(exposure.closingTime)) { |
308 | + | if (exposure.state == State.Collected && hasPassed(exposure.closingTime)) { |
309 | - | state = uint8(State.Closing); |
309 | + | state = uint8(State.Closing); |
310 | - | } |
310 | + | } |
311 | - | } |
311 | + | } |
312 | - | |
312 | + | |
313 | - | function exists(bytes32 id) public constant returns (bool) { |
313 | + | function exists(bytes32 id) public constant returns (bool) { |
314 | - | return exposures[id].creationTime > 0; |
314 | + | return exposures[id].creationTime > 0; |
315 | - | } |
315 | + | } |
316 | - | |
316 | + | |
317 | - | function checkRatio(uint256 veriAmount, uint256 value) |
317 | + | function checkRatio(uint256 veriAmount, uint256 value) |
318 | - | public |
318 | + | public |
319 | - | constant |
319 | + | constant |
320 | - | returns (bool) |
320 | + | returns (bool) |
321 | - | { |
321 | + | { |
322 | - | uint256 expectedValue = ratio.mul(veriAmount).div(1 ether); |
322 | + | uint256 expectedValue = ratio.mul(veriAmount).div(1 ether); |
323 | - | return value == expectedValue; |
323 | + | return value == expectedValue; |
324 | - | } |
324 | + | } |
325 | - | |
325 | + | |
326 | - | function calculateId( |
326 | + | function calculateId( |
327 | - | uint256 veriAmount, |
327 | + | uint256 veriAmount, |
328 | - | uint256 value, |
328 | + | uint256 value, |
329 | - | uint32 duration, |
329 | + | uint32 duration, |
330 | - | uint256 nonce |
330 | + | uint256 nonce |
331 | - | ) |
331 | + | ) |
332 | - | public |
332 | + | public |
333 | - | constant |
333 | + | constant |
334 | - | returns (bytes32) |
334 | + | returns (bytes32) |
335 | - | { |
335 | + | { |
336 | - | return sha256( |
336 | + | return sha256( |
337 | - | this, |
337 | + | this, |
338 | - | msg.sender, |
338 | + | msg.sender, |
339 | - | value, |
339 | + | value, |
340 | - | veriAmount, |
340 | + | veriAmount, |
341 | - | duration, |
341 | + | duration, |
342 | - | nonce |
342 | + | nonce |
343 | - | ); |
343 | + | ); |
344 | - | } |
344 | + | } |
345 | - | |
345 | + | |
346 | - | //--- Fallback function |
346 | + | //--- Fallback function |
347 | - | |
347 | + | |
348 | - | function() public payable { |
348 | + | function() public payable { |
349 | - | // accept Ether deposits |
349 | + | // accept Ether deposits |
350 | - | } |
350 | + | } |
351 | - | |
351 | + | |
352 | - | //--- Private functions |
352 | + | //--- Private functions |
353 | - | |
353 | + | |
354 | - | function forwardTokens(uint256 veriAmount) private { |
354 | + | function forwardTokens(uint256 veriAmount) private { |
355 | - | require(veToken.transferFrom(msg.sender, this, veriAmount)); |
355 | + | require(veToken.transferFrom(msg.sender, this, veriAmount)); |
356 | - | require(veToken.approve(portfolio, veriAmount)); |
356 | + | require(veToken.approve(portfolio, veriAmount)); |
357 | - | } |
357 | + | } |
358 | - | |
358 | + | |
359 | - | function openExposure(bytes32 id, uint256 veriAmount, uint32 duration) private constant { |
359 | + | function openExposure(bytes32 id, uint256 veriAmount, uint32 duration) private constant { |
360 | - | uint64 creationTime = uint64(block.timestamp); |
360 | + | uint64 creationTime = uint64(block.timestamp); |
361 | - | uint64 closingTime = uint64(block.timestamp.add(duration)); |
361 | + | uint64 closingTime = uint64(block.timestamp.add(duration)); |
362 | - | |
362 | + | |
363 | - | exposures[id] = Exposure({ |
363 | + | exposures[id] = Exposure({ |
364 | - | account: msg.sender, |
364 | + | account: msg.sender, |
365 | - | veriAmount: veriAmount, |
365 | + | veriAmount: veriAmount, |
366 | - | initialValue: msg.value, |
366 | + | initialValue: msg.value, |
367 | - | finalValue: 0, |
367 | + | finalValue: 0, |
368 | - | creationTime: creationTime, |
368 | + | creationTime: creationTime, |
369 | - | closingTime: closingTime, |
369 | + | closingTime: closingTime, |
370 | - | state: State.Open |
370 | + | state: State.Open |
371 | - | }); |
371 | + | }); |
372 | - | |
372 | + | |
373 | - | ExposureOpened({ |
373 | + | ExposureOpened({ |
374 | - | id: id, |
374 | + | id: id, |
375 | - | account: msg.sender, |
375 | + | account: msg.sender, |
376 | - | creationTime: creationTime, |
376 | + | creationTime: creationTime, |
377 | - | closingTime: closingTime, |
377 | + | closingTime: closingTime, |
378 | - | veriAmount: veriAmount, |
378 | + | veriAmount: veriAmount, |
379 | - | value: msg.value |
379 | + | value: msg.value |
380 | - | }); |
380 | + | }); |
381 | - | } |
381 | + | } |
382 | - | |
382 | + | |
383 | - | //--- Private constant functions |
383 | + | //--- Private constant functions |
384 | - | |
384 | + | |
385 | - | function hasPassed(uint64 time) |
385 | + | function hasPassed(uint64 time) |
386 | - | private |
386 | + | private |
387 | - | constant |
387 | + | constant |
388 | - | returns (bool) |
388 | + | returns (bool) |
389 | - | { |
389 | + | { |
390 | - | return block.timestamp >= time; |
390 | + | return block.timestamp >= time; |
391 | - | } |
391 | + | } |
392 | } | |
393 | - | |
393 | + | |
394 | - | contract VeRent is TokenDestructible { |
394 | + | contract VeRent is TokenDestructible { |
395 | - | |
395 | + | |
396 | - | //--- Definitions |
396 | + | //--- Definitions |
397 | - | |
397 | + | |
398 | - | using SafeMath for uint256; |
398 | + | using SafeMath for uint256; |
399 | - | |
399 | + | |
400 | - | struct VeriOffer { |
400 | + | struct VeriOffer { |
401 | - | address account; |
401 | + | address account; |
402 | - | uint256 veriAmount; |
402 | + | uint256 veriAmount; |
403 | - | uint256 price; |
403 | + | uint256 price; |
404 | - | uint32 duration; |
404 | + | uint32 duration; |
405 | - | uint64 expiration; |
405 | + | uint64 expiration; |
406 | - | } |
406 | + | } |
407 | - | |
407 | + | |
408 | - | struct EtherOffer { |
408 | + | struct EtherOffer { |
409 | - | address account; |
409 | + | address account; |
410 | - | uint256 veriAmount; |
410 | + | uint256 veriAmount; |
411 | - | uint256 value; |
411 | + | uint256 value; |
412 | - | uint256 price; |
412 | + | uint256 price; |
413 | - | uint32 duration; |
413 | + | uint32 duration; |
414 | - | uint64 expiration; |
414 | + | uint64 expiration; |
415 | - | } |
415 | + | } |
416 | - | |
416 | + | |
417 | - | struct VeriIndex { |
417 | + | struct VeriIndex { |
418 | - | mapping (bytes32 => VeriBucket) buckets; |
418 | + | mapping (bytes32 => VeriBucket) buckets; |
419 | - | } |
419 | + | } |
420 | - | |
420 | + | |
421 | - | struct EtherIndex { |
421 | + | struct EtherIndex { |
422 | - | mapping (bytes32 => EtherBucket) buckets; |
422 | + | mapping (bytes32 => EtherBucket) buckets; |
423 | - | } |
423 | + | } |
424 | - | |
424 | + | |
425 | - | struct VeriBucket { |
425 | + | struct VeriBucket { |
426 | - | bytes32[] ids; |
426 | + | bytes32[] ids; |
427 | - | } |
427 | + | } |
428 | - | |
428 | + | |
429 | - | struct EtherBucket { |
429 | + | struct EtherBucket { |
430 | - | bytes32[] ids; |
430 | + | bytes32[] ids; |
431 | - | } |
431 | + | } |
432 | - | |
432 | + | |
433 | - | //--- Storage |
433 | + | //--- Storage |
434 | - | |
434 | + | |
435 | - | VeritaseumToken public veToken; |
435 | + | VeritaseumToken public veToken; |
436 | - | VeRentExposure public veRentExposure; |
436 | + | VeRentExposure public veRentExposure; |
437 | - | |
437 | + | |
438 | - | mapping (bytes32 => VeriOffer) public veriOffers; |
438 | + | mapping (bytes32 => VeriOffer) public veriOffers; |
439 | - | mapping (bytes32 => EtherOffer) public etherOffers; |
439 | + | mapping (bytes32 => EtherOffer) public etherOffers; |
440 | - | |
440 | + | |
441 | - | EtherIndex private etherIndex; |
441 | + | EtherIndex private etherIndex; |
442 | - | VeriIndex private veriIndex; |
442 | + | VeriIndex private veriIndex; |
443 | - | |
443 | + | |
444 | - | //--- Constructor |
444 | + | //--- Constructor |
445 | - | |
445 | + | |
446 | - | function VeRent(VeritaseumToken _veToken, VeRentExposure _veRentExposure) { |
446 | + | function VeRent(VeritaseumToken _veToken, VeRentExposure _veRentExposure) { |
447 | - | require(_veToken != address(0)); |
447 | + | require(_veToken != address(0)); |
448 | - | require(_veRentExposure != address(0)); |
448 | + | require(_veRentExposure != address(0)); |
449 | - | |
449 | + | |
450 | - | veToken = _veToken; |
450 | + | veToken = _veToken; |
451 | - | veRentExposure = _veRentExposure; |
451 | + | veRentExposure = _veRentExposure; |
452 | - | } |
452 | + | } |
453 | - | |
453 | + | |
454 | - | //--- Accessors |
454 | + | //--- Accessors |
455 | - | |
455 | + | |
456 | - | function ratio() public constant returns (uint256) { |
456 | + | function ratio() public constant returns (uint256) { |
457 | - | return veRentExposure.ratio(); |
457 | + | return veRentExposure.ratio(); |
458 | - | } |
458 | + | } |
459 | - | |
459 | + | |
460 | - | function minVeriAmount() public constant returns (uint256) { |
460 | + | function minVeriAmount() public constant returns (uint256) { |
461 | - | return veRentExposure.minVeriAmount(); |
461 | + | return veRentExposure.minVeriAmount(); |
462 | - | } |
462 | + | } |
463 | - | |
463 | + | |
464 | - | function maxVeriAmount() public constant returns (uint256) { |
464 | + | function maxVeriAmount() public constant returns (uint256) { |
465 | - | return veRentExposure.maxVeriAmount(); |
465 | + | return veRentExposure.maxVeriAmount(); |
466 | - | } |
466 | + | } |
467 | - | |
467 | + | |
468 | - | function minDuration() public constant returns (uint32) { |
468 | + | function minDuration() public constant returns (uint32) { |
469 | - | return veRentExposure.minDuration(); |
469 | + | return veRentExposure.minDuration(); |
470 | - | } |
470 | + | } |
471 | - | |
471 | + | |
472 | - | function maxDuration() public constant returns (uint32) { |
472 | + | function maxDuration() public constant returns (uint32) { |
473 | - | return veRentExposure.maxDuration(); |
473 | + | return veRentExposure.maxDuration(); |
474 | - | } |
474 | + | } |
475 | - | |
475 | + | |
476 | - | function minPrice() public constant returns (uint256) { |
476 | + | function minPrice() public constant returns (uint256) { |
477 | - | return veRentExposure.minPrice(); |
477 | + | return veRentExposure.minPrice(); |
478 | - | } |
478 | + | } |
479 | - | |
479 | + | |
480 | - | function maxPrice() public constant returns (uint256) { |
480 | + | function maxPrice() public constant returns (uint256) { |
481 | - | return veRentExposure.maxPrice(); |
481 | + | return veRentExposure.maxPrice(); |
482 | - | } |
482 | + | } |
483 | - | |
483 | + | |
484 | - | //--- Events |
484 | + | //--- Events |
485 | - | |
485 | + | |
486 | - | event VeriOfferAdded( |
486 | + | event VeriOfferAdded( |
487 | - | bytes32 indexed id, |
487 | + | bytes32 indexed id, |
488 | - | address indexed account, |
488 | + | address indexed account, |
489 | - | uint256 veriAmount, |
489 | + | uint256 veriAmount, |
490 | - | uint256 price, |
490 | + | uint256 price, |
491 | - | uint32 duration, |
491 | + | uint32 duration, |
492 | - | uint64 expiration |
492 | + | uint64 expiration |
493 | - | ); |
493 | + | ); |
494 | - | |
494 | + | |
495 | - | event EtherOfferAdded( |
495 | + | event EtherOfferAdded( |
496 | - | bytes32 indexed id, |
496 | + | bytes32 indexed id, |
497 | - | address indexed account, |
497 | + | address indexed account, |
498 | - | uint256 veriAmount, |
498 | + | uint256 veriAmount, |
499 | - | uint256 value, |
499 | + | uint256 value, |
500 | - | uint256 price, |
500 | + | uint256 price, |
501 | - | uint32 duration, |
501 | + | uint32 duration, |
502 | - | uint64 expiration |
502 | + | uint64 expiration |
503 | - | ); |
503 | + | ); |
504 | - | |
504 | + | |
505 | - | event DealMade( |
505 | + | event DealMade( |
506 | - | bytes32 id, |
506 | + | bytes32 id, |
507 | - | bytes32 veriId, |
507 | + | bytes32 veriId, |
508 | - | bytes32 etherId, |
508 | + | bytes32 etherId, |
509 | - | address indexed veriAccount, |
509 | + | address indexed veriAccount, |
510 | - | address indexed etherAccount, |
510 | + | address indexed etherAccount, |
511 | - | uint256 veriAmount, |
511 | + | uint256 veriAmount, |
512 | - | uint256 value, |
512 | + | uint256 value, |
513 | - | uint256 price, |
513 | + | uint256 price, |
514 | - | uint32 duration |
514 | + | uint32 duration |
515 | - | ); |
515 | + | ); |
516 | - | |
516 | + | |
517 | - | event VeriOfferCancelled(bytes32 indexed id); |
517 | + | event VeriOfferCancelled(bytes32 indexed id); |
518 | - | event EtherOfferCancelled(bytes32 indexed id); |
518 | + | event EtherOfferCancelled(bytes32 indexed id); |
519 | - | |
519 | + | |
520 | - | //--- Public functions |
520 | + | //--- Public functions |
521 | - | |
521 | + | |
522 | - | function addVeriOffer( |
522 | + | function addVeriOffer( |
523 | - | uint256 veriAmount, |
523 | + | uint256 veriAmount, |
524 | - | uint256 price, |
524 | + | uint256 price, |
525 | - | uint32 duration, |
525 | + | uint32 duration, |
526 | - | uint64 expiration, |
526 | + | uint64 expiration, |
527 | - | uint256 nonce |
527 | + | uint256 nonce |
528 | - | ) |
528 | + | ) |
529 | - | public |
529 | + | public |
530 | - | { |
530 | + | { |
531 | - | require(veriAmount >= minVeriAmount() && veriAmount <= maxVeriAmount()); |
531 | + | require(veriAmount >= minVeriAmount() && veriAmount <= maxVeriAmount()); |
532 | - | require(price >= minPrice() && price <= maxPrice()); |
532 | + | require(price >= minPrice() && price <= maxPrice()); |
533 | - | require(duration >= minDuration() && duration <= maxDuration()); |
533 | + | require(duration >= minDuration() && duration <= maxDuration()); |
534 | - | require(isDefaultOrFuture(expiration)); |
534 | + | require(isDefaultOrFuture(expiration)); |
535 | - | |
535 | + | |
536 | - | // remember to call approve(...) on Veritaseum Token before calling this function |
536 | + | // remember to call approve(...) on Veritaseum Token before calling this function |
537 | - | require(veToken.transferFrom(msg.sender, this, veriAmount)); |
537 | + | require(veToken.transferFrom(msg.sender, this, veriAmount)); |
538 | - | |
538 | + | |
539 | - | bytes32 veriId = calculateOfferId({ |
539 | + | bytes32 veriId = calculateOfferId({ |
540 | - | veriAmount: veriAmount, |
540 | + | veriAmount: veriAmount, |
541 | - | value: 0, |
541 | + | value: 0, |
542 | - | price: price, |
542 | + | price: price, |
543 | - | duration: duration, |
543 | + | duration: duration, |
544 | - | expiration: expiration, |
544 | + | expiration: expiration, |
545 | - | nonce: nonce |
545 | + | nonce: nonce |
546 | - | }); |
546 | + | }); |
547 | - | |
547 | + | |
548 | - | require(!veriOfferExists(veriId)); |
548 | + | require(!veriOfferExists(veriId)); |
549 | - | |
549 | + | |
550 | - | VeriOfferAdded({ |
550 | + | VeriOfferAdded({ |
551 | - | id: veriId, |
551 | + | id: veriId, |
552 | - | account: msg.sender, |
552 | + | account: msg.sender, |
553 | - | veriAmount: veriAmount, |
553 | + | veriAmount: veriAmount, |
554 | - | price: price, |
554 | + | price: price, |
555 | - | duration: duration, |
555 | + | duration: duration, |
556 | - | expiration: expiration |
556 | + | expiration: expiration |
557 | - | }); |
557 | + | }); |
558 | - | |
558 | + | |
559 | - | bytes32 bucketKey = calculateBucketKey({ |
559 | + | bytes32 bucketKey = calculateBucketKey({ |
560 | - | veriAmount: veriAmount, |
560 | + | veriAmount: veriAmount, |
561 | - | price: price, |
561 | + | price: price, |
562 | - | duration: duration |
562 | + | duration: duration |
563 | - | }); |
563 | + | }); |
564 | - | |
564 | + | |
565 | - | if (!matchEtherOffer(bucketKey, veriId, nonce)) { |
565 | + | if (!matchEtherOffer(bucketKey, veriId, nonce)) { |
566 | - | saveVeriOffer({ |
566 | + | saveVeriOffer({ |
567 | - | bucketKey: bucketKey, |
567 | + | bucketKey: bucketKey, |
568 | - | veriId: veriId, |
568 | + | veriId: veriId, |
569 | - | veriAmount: veriAmount, |
569 | + | veriAmount: veriAmount, |
570 | - | price: price, |
570 | + | price: price, |
571 | - | duration: duration, |
571 | + | duration: duration, |
572 | - | expiration: expiration |
572 | + | expiration: expiration |
573 | - | }); |
573 | + | }); |
574 | - | } |
574 | + | } |
575 | - | } |
575 | + | } |
576 | - | |
576 | + | |
577 | - | function addEtherOffer( |
577 | + | function addEtherOffer( |
578 | - | uint256 veriAmount, |
578 | + | uint256 veriAmount, |
579 | - | uint256 price, |
579 | + | uint256 price, |
580 | - | uint32 duration, |
580 | + | uint32 duration, |
581 | - | uint64 expiration, |
581 | + | uint64 expiration, |
582 | - | uint256 nonce |
582 | + | uint256 nonce |
583 | - | ) |
583 | + | ) |
584 | - | public |
584 | + | public |
585 | - | payable |
585 | + | payable |
586 | - | { |
586 | + | { |
587 | - | require(price >= minPrice() && price <= maxPrice()); |
587 | + | require(price >= minPrice() && price <= maxPrice()); |
588 | - | require(duration >= minDuration() && duration <= maxDuration()); |
588 | + | require(duration >= minDuration() && duration <= maxDuration()); |
589 | - | require(isDefaultOrFuture(expiration)); |
589 | + | require(isDefaultOrFuture(expiration)); |
590 | - | require(checkRatio(veriAmount, msg.value)); |
590 | + | require(checkRatio(veriAmount, msg.value)); |
591 | - | |
591 | + | |
592 | - | bytes32 etherId = calculateOfferId({ |
592 | + | bytes32 etherId = calculateOfferId({ |
593 | - | veriAmount: veriAmount, |
593 | + | veriAmount: veriAmount, |
594 | - | value: msg.value, |
594 | + | value: msg.value, |
595 | - | price: price, |
595 | + | price: price, |
596 | - | duration: duration, |
596 | + | duration: duration, |
597 | - | expiration: expiration, |
597 | + | expiration: expiration, |
598 | - | nonce: nonce |
598 | + | nonce: nonce |
599 | - | }); |
599 | + | }); |
600 | - | |
600 | + | |
601 | - | require(!etherOfferExists(etherId)); |
601 | + | require(!etherOfferExists(etherId)); |
602 | - | |
602 | + | |
603 | - | EtherOfferAdded({ |
603 | + | EtherOfferAdded({ |
604 | - | id: etherId, |
604 | + | id: etherId, |
605 | - | account: msg.sender, |
605 | + | account: msg.sender, |
606 | - | veriAmount: veriAmount, |
606 | + | veriAmount: veriAmount, |
607 | - | value: msg.value, |
607 | + | value: msg.value, |
608 | - | price: price, |
608 | + | price: price, |
609 | - | duration: duration, |
609 | + | duration: duration, |
610 | - | expiration: expiration |
610 | + | expiration: expiration |
611 | - | }); |
611 | + | }); |
612 | - | |
612 | + | |
613 | - | bytes32 bucketKey = calculateBucketKey({ |
613 | + | bytes32 bucketKey = calculateBucketKey({ |
614 | - | veriAmount: veriAmount, |
614 | + | veriAmount: veriAmount, |
615 | - | price: price, |
615 | + | price: price, |
616 | - | duration: duration |
616 | + | duration: duration |
617 | - | }); |
617 | + | }); |
618 | - | |
618 | + | |
619 | - | if (!matchVeriOffer(bucketKey, etherId, nonce)) { |
619 | + | if (!matchVeriOffer(bucketKey, etherId, nonce)) { |
620 | - | saveEtherOffer({ |
620 | + | saveEtherOffer({ |
621 | - | bucketKey: bucketKey, |
621 | + | bucketKey: bucketKey, |
622 | - | etherId: etherId, |
622 | + | etherId: etherId, |
623 | - | veriAmount: veriAmount, |
623 | + | veriAmount: veriAmount, |
624 | - | price: price, |
624 | + | price: price, |
625 | - | duration: duration, |
625 | + | duration: duration, |
626 | - | expiration: expiration |
626 | + | expiration: expiration |
627 | - | }); |
627 | + | }); |
628 | - | } |
628 | + | } |
629 | - | } |
629 | + | } |
630 | - | |
630 | + | |
631 | - | function cancelVeriOffer(bytes32 veriId) public { |
631 | + | function cancelVeriOffer(bytes32 veriId) public { |
632 | - | VeriOffer storage offer = veriOffers[veriId]; |
632 | + | VeriOffer storage offer = veriOffers[veriId]; |
633 | - | require(msg.sender == offer.account || msg.sender == owner); |
633 | + | require(msg.sender == offer.account || msg.sender == owner); |
634 | - | |
634 | + | |
635 | - | bytes32 bucketKey = calculateBucketKey({ |
635 | + | bytes32 bucketKey = calculateBucketKey({ |
636 | - | veriAmount: offer.veriAmount, |
636 | + | veriAmount: offer.veriAmount, |
637 | - | price: offer.price, |
637 | + | price: offer.price, |
638 | - | duration: offer.duration |
638 | + | duration: offer.duration |
639 | - | }); |
639 | + | }); |
640 | - | VeriBucket storage veriBucket = veriIndex.buckets[bucketKey]; |
640 | + | VeriBucket storage veriBucket = veriIndex.buckets[bucketKey]; |
641 | - | |
641 | + | |
642 | - | // copy before deletion |
642 | + | // copy before deletion |
643 | - | uint256 veriAmount = offer.veriAmount; |
643 | + | uint256 veriAmount = offer.veriAmount; |
644 | - | address veriAccount = offer.account; |
644 | + | address veriAccount = offer.account; |
645 | - | |
645 | + | |
646 | - | removeVeriOffer(veriBucket, veriId); |
646 | + | removeVeriOffer(veriBucket, veriId); |
647 | - | paybackTokens(veriAccount, veriAmount); |
647 | + | paybackTokens(veriAccount, veriAmount); |
648 | - | |
648 | + | |
649 | - | VeriOfferCancelled(veriId); |
649 | + | VeriOfferCancelled(veriId); |
650 | - | } |
650 | + | } |
651 | - | |
651 | + | |
652 | - | function cancelEtherOffer(bytes32 etherId) public { |
652 | + | function cancelEtherOffer(bytes32 etherId) public { |
653 | - | EtherOffer storage offer = etherOffers[etherId]; |
653 | + | EtherOffer storage offer = etherOffers[etherId]; |
654 | - | require(msg.sender == offer.account || msg.sender == owner); |
654 | + | require(msg.sender == offer.account || msg.sender == owner); |
655 | - | |
655 | + | |
656 | - | bytes32 bucketKey = calculateBucketKey({ |
656 | + | bytes32 bucketKey = calculateBucketKey({ |
657 | - | veriAmount: offer.veriAmount, |
657 | + | veriAmount: offer.veriAmount, |
658 | - | price: offer.price, |
658 | + | price: offer.price, |
659 | - | duration: offer.duration |
659 | + | duration: offer.duration |
660 | - | }); |
660 | + | }); |
661 | - | EtherBucket storage etherBucket = etherIndex.buckets[bucketKey]; |
661 | + | EtherBucket storage etherBucket = etherIndex.buckets[bucketKey]; |
662 | - | |
662 | + | |
663 | - | // copy before deletion |
663 | + | // copy before deletion |
664 | - | uint256 value = offer.value; |
664 | + | uint256 value = offer.value; |
665 | - | address etherAccount = offer.account; |
665 | + | address etherAccount = offer.account; |
666 | - | |
666 | + | |
667 | - | removeEtherOffer(etherBucket, etherId); |
667 | + | removeEtherOffer(etherBucket, etherId); |
668 | - | paybackEther(etherAccount, value); |
668 | + | paybackEther(etherAccount, value); |
669 | - | |
669 | + | |
670 | - | EtherOfferCancelled(etherId); |
670 | + | EtherOfferCancelled(etherId); |
671 | - | } |
671 | + | } |
672 | - | |
672 | + | |
673 | - | //--- Public constant functions |
673 | + | //--- Public constant functions |
674 | - | |
674 | + | |
675 | - | function checkRatio(uint256 veriAmount, uint256 value) |
675 | + | function checkRatio(uint256 veriAmount, uint256 value) |
676 | - | public |
676 | + | public |
677 | - | constant |
677 | + | constant |
678 | - | returns (bool) |
678 | + | returns (bool) |
679 | - | { |
679 | + | { |
680 | - | return veRentExposure.checkRatio(veriAmount, value); |
680 | + | return veRentExposure.checkRatio(veriAmount, value); |
681 | - | } |
681 | + | } |
682 | - | |
682 | + | |
683 | - | function veriOfferExists(bytes32 veriId) |
683 | + | function veriOfferExists(bytes32 veriId) |
684 | - | public |
684 | + | public |
685 | - | constant |
685 | + | constant |
686 | - | returns (bool) |
686 | + | returns (bool) |
687 | - | { |
687 | + | { |
688 | - | return veriOffers[veriId].account != address(0); |
688 | + | return veriOffers[veriId].account != address(0); |
689 | - | } |
689 | + | } |
690 | - | |
690 | + | |
691 | - | function etherOfferExists(bytes32 etherId) |
691 | + | function etherOfferExists(bytes32 etherId) |
692 | - | public |
692 | + | public |
693 | - | constant |
693 | + | constant |
694 | - | returns (bool) |
694 | + | returns (bool) |
695 | - | { |
695 | + | { |
696 | - | return etherOffers[etherId].account != address(0); |
696 | + | return etherOffers[etherId].account != address(0); |
697 | - | } |
697 | + | } |
698 | - | |
698 | + | |
699 | - | //--- Fallback function |
699 | + | //--- Fallback function |
700 | - | |
700 | + | |
701 | - | function() { |
701 | + | function() { |
702 | - | // prevent accidental sending Ether |
702 | + | // prevent accidental sending Ether |
703 | - | revert(); |
703 | + | revert(); |
704 | - | } |
704 | + | } |
705 | - | |
705 | + | |
706 | - | //--- Private functions |
706 | + | //--- Private functions |
707 | - | |
707 | + | |
708 | - | function matchVeriOffer(bytes32 bucketKey, bytes32 etherId, uint256 nonce) |
708 | + | function matchVeriOffer(bytes32 bucketKey, bytes32 etherId, uint256 nonce) |
709 | - | private |
709 | + | private |
710 | - | returns (bool) |
710 | + | returns (bool) |
711 | - | { |
711 | + | { |
712 | - | VeriBucket storage veriBucket = veriIndex.buckets[bucketKey]; |
712 | + | VeriBucket storage veriBucket = veriIndex.buckets[bucketKey]; |
713 | - | |
713 | + | |
714 | - | for (uint256 i = 0; i < veriBucket.ids.length; i++) { |
714 | + | for (uint256 i = 0; i < veriBucket.ids.length; i++) { |
715 | - | bytes32 matchingVeriId = veriBucket.ids[i]; |
715 | + | bytes32 matchingVeriId = veriBucket.ids[i]; |
716 | - | |
716 | + | |
717 | - | VeriOffer storage matchingOffer = veriOffers[matchingVeriId]; |
717 | + | VeriOffer storage matchingOffer = veriOffers[matchingVeriId]; |
718 | - | if (isDefaultOrFuture(matchingOffer.expiration)) { |
718 | + | if (isDefaultOrFuture(matchingOffer.expiration)) { |
719 | - | openRentExposure({ |
719 | + | openRentExposure({ |
720 | - | veriId: matchingVeriId, |
720 | + | veriId: matchingVeriId, |
721 | - | etherId: etherId, |
721 | + | etherId: etherId, |
722 | - | veriAccount: matchingOffer.account, |
722 | + | veriAccount: matchingOffer.account, |
723 | - | etherAccount: msg.sender, |
723 | + | etherAccount: msg.sender, |
724 | - | veriAmount: matchingOffer.veriAmount, |
724 | + | veriAmount: matchingOffer.veriAmount, |
725 | - | value: msg.value, |
725 | + | value: msg.value, |
726 | - | price: matchingOffer.price, |
726 | + | price: matchingOffer.price, |
727 | - | duration: matchingOffer.duration, |
727 | + | duration: matchingOffer.duration, |
728 | - | nonce: nonce |
728 | + | nonce: nonce |
729 | - | }); |
729 | + | }); |
730 | - | |
730 | + | |
731 | - | removeVeriOffer(veriBucket, matchingVeriId); |
731 | + | removeVeriOffer(veriBucket, matchingVeriId); |
732 | - | return true; |
732 | + | return true; |
733 | - | } |
733 | + | } |
734 | - | } |
734 | + | } |
735 | - | return false; |
735 | + | return false; |
736 | - | } |
736 | + | } |
737 | - | |
737 | + | |
738 | - | function matchEtherOffer(bytes32 bucketKey, bytes32 veriId, uint256 nonce) |
738 | + | function matchEtherOffer(bytes32 bucketKey, bytes32 veriId, uint256 nonce) |
739 | - | private |
739 | + | private |
740 | - | returns (bool) |
740 | + | returns (bool) |
741 | - | { |
741 | + | { |
742 | - | EtherBucket storage etherBucket = etherIndex.buckets[bucketKey]; |
742 | + | EtherBucket storage etherBucket = etherIndex.buckets[bucketKey]; |
743 | - | |
743 | + | |
744 | - | for (uint256 i = 0; i < etherBucket.ids.length; i++) { |
744 | + | for (uint256 i = 0; i < etherBucket.ids.length; i++) { |
745 | - | bytes32 matchingEtherId = etherBucket.ids[i]; |
745 | + | bytes32 matchingEtherId = etherBucket.ids[i]; |
746 | - | |
746 | + | |
747 | - | EtherOffer storage matchingOffer = etherOffers[matchingEtherId]; |
747 | + | EtherOffer storage matchingOffer = etherOffers[matchingEtherId]; |
748 | - | if (isDefaultOrFuture(matchingOffer.expiration)) { |
748 | + | if (isDefaultOrFuture(matchingOffer.expiration)) { |
749 | - | openRentExposure({ |
749 | + | openRentExposure({ |
750 | - | veriId: veriId, |
750 | + | veriId: veriId, |
751 | - | etherId: matchingEtherId, |
751 | + | etherId: matchingEtherId, |
752 | - | veriAccount: msg.sender, |
752 | + | veriAccount: msg.sender, |
753 | - | etherAccount: matchingOffer.account, |
753 | + | etherAccount: matchingOffer.account, |
754 | - | veriAmount: matchingOffer.veriAmount, |
754 | + | veriAmount: matchingOffer.veriAmount, |
755 | - | value: matchingOffer.value, |
755 | + | value: matchingOffer.value, |
756 | - | price: matchingOffer.price, |
756 | + | price: matchingOffer.price, |
757 | - | duration: matchingOffer.duration, |
757 | + | duration: matchingOffer.duration, |
758 | - | nonce: nonce |
758 | + | nonce: nonce |
759 | - | }); |
759 | + | }); |
760 | - | |
760 | + | |
761 | - | removeEtherOffer(etherBucket, matchingEtherId); |
761 | + | removeEtherOffer(etherBucket, matchingEtherId); |
762 | - | return true; |
762 | + | return true; |
763 | - | } |
763 | + | } |
764 | - | } |
764 | + | } |
765 | - | return false; |
765 | + | return false; |
766 | - | } |
766 | + | } |
767 | - | |
767 | + | |
768 | - | function saveVeriOffer( |
768 | + | function saveVeriOffer( |
769 | - | bytes32 bucketKey, |
769 | + | bytes32 bucketKey, |
770 | - | bytes32 veriId, |
770 | + | bytes32 veriId, |
771 | - | uint256 veriAmount, |
771 | + | uint256 veriAmount, |
772 | - | uint256 price, |
772 | + | uint256 price, |
773 | - | uint32 duration, |
773 | + | uint32 duration, |
774 | - | uint64 expiration |
774 | + | uint64 expiration |
775 | - | ) |
775 | + | ) |
776 | - | private |
776 | + | private |
777 | - | { |
777 | + | { |
778 | - | VeriBucket storage veriBucket = veriIndex.buckets[bucketKey]; |
778 | + | VeriBucket storage veriBucket = veriIndex.buckets[bucketKey]; |
779 | - | veriBucket.ids.push(veriId); |
779 | + | veriBucket.ids.push(veriId); |
780 | - | |
780 | + | |
781 | - | veriOffers[veriId] = VeriOffer({ |
781 | + | veriOffers[veriId] = VeriOffer({ |
782 | - | account: msg.sender, |
782 | + | account: msg.sender, |
783 | - | veriAmount: veriAmount, |
783 | + | veriAmount: veriAmount, |
784 | - | price: price, |
784 | + | price: price, |
785 | - | duration: duration, |
785 | + | duration: duration, |
786 | - | expiration: expiration |
786 | + | expiration: expiration |
787 | - | }); |
787 | + | }); |
788 | - | } |
788 | + | } |
789 | - | |
789 | + | |
790 | - | function saveEtherOffer( |
790 | + | function saveEtherOffer( |
791 | - | bytes32 bucketKey, |
791 | + | bytes32 bucketKey, |
792 | - | bytes32 etherId, |
792 | + | bytes32 etherId, |
793 | - | uint256 veriAmount, |
793 | + | uint256 veriAmount, |
794 | - | uint256 price, |
794 | + | uint256 price, |
795 | - | uint32 duration, |
795 | + | uint32 duration, |
796 | - | uint64 expiration |
796 | + | uint64 expiration |
797 | - | ) |
797 | + | ) |
798 | - | private |
798 | + | private |
799 | - | { |
799 | + | { |
800 | - | EtherBucket storage etherBucket = etherIndex.buckets[bucketKey]; |
800 | + | EtherBucket storage etherBucket = etherIndex.buckets[bucketKey]; |
801 | - | etherBucket.ids.push(etherId); |
801 | + | etherBucket.ids.push(etherId); |
802 | - | |
802 | + | |
803 | - | etherOffers[etherId] = EtherOffer({ |
803 | + | etherOffers[etherId] = EtherOffer({ |
804 | - | account: msg.sender, |
804 | + | account: msg.sender, |
805 | - | veriAmount: veriAmount, |
805 | + | veriAmount: veriAmount, |
806 | - | value: msg.value, |
806 | + | value: msg.value, |
807 | - | price: price, |
807 | + | price: price, |
808 | - | duration: duration, |
808 | + | duration: duration, |
809 | - | expiration: expiration |
809 | + | expiration: expiration |
810 | - | }); |
810 | + | }); |
811 | - | } |
811 | + | } |
812 | - | |
812 | + | |
813 | - | function openRentExposure( |
813 | + | function openRentExposure( |
814 | - | bytes32 veriId, |
814 | + | bytes32 veriId, |
815 | - | bytes32 etherId, |
815 | + | bytes32 etherId, |
816 | - | address veriAccount, |
816 | + | address veriAccount, |
817 | - | address etherAccount, |
817 | + | address etherAccount, |
818 | - | uint256 veriAmount, |
818 | + | uint256 veriAmount, |
819 | - | uint256 value, |
819 | + | uint256 value, |
820 | - | uint256 price, |
820 | + | uint256 price, |
821 | - | uint32 duration, |
821 | + | uint32 duration, |
822 | - | uint256 nonce |
822 | + | uint256 nonce |
823 | - | ) |
823 | + | ) |
824 | - | private |
824 | + | private |
825 | - | { |
825 | + | { |
826 | - | require(veToken.approve(veRentExposure, veriAmount)); |
826 | + | require(veToken.approve(veRentExposure, veriAmount)); |
827 | - | |
827 | + | |
828 | - | bytes32 id = veRentExposure.calculateId({ |
828 | + | bytes32 id = veRentExposure.calculateId({ |
829 | - | veriAmount: veriAmount, |
829 | + | veriAmount: veriAmount, |
830 | - | value: value, |
830 | + | value: value, |
831 | - | duration: duration, |
831 | + | duration: duration, |
832 | - | nonce: nonce |
832 | + | nonce: nonce |
833 | - | }); |
833 | + | }); |
834 | - | |
834 | + | |
835 | - | DealMade({ |
835 | + | DealMade({ |
836 | - | id: id, |
836 | + | id: id, |
837 | - | veriId: veriId, |
837 | + | veriId: veriId, |
838 | - | etherId: etherId, |
838 | + | etherId: etherId, |
839 | - | veriAccount: veriAccount, |
839 | + | veriAccount: veriAccount, |
840 | - | etherAccount: etherAccount, |
840 | + | etherAccount: etherAccount, |
841 | - | veriAmount: veriAmount, |
841 | + | veriAmount: veriAmount, |
842 | - | value: value, |
842 | + | value: value, |
843 | - | price: price, |
843 | + | price: price, |
844 | - | duration: duration |
844 | + | duration: duration |
845 | - | }); |
845 | + | }); |
846 | - | |
846 | + | |
847 | - | veRentExposure.open.value(value)({ |
847 | + | veRentExposure.open.value(value)({ |
848 | - | veriAccount: veriAccount, |
848 | + | veriAccount: veriAccount, |
849 | - | etherAccount: etherAccount, |
849 | + | etherAccount: etherAccount, |
850 | - | veriAmount: veriAmount, |
850 | + | veriAmount: veriAmount, |
851 | - | price: price, |
851 | + | price: price, |
852 | - | duration: duration, |
852 | + | duration: duration, |
853 | - | nonce: nonce |
853 | + | nonce: nonce |
854 | - | }); |
854 | + | }); |
855 | - | } |
855 | + | } |
856 | - | |
856 | + | |
857 | - | function removeVeriOffer(VeriBucket storage veriBucket, bytes32 veriId) private { |
857 | + | function removeVeriOffer(VeriBucket storage veriBucket, bytes32 veriId) private { |
858 | - | uint256 index = getIndex(veriBucket.ids, veriId); |
858 | + | uint256 index = getIndex(veriBucket.ids, veriId); |
859 | - | removeByIndex(veriBucket.ids, index); |
859 | + | removeByIndex(veriBucket.ids, index); |
860 | - | |
860 | + | |
861 | - | delete veriOffers[veriId]; |
861 | + | delete veriOffers[veriId]; |
862 | - | } |
862 | + | } |
863 | - | |
863 | + | |
864 | - | function removeEtherOffer(EtherBucket storage etherBucket, bytes32 etherId) private { |
864 | + | function removeEtherOffer(EtherBucket storage etherBucket, bytes32 etherId) private { |
865 | - | uint256 index = getIndex(etherBucket.ids, etherId); |
865 | + | uint256 index = getIndex(etherBucket.ids, etherId); |
866 | - | removeByIndex(etherBucket.ids, index); |
866 | + | removeByIndex(etherBucket.ids, index); |
867 | - | |
867 | + | |
868 | - | delete etherOffers[etherId]; |
868 | + | delete etherOffers[etherId]; |
869 | - | } |
869 | + | } |
870 | - | |
870 | + | |
871 | - | function paybackTokens(address account, uint256 veriAmount) private { |
871 | + | function paybackTokens(address account, uint256 veriAmount) private { |
872 | - | require(veToken.transfer(account, veriAmount)); |
872 | + | require(veToken.transfer(account, veriAmount)); |
873 | - | } |
873 | + | } |
874 | - | |
874 | + | |
875 | - | function paybackEther(address account, uint256 value) private { |
875 | + | function paybackEther(address account, uint256 value) private { |
876 | - | account.transfer(value); |
876 | + | account.transfer(value); |
877 | - | } |
877 | + | } |
878 | - | |
878 | + | |
879 | - | function removeByIndex(bytes32[] storage array, uint256 i) private { |
879 | + | function removeByIndex(bytes32[] storage array, uint256 i) private { |
880 | - | array[i] = array[array.length - 1]; |
880 | + | array[i] = array[array.length - 1]; |
881 | - | array.length--; |
881 | + | array.length--; |
882 | - | } |
882 | + | } |
883 | - | |
883 | + | |
884 | - | //--- Private constant functions |
884 | + | //--- Private constant functions |
885 | - | |
885 | + | |
886 | - | function calculateOfferId( |
886 | + | function calculateOfferId( |
887 | - | uint256 veriAmount, |
887 | + | uint256 veriAmount, |
888 | - | uint256 value, |
888 | + | uint256 value, |
889 | - | uint256 price, |
889 | + | uint256 price, |
890 | - | uint32 duration, |
890 | + | uint32 duration, |
891 | - | uint64 expiration, |
891 | + | uint64 expiration, |
892 | - | uint256 nonce |
892 | + | uint256 nonce |
893 | - | ) |
893 | + | ) |
894 | - | private |
894 | + | private |
895 | - | constant |
895 | + | constant |
896 | - | returns (bytes32) |
896 | + | returns (bytes32) |
897 | - | { |
897 | + | { |
898 | - | return sha256( |
898 | + | return sha256( |
899 | - | this, |
899 | + | this, |
900 | - | msg.sender, |
900 | + | msg.sender, |
901 | - | value, |
901 | + | value, |
902 | - | veriAmount, |
902 | + | veriAmount, |
903 | - | price, |
903 | + | price, |
904 | - | duration, |
904 | + | duration, |
905 | - | expiration, |
905 | + | expiration, |
906 | - | nonce |
906 | + | nonce |
907 | - | ); |
907 | + | ); |
908 | - | } |
908 | + | } |
909 | - | |
909 | + | |
910 | - | function calculateBucketKey( |
910 | + | function calculateBucketKey( |
911 | - | uint256 veriAmount, |
911 | + | uint256 veriAmount, |
912 | - | uint256 price, |
912 | + | uint256 price, |
913 | - | uint32 duration |
913 | + | uint32 duration |
914 | - | ) |
914 | + | ) |
915 | - | private |
915 | + | private |
916 | - | constant |
916 | + | constant |
917 | - | returns (bytes32) |
917 | + | returns (bytes32) |
918 | - | { |
918 | + | { |
919 | - | return sha256(veriAmount, price, duration); |
919 | + | return sha256(veriAmount, price, duration); |
920 | - | } |
920 | + | } |
921 | - | |
921 | + | |
922 | - | function getIndex(bytes32[] storage ids, bytes32 id) |
922 | + | function getIndex(bytes32[] storage ids, bytes32 id) |
923 | - | private |
923 | + | private |
924 | - | constant |
924 | + | constant |
925 | - | returns (uint256) |
925 | + | returns (uint256) |
926 | - | { |
926 | + | { |
927 | - | for (uint256 i = 0; i < ids.length; i++) { |
927 | + | for (uint256 i = 0; i < ids.length; i++) { |
928 | - | if (ids[i] == id) { |
928 | + | if (ids[i] == id) { |
929 | - | return i; |
929 | + | return i; |
930 | - | } |
930 | + | } |
931 | - | } |
931 | + | } |
932 | - | assert(false); |
932 | + | assert(false); |
933 | - | } |
933 | + | } |
934 | - | |
934 | + | |
935 | - | function isDefaultOrFuture(uint64 time) private constant returns (bool) { |
935 | + | function isDefaultOrFuture(uint64 time) private constant returns (bool) { |
936 | - | return time == 0 || time > block.timestamp; |
936 | + | return time == 0 || time > block.timestamp; |
937 | - | } |
937 | + | } |
938 | } | |
939 | - | |
939 | + | |
940 | - | contract VeRentExposure is TokenDestructible { |
940 | + | contract VeRentExposure is TokenDestructible { |
941 | - | |
941 | + | |
942 | - | //--- Definitions |
942 | + | //--- Definitions |
943 | - | |
943 | + | |
944 | - | using SafeMath for uint; |
944 | + | using SafeMath for uint; |
945 | - | |
945 | + | |
946 | - | struct RentExposure { |
946 | + | struct RentExposure { |
947 | - | bytes32 id; |
947 | + | bytes32 id; |
948 | - | address veriAccount; |
948 | + | address veriAccount; |
949 | - | address etherAccount; |
949 | + | address etherAccount; |
950 | - | uint256 veriAmount; |
950 | + | uint256 veriAmount; |
951 | - | uint256 price; |
951 | + | uint256 price; |
952 | - | uint256 initialValue; |
952 | + | uint256 initialValue; |
953 | - | uint256 finalValue; |
953 | + | uint256 finalValue; |
954 | - | bool veriSettled; |
954 | + | bool veriSettled; |
955 | - | bool etherSettled; |
955 | + | bool etherSettled; |
956 | - | } |
956 | + | } |
957 | - | |
957 | + | |
958 | - | uint256 constant public PRICE_100_PERCENT = 1 ether; |
958 | + | uint256 constant public PRICE_100_PERCENT = 1 ether; |
959 | - | |
959 | + | |
960 | - | //--- Storage |
960 | + | //--- Storage |
961 | - | |
961 | + | |
962 | - | VeritaseumToken public veToken; |
962 | + | VeritaseumToken public veToken; |
963 | - | VeExposure public veExposure; |
963 | + | VeExposure public veExposure; |
964 | - | |
964 | + | |
965 | - | uint256 public minPrice; |
965 | + | uint256 public minPrice; |
966 | - | uint256 public maxPrice; |
966 | + | uint256 public maxPrice; |
967 | - | |
967 | + | |
968 | - | mapping (bytes32 => RentExposure) exposures; |
968 | + | mapping (bytes32 => RentExposure) exposures; |
969 | - | |
969 | + | |
970 | - | //--- Constructor |
970 | + | //--- Constructor |
971 | - | |
971 | + | |
972 | - | function VeRentExposure( |
972 | + | function VeRentExposure( |
973 | - | VeritaseumToken _veToken, |
973 | + | VeritaseumToken _veToken, |
974 | - | VeExposure _veExposure, |
974 | + | VeExposure _veExposure, |
975 | - | uint256 _minPrice, |
975 | + | uint256 _minPrice, |
976 | - | uint256 _maxPrice |
976 | + | uint256 _maxPrice |
977 | - | ) { |
977 | + | ) { |
978 | - | require(_veToken != address(0)); |
978 | + | require(_veToken != address(0)); |
979 | - | require(_veExposure != address(0)); |
979 | + | require(_veExposure != address(0)); |
980 | - | require(_minPrice <= _maxPrice && _maxPrice <= PRICE_100_PERCENT); |
980 | + | require(_minPrice <= _maxPrice && _maxPrice <= PRICE_100_PERCENT); |
981 | - | |
981 | + | |
982 | - | veToken = _veToken; |
982 | + | veToken = _veToken; |
983 | - | veExposure = _veExposure; |
983 | + | veExposure = _veExposure; |
984 | - | minPrice = _minPrice; |
984 | + | minPrice = _minPrice; |
985 | - | maxPrice = _maxPrice; |
985 | + | maxPrice = _maxPrice; |
986 | - | } |
986 | + | } |
987 | - | |
987 | + | |
988 | - | //--- Accessors |
988 | + | //--- Accessors |
989 | - | |
989 | + | |
990 | - | function ratio() public constant returns (uint256) { |
990 | + | function ratio() public constant returns (uint256) { |
991 | - | return veExposure.ratio(); |
991 | + | return veExposure.ratio(); |
992 | - | } |
992 | + | } |
993 | - | |
993 | + | |
994 | - | function minVeriAmount() public constant returns (uint256) { |
994 | + | function minVeriAmount() public constant returns (uint256) { |
995 | - | return veExposure.minVeriAmount(); |
995 | + | return veExposure.minVeriAmount(); |
996 | - | } |
996 | + | } |
997 | - | |
997 | + | |
998 | - | function maxVeriAmount() public constant returns (uint256) { |
998 | + | function maxVeriAmount() public constant returns (uint256) { |
999 | - | return veExposure.maxVeriAmount(); |
999 | + | return veExposure.maxVeriAmount(); |
1000 | - | } |
1000 | + | } |
1001 | - | |
1001 | + | |
1002 | - | function minDuration() constant public returns (uint32) { |
1002 | + | function minDuration() constant public returns (uint32) { |
1003 | - | return veExposure.minDuration(); |
1003 | + | return veExposure.minDuration(); |
1004 | - | } |
1004 | + | } |
1005 | - | |
1005 | + | |
1006 | - | function maxDuration() constant public returns (uint32) { |
1006 | + | function maxDuration() constant public returns (uint32) { |
1007 | - | return veExposure.maxDuration(); |
1007 | + | return veExposure.maxDuration(); |
1008 | - | } |
1008 | + | } |
1009 | - | |
1009 | + | |
1010 | - | function setMinPrice(uint256 _minPrice) public onlyOwner { |
1010 | + | function setMinPrice(uint256 _minPrice) public onlyOwner { |
1011 | - | require(_minPrice <= maxPrice); |
1011 | + | require(_minPrice <= maxPrice); |
1012 | - | |
1012 | + | |
1013 | - | minPrice = _minPrice; |
1013 | + | minPrice = _minPrice; |
1014 | - | } |
1014 | + | } |
1015 | - | |
1015 | + | |
1016 | - | function setMaxPrice(uint256 _maxPrice) public onlyOwner { |
1016 | + | function setMaxPrice(uint256 _maxPrice) public onlyOwner { |
1017 | - | require(_maxPrice >= minPrice && _maxPrice <= PRICE_100_PERCENT); |
1017 | + | require(_maxPrice >= minPrice && _maxPrice <= PRICE_100_PERCENT); |
1018 | - | |
1018 | + | |
1019 | - | maxPrice = _maxPrice; |
1019 | + | maxPrice = _maxPrice; |
1020 | - | } |
1020 | + | } |
1021 | - | |
1021 | + | |
1022 | - | //--- Events |
1022 | + | //--- Events |
1023 | - | |
1023 | + | |
1024 | - | event RentExposureOpened( |
1024 | + | event RentExposureOpened( |
1025 | - | bytes32 indexed id, |
1025 | + | bytes32 indexed id, |
1026 | - | address indexed veriAccount, |
1026 | + | address indexed veriAccount, |
1027 | - | address indexed etherAccount, |
1027 | + | address indexed etherAccount, |
1028 | - | uint256 veriAmount, |
1028 | + | uint256 veriAmount, |
1029 | - | uint256 value, |
1029 | + | uint256 value, |
1030 | - | uint256 price, |
1030 | + | uint256 price, |
1031 | - | uint32 duration |
1031 | + | uint32 duration |
1032 | - | ); |
1032 | + | ); |
1033 | - | |
1033 | + | |
1034 | - | event VeriExposureSettled( |
1034 | + | event VeriExposureSettled( |
1035 | - | bytes32 indexed id, |
1035 | + | bytes32 indexed id, |
1036 | - | address indexed account, |
1036 | + | address indexed account, |
1037 | - | uint256 value |
1037 | + | uint256 value |
1038 | - | ); |
1038 | + | ); |
1039 | - | |
1039 | + | |
1040 | - | event EtherExposureSettled( |
1040 | + | event EtherExposureSettled( |
1041 | - | bytes32 indexed id, |
1041 | + | bytes32 indexed id, |
1042 | - | address indexed account, |
1042 | + | address indexed account, |
1043 | - | uint256 value |
1043 | + | uint256 value |
1044 | - | ); |
1044 | + | ); |
1045 | - | |
1045 | + | |
1046 | - | //--- Public functions |
1046 | + | //--- Public functions |
1047 | - | |
1047 | + | |
1048 | - | function open( |
1048 | + | function open( |
1049 | - | address veriAccount, |
1049 | + | address veriAccount, |
1050 | - | address etherAccount, |
1050 | + | address etherAccount, |
1051 | - | uint256 veriAmount, |
1051 | + | uint256 veriAmount, |
1052 | - | uint256 price, |
1052 | + | uint256 price, |
1053 | - | uint32 duration, |
1053 | + | uint32 duration, |
1054 | - | uint256 nonce |
1054 | + | uint256 nonce |
1055 | - | ) |
1055 | + | ) |
1056 | - | public |
1056 | + | public |
1057 | - | payable |
1057 | + | payable |
1058 | - | returns (bytes32) |
1058 | + | returns (bytes32) |
1059 | - | { |
1059 | + | { |
1060 | - | require(veriAccount != address(0)); |
1060 | + | require(veriAccount != address(0)); |
1061 | - | require(etherAccount != address(0)); |
1061 | + | require(etherAccount != address(0)); |
1062 | - | require(price >= minPrice && minPrice <= maxPrice); |
1062 | + | require(price >= minPrice && minPrice <= maxPrice); |
1063 | - | |
1063 | + | |
1064 | - | forwardTokens(veriAmount); |
1064 | + | forwardTokens(veriAmount); |
1065 | - | |
1065 | + | |
1066 | - | bytes32 id = calculateId({ |
1066 | + | bytes32 id = calculateId({ |
1067 | - | veriAmount: veriAmount, |
1067 | + | veriAmount: veriAmount, |
1068 | - | value: msg.value, |
1068 | + | value: msg.value, |
1069 | - | duration: duration, |
1069 | + | duration: duration, |
1070 | - | nonce: nonce |
1070 | + | nonce: nonce |
1071 | - | }); |
1071 | + | }); |
1072 | - | |
1072 | + | |
1073 | - | require(!exists(id)); |
1073 | + | require(!exists(id)); |
1074 | - | exposures[id] = RentExposure({ |
1074 | + | exposures[id] = RentExposure({ |
1075 | - | id: id, |
1075 | + | id: id, |
1076 | - | veriAccount: veriAccount, |
1076 | + | veriAccount: veriAccount, |
1077 | - | etherAccount: etherAccount, |
1077 | + | etherAccount: etherAccount, |
1078 | - | veriAmount: veriAmount, |
1078 | + | veriAmount: veriAmount, |
1079 | - | initialValue: msg.value, |
1079 | + | initialValue: msg.value, |
1080 | - | finalValue: 0, |
1080 | + | finalValue: 0, |
1081 | - | price: price, |
1081 | + | price: price, |
1082 | - | veriSettled: false, |
1082 | + | veriSettled: false, |
1083 | - | etherSettled: false |
1083 | + | etherSettled: false |
1084 | - | }); |
1084 | + | }); |
1085 | - | |
1085 | + | |
1086 | - | RentExposureOpened({ |
1086 | + | RentExposureOpened({ |
1087 | - | id: id, |
1087 | + | id: id, |
1088 | - | veriAccount: veriAccount, |
1088 | + | veriAccount: veriAccount, |
1089 | - | etherAccount: etherAccount, |
1089 | + | etherAccount: etherAccount, |
1090 | - | veriAmount: veriAmount, |
1090 | + | veriAmount: veriAmount, |
1091 | - | value: msg.value, |
1091 | + | value: msg.value, |
1092 | - | price: price, |
1092 | + | price: price, |
1093 | - | duration: duration |
1093 | + | duration: duration |
1094 | - | }); |
1094 | + | }); |
1095 | - | |
1095 | + | |
1096 | - | veExposure.open.value(msg.value)({ |
1096 | + | veExposure.open.value(msg.value)({ |
1097 | - | veriAmount: veriAmount, |
1097 | + | veriAmount: veriAmount, |
1098 | - | duration: duration, |
1098 | + | duration: duration, |
1099 | - | nonce: nonce |
1099 | + | nonce: nonce |
1100 | - | }); |
1100 | + | }); |
1101 | - | } |
1101 | + | } |
1102 | - | |
1102 | + | |
1103 | - | function settle(bytes32 id) public { |
1103 | + | function settle(bytes32 id) public { |
1104 | - | require(exists(id)); |
1104 | + | require(exists(id)); |
1105 | - | |
1105 | + | |
1106 | - | RentExposure storage exposure = exposures[id]; |
1106 | + | RentExposure storage exposure = exposures[id]; |
1107 | - | bool shouldSettleVeri = (msg.sender == exposure.veriAccount && !exposure.veriSettled); |
1107 | + | bool shouldSettleVeri = (msg.sender == exposure.veriAccount && !exposure.veriSettled); |
1108 | - | bool shouldSettleEther = (msg.sender == exposure.etherAccount && !exposure.etherSettled); |
1108 | + | bool shouldSettleEther = (msg.sender == exposure.etherAccount && !exposure.etherSettled); |
1109 | - | require(shouldSettleVeri || shouldSettleEther); |
1109 | + | require(shouldSettleVeri || shouldSettleEther); |
1110 | - | |
1110 | + | |
1111 | - | if (!exposure.veriSettled && !exposure.etherSettled) { |
1111 | + | if (!exposure.veriSettled && !exposure.etherSettled) { |
1112 | - | exposure.finalValue = veExposure.settle(id); |
1112 | + | exposure.finalValue = veExposure.settle(id); |
1113 | - | } |
1113 | + | } |
1114 | - | |
1114 | + | |
1115 | - | if (shouldSettleVeri) { |
1115 | + | if (shouldSettleVeri) { |
1116 | - | settleVeri(exposure); |
1116 | + | settleVeri(exposure); |
1117 | - | } |
1117 | + | } |
1118 | - | |
1118 | + | |
1119 | - | if (shouldSettleEther) { |
1119 | + | if (shouldSettleEther) { |
1120 | - | settleEther(exposure); |
1120 | + | settleEther(exposure); |
1121 | - | } |
1121 | + | } |
1122 | - | |
1122 | + | |
1123 | - | if (exposure.veriSettled && exposure.etherSettled) { |
1123 | + | if (exposure.veriSettled && exposure.etherSettled) { |
1124 | - | delete exposures[id]; |
1124 | + | delete exposures[id]; |
1125 | - | } |
1125 | + | } |
1126 | - | } |
1126 | + | } |
1127 | - | |
1127 | + | |
1128 | - | //--- Public constant functions |
1128 | + | //--- Public constant functions |
1129 | - | |
1129 | + | |
1130 | - | function exists(bytes32 id) public constant returns (bool) { |
1130 | + | function exists(bytes32 id) public constant returns (bool) { |
1131 | - | return exposures[id].veriAccount != address(0); |
1131 | + | return exposures[id].veriAccount != address(0); |
1132 | - | } |
1132 | + | } |
1133 | - | |
1133 | + | |
1134 | - | function calculateId( |
1134 | + | function calculateId( |
1135 | - | uint256 veriAmount, |
1135 | + | uint256 veriAmount, |
1136 | - | uint256 value, |
1136 | + | uint256 value, |
1137 | - | uint32 duration, |
1137 | + | uint32 duration, |
1138 | - | uint256 nonce |
1138 | + | uint256 nonce |
1139 | - | ) |
1139 | + | ) |
1140 | - | public |
1140 | + | public |
1141 | - | constant |
1141 | + | constant |
1142 | - | returns (bytes32) |
1142 | + | returns (bytes32) |
1143 | - | { |
1143 | + | { |
1144 | - | return veExposure.calculateId({ |
1144 | + | return veExposure.calculateId({ |
1145 | - | veriAmount: veriAmount, |
1145 | + | veriAmount: veriAmount, |
1146 | - | value: value, |
1146 | + | value: value, |
1147 | - | duration: duration, |
1147 | + | duration: duration, |
1148 | - | nonce: nonce |
1148 | + | nonce: nonce |
1149 | - | }); |
1149 | + | }); |
1150 | - | } |
1150 | + | } |
1151 | - | |
1151 | + | |
1152 | - | function checkRatio(uint256 veriAmount, uint256 value) |
1152 | + | function checkRatio(uint256 veriAmount, uint256 value) |
1153 | - | public |
1153 | + | public |
1154 | - | constant |
1154 | + | constant |
1155 | - | returns (bool) |
1155 | + | returns (bool) |
1156 | - | { |
1156 | + | { |
1157 | - | return veExposure.checkRatio(veriAmount, value); |
1157 | + | return veExposure.checkRatio(veriAmount, value); |
1158 | - | } |
1158 | + | } |
1159 | - | |
1159 | + | |
1160 | - | //--- Fallback function |
1160 | + | //--- Fallback function |
1161 | - | |
1161 | + | |
1162 | - | function() public payable { |
1162 | + | function() public payable { |
1163 | - | // accept Ether deposits |
1163 | + | // accept Ether deposits |
1164 | - | } |
1164 | + | } |
1165 | - | |
1165 | + | |
1166 | - | //--- Private functions |
1166 | + | //--- Private functions |
1167 | - | |
1167 | + | |
1168 | - | function settleVeri(RentExposure storage exposure) private { |
1168 | + | function settleVeri(RentExposure storage exposure) private { |
1169 | - | assert(msg.sender == exposure.veriAccount && !exposure.veriSettled); |
1169 | + | assert(msg.sender == exposure.veriAccount && !exposure.veriSettled); |
1170 | - | |
1170 | + | |
1171 | - | uint256 transferValue = 0; |
1171 | + | uint256 transferValue = 0; |
1172 | - | if (exposure.finalValue > exposure.initialValue) { |
1172 | + | if (exposure.finalValue > exposure.initialValue) { |
1173 | - | // transfer part of profits (price) |
1173 | + | // transfer part of profits (price) |
1174 | - | uint256 totalProfit = exposure.finalValue - exposure.initialValue; |
1174 | + | uint256 totalProfit = exposure.finalValue - exposure.initialValue; |
1175 | - | uint256 veriPrice = exposure.price; |
1175 | + | uint256 veriPrice = exposure.price; |
1176 | - | uint256 veriProfit = totalProfit.mul(veriPrice).div(1 ether); |
1176 | + | uint256 veriProfit = totalProfit.mul(veriPrice).div(1 ether); |
1177 | - | transferValue = veriProfit; |
1177 | + | transferValue = veriProfit; |
1178 | - | } |
1178 | + | } |
1179 | - | |
1179 | + | |
1180 | - | exposure.veriSettled = true; |
1180 | + | exposure.veriSettled = true; |
1181 | - | if (transferValue > 0) { |
1181 | + | if (transferValue > 0) { |
1182 | - | exposure.veriAccount.transfer(transferValue); |
1182 | + | exposure.veriAccount.transfer(transferValue); |
1183 | - | } |
1183 | + | } |
1184 | - | |
1184 | + | |
1185 | - | VeriExposureSettled({ |
1185 | + | VeriExposureSettled({ |
1186 | - | id: exposure.id, |
1186 | + | id: exposure.id, |
1187 | - | account: msg.sender, |
1187 | + | account: msg.sender, |
1188 | - | value: transferValue |
1188 | + | value: transferValue |
1189 | - | }); |
1189 | + | }); |
1190 | - | } |
1190 | + | } |
1191 | - | |
1191 | + | |
1192 | - | function settleEther(RentExposure storage exposure) private { |
1192 | + | function settleEther(RentExposure storage exposure) private { |
1193 | - | assert(msg.sender == exposure.etherAccount && !exposure.etherSettled); |
1193 | + | assert(msg.sender == exposure.etherAccount && !exposure.etherSettled); |
1194 | - | |
1194 | + | |
1195 | - | uint256 transferValue = 0; |
1195 | + | uint256 transferValue = 0; |
1196 | - | if (exposure.finalValue > exposure.initialValue) { |
1196 | + | if (exposure.finalValue > exposure.initialValue) { |
1197 | - | // transfer part of profits (100% - price) |
1197 | + | // transfer part of profits (100% - price) |
1198 | - | uint256 totalProfit = exposure.finalValue - exposure.initialValue; |
1198 | + | uint256 totalProfit = exposure.finalValue - exposure.initialValue; |
1199 | - | uint256 etherPrice = PRICE_100_PERCENT.sub(exposure.price); |
1199 | + | uint256 etherPrice = PRICE_100_PERCENT.sub(exposure.price); |
1200 | - | uint256 etherProfit = totalProfit.mul(etherPrice).div(1 ether); |
1200 | + | uint256 etherProfit = totalProfit.mul(etherPrice).div(1 ether); |
1201 | - | transferValue = exposure.initialValue.add(etherProfit); |
1201 | + | transferValue = exposure.initialValue.add(etherProfit); |
1202 | - | } else { |
1202 | + | } else { |
1203 | - | // transfer remains |
1203 | + | // transfer remains |
1204 | - | transferValue = exposure.finalValue; |
1204 | + | transferValue = exposure.finalValue; |
1205 | - | } |
1205 | + | } |
1206 | - | |
1206 | + | |
1207 | - | exposure.etherSettled = true; |
1207 | + | exposure.etherSettled = true; |
1208 | - | if (transferValue > 0) { |
1208 | + | if (transferValue > 0) { |
1209 | - | exposure.etherAccount.transfer(transferValue); |
1209 | + | exposure.etherAccount.transfer(transferValue); |
1210 | - | } |
1210 | + | } |
1211 | - | |
1211 | + | |
1212 | - | EtherExposureSettled({ |
1212 | + | EtherExposureSettled({ |
1213 | - | id: exposure.id, |
1213 | + | id: exposure.id, |
1214 | - | account: msg.sender, |
1214 | + | account: msg.sender, |
1215 | - | value: transferValue |
1215 | + | value: transferValue |
1216 | - | }); |
1216 | + | }); |
1217 | - | } |
1217 | + | } |
1218 | - | |
1218 | + | |
1219 | - | function forwardTokens(uint256 veriAmount) private { |
1219 | + | function forwardTokens(uint256 veriAmount) private { |
1220 | - | require(veToken.transferFrom(msg.sender, this, veriAmount)); |
1220 | + | require(veToken.transferFrom(msg.sender, this, veriAmount)); |
1221 | - | require(veToken.approve(veExposure, veriAmount)); |
1221 | + | require(veToken.approve(veExposure, veriAmount)); |
1222 | - | } |
1222 | + | } |
1223 | } | |
1224 | - | |
1224 | + | |
1225 | - | contract ERC20Basic { |
1225 | + | contract ERC20Basic { |
1226 | - | uint256 public totalSupply; |
1226 | + | uint256 public totalSupply; |
1227 | - | function balanceOf(address who) public constant returns (uint256); |
1227 | + | function balanceOf(address who) public constant returns (uint256); |
1228 | - | function transfer(address to, uint256 value) public returns (bool); |
1228 | + | function transfer(address to, uint256 value) public returns (bool); |
1229 | - | event Transfer(address indexed from, address indexed to, uint256 value); |
1229 | + | event Transfer(address indexed from, address indexed to, uint256 value); |
1230 | } |