Guest User

Untitled

a guest
Aug 16th, 2018
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.93 KB | None | 0 0
  1. pragma solidity 0.4.18;
  2.  
  3. import "./SafeMath.sol";
  4. import "./ERC20.sol";
  5. import "./TermsContract.sol";
  6. import "./DebtRegistry.sol";
  7. import "./TokenRegistry.sol";
  8. import "./TokenTransferProxy.sol";
  9. import { PermissionsLib, PermissionEvents } from "./PermissionsLib.sol";
  10.  
  11. contract Collateralizer is Pausable, PermissionEvents {
  12. using PermissionsLib for PermissionsLib.Permissions;
  13. using SafeMath for uint;
  14.  
  15. address public debtKernelAddress;
  16.  
  17. DebtRegistry public debtRegistry;
  18. TokenRegistry public tokenRegistry;
  19. TokenTransferProxy public tokenTransferProxy;
  20.  
  21. // Collateralizer here refers to the owner of the asset that is being collateralized.
  22. mapping(bytes32 => address) public agreementToCollateralizer;
  23.  
  24. PermissionsLib.Permissions internal collateralizationPermissions;
  25.  
  26. uint public constant SECONDS_IN_DAY = 24*60*60;
  27.  
  28. string public constant CONTEXT = "collateralizer";
  29.  
  30. event CollateralLocked(
  31. bytes32 indexed agreementID,
  32. address indexed token,
  33. uint amount
  34. );
  35.  
  36. event CollateralReturned(
  37. bytes32 indexed agreementID,
  38. address indexed collateralizer,
  39. address token,
  40. uint amount
  41. );
  42.  
  43. event CollateralSeized(
  44. bytes32 indexed agreementID,
  45. address indexed beneficiary,
  46. address token,
  47. uint amount
  48. );
  49.  
  50. modifier onlyAuthorizedToCollateralize() {
  51. require(collateralizationPermissions.isAuthorized(msg.sender));
  52. _;
  53. }
  54.  
  55. function Collateralizer(
  56. address _debtKernel,
  57. address _debtRegistry,
  58. address _tokenRegistry,
  59. address _tokenTransferProxy
  60. ) public {
  61. debtKernelAddress = _debtKernel;
  62. debtRegistry = DebtRegistry(_debtRegistry);
  63. tokenRegistry = TokenRegistry(_tokenRegistry);
  64. tokenTransferProxy = TokenTransferProxy(_tokenTransferProxy);
  65. }
  66.  
  67. function collateralize(
  68. bytes32 agreementId,
  69. address collateralizer
  70. )
  71. public
  72. onlyAuthorizedToCollateralize
  73. whenNotPaused
  74. returns (bool _success)
  75. {
  76. // The token in which collateral is denominated
  77. address collateralToken;
  78. // The amount being put up for collateral
  79. uint collateralAmount;
  80. // The number of days a debtor has after a debt enters default
  81. // before their collateral is eligible for seizure.
  82. uint gracePeriodInDays;
  83. // The terms contract according to which this asset is being collateralized.
  84. TermsContract termsContract;
  85.  
  86. // Fetch all relevant collateralization parameters
  87. (
  88. collateralToken,
  89. collateralAmount,
  90. gracePeriodInDays,
  91. termsContract
  92. ) = retrieveCollateralParameters(agreementId);
  93.  
  94. require(termsContract == msg.sender);
  95. require(collateralAmount > 0);
  96. require(collateralToken != address(0));
  97.  
  98. /*
  99. Ensure that the agreement has not already been collateralized.
  100.  
  101. If the agreement has already been collateralized, this check will fail
  102. because any valid collateralization must have some sort of valid
  103. address associated with it as a collateralizer. Given that it is impossible
  104. to send transactions from address 0x0, this check will only fail
  105. when the agreement is already collateralized.
  106. */
  107. require(agreementToCollateralizer[agreementId] == address(0));
  108.  
  109. ERC20 erc20token = ERC20(collateralToken);
  110. address custodian = address(this);
  111.  
  112. /*
  113. The collateralizer must have sufficient balance equal to or greater
  114. than the amount being put up for collateral.
  115. */
  116. require(erc20token.balanceOf(collateralizer) >= collateralAmount);
  117.  
  118. /*
  119. The proxy must have an allowance granted by the collateralizer equal
  120. to or greater than the amount being put up for collateral.
  121. */
  122. require(erc20token.allowance(collateralizer, tokenTransferProxy) >= collateralAmount);
  123.  
  124. // store collaterallizer in mapping, effectively demarcating that the
  125. // agreement is now collateralized.
  126. agreementToCollateralizer[agreementId] = collateralizer;
  127.  
  128. // the collateral must be successfully transferred to this contract, via a proxy.
  129. require(tokenTransferProxy.transferFrom(
  130. erc20token,
  131. collateralizer,
  132. custodian,
  133. collateralAmount
  134. ));
  135.  
  136. // emit event that collateral has been secured.
  137. CollateralLocked(agreementId, collateralToken, collateralAmount);
  138.  
  139. return true;
  140. }
  141.  
  142. function returnCollateral(
  143. bytes32 agreementId
  144. )
  145. public
  146. whenNotPaused
  147. {
  148. // The token in which collateral is denominated
  149. address collateralToken;
  150. // The amount being put up for collateral
  151. uint collateralAmount;
  152. // The number of days a debtor has after a debt enters default
  153. // before their collateral is eligible for seizure.
  154. uint gracePeriodInDays;
  155. // The terms contract according to which this asset is being collateralized.
  156. TermsContract termsContract;
  157.  
  158. // Fetch all relevant collateralization parameters.
  159. (
  160. collateralToken,
  161. collateralAmount,
  162. gracePeriodInDays,
  163. termsContract
  164. ) = retrieveCollateralParameters(agreementId);
  165.  
  166. // Ensure a valid form of collateral is tied to this agreement id
  167. require(collateralAmount > 0);
  168. require(collateralToken != address(0));
  169.  
  170. // Withdrawal can only occur if the collateral has yet to be withdrawn.
  171. // When we withdraw collateral, we reset the collateral agreement
  172. // in a gas-efficient manner by resetting the address of the collateralizer to 0
  173. require(agreementToCollateralizer[agreementId] != address(0));
  174.  
  175. // Ensure that the debt is not in a state of default
  176. require(
  177. termsContract.getExpectedRepaymentValue(
  178. agreementId,
  179. termsContract.getTermEndTimestamp(agreementId)
  180. ) <= termsContract.getValueRepaidToDate(agreementId)
  181. );
  182.  
  183. // determine collateralizer of the collateral.
  184. address collateralizer = agreementToCollateralizer[agreementId];
  185.  
  186. // Mark agreement's collateral as withdrawn by setting the agreement's
  187. // collateralizer to 0x0.
  188. delete agreementToCollateralizer[agreementId];
  189.  
  190. // transfer the collateral this contract was holding in escrow back to collateralizer.
  191. require(
  192. ERC20(collateralToken).transfer(
  193. collateralizer,
  194. collateralAmount
  195. )
  196. );
  197.  
  198. // log the return event.
  199. CollateralReturned(
  200. agreementId,
  201. collateralizer,
  202. collateralToken,
  203. collateralAmount
  204. );
  205. }
  206.  
  207.  
  208. function seizeCollateral(
  209. bytes32 agreementId
  210. )
  211. public
  212. whenNotPaused
  213. {
  214.  
  215. // The token in which collateral is denominated
  216. address collateralToken;
  217. // The amount being put up for collateral
  218. uint collateralAmount;
  219. // The number of days a debtor has after a debt enters default
  220. // before their collateral is eligible for seizure.
  221. uint gracePeriodInDays;
  222. // The terms contract according to which this asset is being collateralized.
  223. TermsContract termsContract;
  224.  
  225. // Fetch all relevant collateralization parameters
  226. (
  227. collateralToken,
  228. collateralAmount,
  229. gracePeriodInDays,
  230. termsContract
  231. ) = retrieveCollateralParameters(agreementId);
  232.  
  233. // Ensure a valid form of collateral is tied to this agreement id
  234. require(collateralAmount > 0);
  235. require(collateralToken != address(0));
  236.  
  237. // Seizure can only occur if the collateral has yet to be withdrawn.
  238. // When we withdraw collateral, we reset the collateral agreement
  239. // in a gas-efficient manner by resetting the address of the collateralizer to 0
  240. require(agreementToCollateralizer[agreementId] != address(0));
  241.  
  242. // Ensure debt is in a state of default when we account for the
  243. // specified "grace period". We do this by checking whether the
  244. // *current* value repaid to-date exceeds the expected repayment value
  245. // at the point of time at which the grace period would begin if it ended
  246. // now. This crucially relies on the assumption that both expected repayment value
  247. /// and value repaid to date monotonically increase over time
  248. require(
  249. termsContract.getExpectedRepaymentValue(
  250. agreementId,
  251. timestampAdjustedForGracePeriod(gracePeriodInDays)
  252. ) > termsContract.getValueRepaidToDate(agreementId)
  253. );
  254.  
  255. // Mark agreement's collateral as withdrawn by setting the agreement's
  256. // collateralizer to 0x0.
  257. delete agreementToCollateralizer[agreementId];
  258.  
  259. // determine beneficiary of the seized collateral.
  260. address beneficiary = debtRegistry.getBeneficiary(agreementId);
  261.  
  262. // transfer the collateral this contract was holding in escrow to beneficiary.
  263. require(
  264. ERC20(collateralToken).transfer(
  265. beneficiary,
  266. collateralAmount
  267. )
  268. );
  269.  
  270. // log the seizure event.
  271. CollateralSeized(
  272. agreementId,
  273. beneficiary,
  274. collateralToken,
  275. collateralAmount
  276. );
  277. }
  278.  
  279.  
  280. function addAuthorizedCollateralizeAgent(address agent)
  281. public
  282. onlyOwner
  283. {
  284. collateralizationPermissions.authorize(agent, CONTEXT);
  285. }
  286.  
  287.  
  288. function revokeCollateralizeAuthorization(address agent)
  289. public
  290. onlyOwner
  291. {
  292. collateralizationPermissions.revokeAuthorization(agent, CONTEXT);
  293. }
  294.  
  295.  
  296. function getAuthorizedCollateralizeAgents()
  297. public
  298. view
  299. returns(address[])
  300. {
  301. return collateralizationPermissions.getAuthorizedAgents();
  302. }
  303.  
  304. function unpackCollateralParametersFromBytes(bytes32 parameters)
  305. public
  306. pure
  307. returns (uint, uint, uint)
  308. {
  309. // The first byte of the 108 reserved bits represents the collateral token.
  310. bytes32 collateralTokenIndexShifted =
  311. parameters & 0x0000000000000000000000000000000000000ff0000000000000000000000000;
  312. // The subsequent 92 bits represents the collateral amount, as denominated in the above token.
  313. bytes32 collateralAmountShifted =
  314. parameters & 0x000000000000000000000000000000000000000fffffffffffffffffffffff00;
  315.  
  316. // We bit-shift these values, respectively, 100 bits and 8 bits right using
  317. // mathematical operations, so that their 32 byte integer counterparts
  318. // correspond to the intended values packed in the 32 byte string
  319. uint collateralTokenIndex = uint(collateralTokenIndexShifted) / 2 ** 100;
  320. uint collateralAmount = uint(collateralAmountShifted) / 2 ** 8;
  321.  
  322. // The last byte of the parameters represents the "grace period" of the loan,
  323. // as defined in terms of days.
  324. // Since this value takes the rightmost place in the parameters string,
  325. // we do not need to bit-shift it.
  326. bytes32 gracePeriodInDays =
  327. parameters & 0x00000000000000000000000000000000000000000000000000000000000000ff;
  328.  
  329. return (
  330. collateralTokenIndex,
  331. collateralAmount,
  332. uint(gracePeriodInDays)
  333. );
  334. }
  335.  
  336. function timestampAdjustedForGracePeriod(uint gracePeriodInDays)
  337. public
  338. view
  339. returns (uint)
  340. {
  341. return block.timestamp.sub(
  342. SECONDS_IN_DAY.mul(gracePeriodInDays)
  343. );
  344. }
  345.  
  346. function retrieveCollateralParameters(bytes32 agreementId)
  347. internal
  348. view
  349. returns (
  350. address _collateralToken,
  351. uint _collateralAmount,
  352. uint _gracePeriodInDays,
  353. TermsContract _termsContract
  354. )
  355. {
  356. address termsContractAddress;
  357. bytes32 termsContractParameters;
  358.  
  359. // Pull the terms contract and associated parameters for the agreement
  360. (termsContractAddress, termsContractParameters) = debtRegistry.getTerms(agreementId);
  361.  
  362. uint collateralTokenIndex;
  363. uint collateralAmount;
  364. uint gracePeriodInDays;
  365.  
  366. // Unpack terms contract parameters in order to get collateralization-specific params
  367. (
  368. collateralTokenIndex,
  369. collateralAmount,
  370. gracePeriodInDays
  371. ) = unpackCollateralParametersFromBytes(termsContractParameters);
  372.  
  373. // Resolve address of token associated with this agreement in token registry
  374. address collateralTokenAddress = tokenRegistry.getTokenAddressByIndex(collateralTokenIndex);
  375.  
  376. return (
  377. collateralTokenAddress,
  378. collateralAmount,
  379. gracePeriodInDays,
  380. TermsContract(termsContractAddress)
  381. );
  382. }
  383. }
Add Comment
Please, Sign In to add comment