Advertisement
libdo

Untitled

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