├── .gitattributes ├── HybridMVP.sol ├── OnChainMVP.sol ├── README.md ├── contracts └── offerContract.sol ├── css ├── julios-blank-site-e50fbc.webflow.css ├── normalize.css └── webflow.css ├── images ├── LightDefi.png ├── background-p-1080.png ├── background-p-500.png ├── background-p-800.png ├── background.png ├── favicon.ico ├── logo.png ├── logo.svg ├── resized-p-500.png ├── resized.png └── webclip.png ├── index.html └── js ├── test.js ├── web3.min.js └── webflow.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /HybridMVP.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.9; 2 | 3 | import "./safeMath.sol"; 4 | 5 | contract Erc20 { 6 | function approve(address, uint) external returns (bool); 7 | function transfer(address, uint) external returns (bool); 8 | function balanceOf(address _owner) external returns (uint256 balance); 9 | function transferFrom(address sender, address recipient, uint256 amount) public returns (bool); 10 | } 11 | 12 | contract CErc20 is Erc20 { 13 | function mint(uint) external returns (uint); 14 | function redeem(uint redeemTokens) external returns (uint); 15 | function redeemUnderlying(uint redeemAmount) external returns (uint); 16 | function exchangeRateCurrent() external returns (uint); 17 | } 18 | 19 | contract CEth { 20 | function mint() external payable; 21 | function redeem(uint redeemTokens) external returns (uint); 22 | function balanceOf(address _owner) external returns (uint256 balance); 23 | function approve(address spender, uint tokens) public returns (bool success); 24 | function redeemUnderlying(uint redeemAmount) external returns (uint); 25 | function exchangeRateCurrent() external returns (uint); 26 | } 27 | 28 | contract DefiHedge { 29 | 30 | struct RPCSig{ 31 | uint8 v; 32 | bytes32 r; 33 | bytes32 s; 34 | } 35 | 36 | struct EIP712Domain { 37 | string name; 38 | string version; 39 | uint256 chainId; 40 | address verifyingContract; 41 | } 42 | 43 | struct OnChainOffer { 44 | address maker; 45 | address taker; 46 | uint256 side; 47 | address tokenAddress; 48 | uint256 duration; 49 | uint256 rate; 50 | uint256 interest; 51 | uint256 base; 52 | uint256 state; 53 | } 54 | 55 | struct Offer { 56 | address maker; 57 | address taker; 58 | uint256 side; 59 | address tokenAddress; 60 | uint256 duration; 61 | uint256 rate; 62 | uint256 interest; 63 | uint256 base; 64 | } 65 | 66 | struct signedOffer { 67 | address maker; 68 | address taker; 69 | uint256 side; 70 | address tokenAddress; 71 | uint256 duration; 72 | uint256 rate; 73 | uint256 interest; 74 | uint256 base; 75 | uint256 state; 76 | uint256 lockTime; 77 | uint256 initialRate; 78 | } 79 | 80 | mapping (bytes32 => signedOffer) offerMapping; 81 | 82 | mapping (bytes32 => OnChainOffer) onChainOfferMapping; 83 | 84 | bytes32[] public onChainOfferList; 85 | 86 | bytes32[] public offerList; 87 | 88 | event newFixedOffer( 89 | bytes32 offerKey, 90 | address maker, 91 | address taker, 92 | address tokenAddress, 93 | uint256 duration, 94 | uint256 rate, 95 | uint256 interest, 96 | uint256 base 97 | ); 98 | 99 | event newFloatingOffer( 100 | bytes32 offerKey, 101 | address maker, 102 | address taker, 103 | address tokenAddress, 104 | uint256 duration, 105 | uint256 rate, 106 | uint256 interest, 107 | uint256 base 108 | ); 109 | 110 | event newLockedOffer( 111 | bytes32 offerKey, 112 | address maker, 113 | address taker, 114 | uint256 side, 115 | address tokenAddress, 116 | uint256 duration, 117 | uint256 rate, 118 | uint256 interest, 119 | uint256 base 120 | ); 121 | 122 | event Aborted( 123 | bytes32 offerKey 124 | ); 125 | 126 | event bondReleased( 127 | bytes32 offerKey 128 | ); 129 | 130 | 131 | using SafeMath for uint; 132 | 133 | constructor () public { 134 | DOMAIN_SEPARATOR = hashDomain(EIP712Domain({ 135 | name: "DefiHedge", 136 | version: '1', 137 | chainId: 3, 138 | verifyingContract: 0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC 139 | })); 140 | } 141 | 142 | bytes32 DOMAIN_SEPARATOR; 143 | 144 | // Offer + EIP Domain Hash Schema 145 | bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256( 146 | "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" 147 | ); 148 | 149 | bytes32 constant OFFER_TYPEHASH = keccak256( 150 | "Offer(address maker,address taker,uint256 side,address tokenAddress,uint256 duration,uint256 rate,uint256 interest,uint256 base)" 151 | ); 152 | 153 | function hashDomain(EIP712Domain memory eip712Domain) internal pure returns (bytes32) { 154 | return keccak256(abi.encode( 155 | EIP712DOMAIN_TYPEHASH, 156 | keccak256(bytes(eip712Domain.name)), 157 | keccak256(bytes(eip712Domain.version)), 158 | eip712Domain.chainId, 159 | eip712Domain.verifyingContract 160 | )); 161 | } 162 | 163 | function hashOffer(Offer memory _offer)private pure returns(bytes32){ 164 | return keccak256(abi.encode( 165 | OFFER_TYPEHASH, 166 | _offer.maker, 167 | _offer.taker, 168 | _offer.side, 169 | _offer.tokenAddress, 170 | _offer.duration, 171 | _offer.rate, 172 | _offer.interest, 173 | _offer.base 174 | )); 175 | } 176 | 177 | 178 | function getOnChainOffer(bytes32 offerKey) 179 | public 180 | view 181 | returns (address maker, address taker, uint256 side, address tokenAddress, uint256 duration, uint256 rate, uint256 base, uint256 interest, uint256 state) 182 | { 183 | // Returns all offer details 184 | maker = onChainOfferMapping[offerKey].maker; 185 | taker = onChainOfferMapping[offerKey].taker; 186 | side = onChainOfferMapping[offerKey].side; 187 | tokenAddress = onChainOfferMapping[offerKey].tokenAddress; 188 | duration = onChainOfferMapping[offerKey].duration; 189 | rate = onChainOfferMapping[offerKey].rate; 190 | interest = onChainOfferMapping[offerKey].interest; 191 | base = onChainOfferMapping[offerKey].base; 192 | state = onChainOfferMapping[offerKey].state; 193 | 194 | return (maker, taker, side, tokenAddress, duration, rate, base, interest, state); 195 | } 196 | 197 | function getActiveOffer(bytes32 offerKey) 198 | public 199 | view 200 | returns (address maker, address taker, uint256 side, address tokenAddress, uint256 duration, uint256 rate, uint256 base, uint256 interest, uint256 state, uint256 lockTime, uint256 initialRate) 201 | { 202 | // Returns all offer details 203 | maker = offerMapping[offerKey].maker; 204 | taker = offerMapping[offerKey].taker; 205 | side = offerMapping[offerKey].side; 206 | tokenAddress = offerMapping[offerKey].tokenAddress; 207 | duration = offerMapping[offerKey].duration; 208 | rate = offerMapping[offerKey].rate; 209 | interest = offerMapping[offerKey].interest; 210 | base = offerMapping[offerKey].base; 211 | state = offerMapping[offerKey].state; 212 | lockTime = offerMapping[offerKey].lockTime; 213 | initialRate = offerMapping[offerKey].initialRate; 214 | 215 | return (maker, taker, side, tokenAddress, duration, rate, base, interest, state, lockTime, initialRate); 216 | } 217 | 218 | // Deploy a new Erc lending contract 219 | function createOnChainErcOffer(address maker, address taker, uint side, address tokenAddress, uint256 duration, uint256 rate, uint256 interest, uint256 base) 220 | public 221 | returns (bytes32 _offerKey) 222 | { 223 | 224 | 225 | Erc20 underlying = Erc20(tokenAddress); 226 | 227 | // Create unique offer key 228 | bytes32 offerKey = keccak256(abi.encodePacked((now),msg.sender)); 229 | 230 | // Require transfer of input erc amount 231 | if (side == 0) { 232 | require(underlying.transferFrom(maker, address(this), base), "Transfer Failed"); 233 | 234 | emit newFixedOffer(offerKey, maker, taker, tokenAddress, rate, duration, interest, base); 235 | 236 | } 237 | 238 | if (side == 1) { 239 | require(underlying.transferFrom(maker, address(this), interest), "Transfer Failed"); 240 | 241 | emit newFloatingOffer(offerKey, maker, taker, tokenAddress, rate, duration, interest, base); 242 | } 243 | 244 | // Save offer on-chain 245 | OnChainOffer memory ercContract = onChainOfferMapping[offerKey]; 246 | 247 | ercContract.maker = address(msg.sender); 248 | ercContract.taker = taker; 249 | ercContract.side = side; 250 | ercContract.tokenAddress = tokenAddress; 251 | ercContract.duration = duration; 252 | ercContract.rate = rate; 253 | ercContract.interest = interest; 254 | ercContract.base = base; 255 | ercContract.state = 0; 256 | 257 | onChainOfferList.push(offerKey) -1; 258 | 259 | return offerKey; 260 | } 261 | 262 | 263 | // Deploy a new Eth lending contract 264 | function createOnChainEthOffer(address maker, address taker, uint side, address tokenAddress, uint256 duration, uint256 rate, uint256 interest, uint256 base) 265 | public 266 | payable 267 | returns (bytes32 _offerKey) 268 | { 269 | 270 | // Create unique offer key 271 | bytes32 offerKey = keccak256(abi.encodePacked((now),msg.sender)); 272 | 273 | if (side == 0) { 274 | 275 | // Require correct value between transaction and input value 276 | require(base == msg.value, "Invalid Transaction/Input Value"); 277 | 278 | // Save offer on-chain 279 | OnChainOffer memory ethOffer = OnChainOffer( 280 | msg.sender, 281 | taker, 282 | side, 283 | tokenAddress, 284 | duration, 285 | rate, 286 | interest, 287 | msg.value, 288 | 0 289 | ); 290 | 291 | onChainOfferMapping[offerKey] = ethOffer; 292 | 293 | onChainOfferList.push(offerKey); 294 | 295 | emit newFixedOffer(offerKey, maker, taker, tokenAddress, rate, duration, interest, msg.value); 296 | 297 | return(offerKey); 298 | 299 | 300 | } 301 | if (side == 1) { 302 | 303 | require(interest == msg.value, "Invalid Transaction/Input Value"); 304 | 305 | OnChainOffer memory ethOffer = OnChainOffer( 306 | msg.sender, 307 | taker, 308 | side, 309 | tokenAddress, 310 | duration, 311 | rate, 312 | msg.value, 313 | base, 314 | 0 315 | ); 316 | 317 | onChainOfferMapping[offerKey] = ethOffer; 318 | 319 | onChainOfferList.push(offerKey); 320 | 321 | emit newFloatingOffer(offerKey, maker, taker, tokenAddress, rate, duration, msg.value, base); 322 | 323 | return(offerKey); 324 | 325 | } 326 | 327 | 328 | } 329 | 330 | function takeEthOffer(bytes32 offerKey) public payable returns (bytes32){ 331 | 332 | // Require offer to be in state "created" 333 | require (onChainOfferMapping[offerKey].state == 0, "Invalid State"); 334 | 335 | // Transfer taker funds to contract 336 | if (onChainOfferMapping[offerKey].side == 0){ 337 | require(msg.value >= onChainOfferMapping[offerKey].interest, "Transfer Failed"); 338 | } 339 | if (onChainOfferMapping[offerKey].side == 1){ 340 | require(msg.value >= onChainOfferMapping[offerKey].base, "Transfer Failed"); 341 | } 342 | 343 | // Mint Ctokens 344 | mintCEther((onChainOfferMapping[offerKey].base).add((onChainOfferMapping[offerKey].interest))); 345 | 346 | // Set taker address 347 | onChainOfferMapping[offerKey].taker = msg.sender; 348 | 349 | // Set state to Active 350 | onChainOfferMapping[offerKey].state = 1; 351 | 352 | // Set locktime 353 | offerMapping[offerKey].lockTime = onChainOfferMapping[offerKey].duration.add(now); 354 | 355 | emit newLockedOffer(offerKey,onChainOfferMapping[offerKey].maker,onChainOfferMapping[offerKey].taker,onChainOfferMapping[offerKey].side,onChainOfferMapping[offerKey].tokenAddress,onChainOfferMapping[offerKey].duration,onChainOfferMapping[offerKey].rate,onChainOfferMapping[offerKey].interest,onChainOfferMapping[offerKey].base); 356 | } 357 | 358 | function takeErcOffer(bytes32 offerKey) public payable returns (bytes32){ 359 | 360 | // Require offer to be in state "created" 361 | require (onChainOfferMapping[offerKey].state == 0, "Invalid State"); 362 | 363 | Erc20 underlying = Erc20(onChainOfferMapping[offerKey].tokenAddress); 364 | 365 | // Transfer taker funds to contract 366 | if (onChainOfferMapping[offerKey].side == 0){ 367 | require(underlying.transferFrom(msg.sender, address(this), onChainOfferMapping[offerKey].interest), "Transfer Failed"); 368 | 369 | } 370 | if (onChainOfferMapping[offerKey].side == 1){ 371 | require(underlying.transferFrom(msg.sender, address(this), onChainOfferMapping[offerKey].base), "Transfer Failed"); 372 | } 373 | 374 | // Mint Ctokens 375 | mintCToken(onChainOfferMapping[offerKey].tokenAddress,(onChainOfferMapping[offerKey].base).add((onChainOfferMapping[offerKey].interest))); 376 | 377 | // Set taker address 378 | onChainOfferMapping[offerKey].taker = msg.sender; 379 | 380 | // Set state to Active 381 | onChainOfferMapping[offerKey].state = 1; 382 | 383 | // Set locktime 384 | offerMapping[offerKey].lockTime = onChainOfferMapping[offerKey].duration.add(now); 385 | 386 | emit newLockedOffer(offerKey,onChainOfferMapping[offerKey].maker,onChainOfferMapping[offerKey].taker,onChainOfferMapping[offerKey].side,onChainOfferMapping[offerKey].tokenAddress,onChainOfferMapping[offerKey].duration,onChainOfferMapping[offerKey].rate,onChainOfferMapping[offerKey].interest,onChainOfferMapping[offerKey].base); 387 | } 388 | 389 | 390 | function offerSettle(address maker, address taker, uint256 side, address tokenAddress, uint256 duration, uint256 interest, uint256 base, uint256 value, bytes32 offerKey) private returns (uint256){ 391 | 392 | 393 | 394 | signedOffer memory currentOffer; 395 | 396 | CErc20 cToken = CErc20(0xdb5Ed4605C11822811a39F94314fDb8F0fb59A2C); //DAI cToken Address 397 | 398 | // Check trades side 399 | // Transfers funds to DefiHedge contract 400 | Erc20 underlying = Erc20(tokenAddress); 401 | if (side == 0) { 402 | require(underlying.transferFrom(maker, address(this), base), "Transfer Failed!"); 403 | require(underlying.transferFrom(taker, address(this), interest), "Transfer Failed!"); 404 | } 405 | if (side == 1) { 406 | require(underlying.transferFrom(maker, address(this), interest), "Transfer Failed!"); 407 | require(underlying.transferFrom(taker, address(this), base), "Transfer Failed!"); 408 | } 409 | 410 | // Mint CToken from DefiHedge contract 411 | uint mintResponse = mintCToken(tokenAddress,value); 412 | 413 | // Set locktime uint + set state to active 414 | uint lockTime = now.add(duration); 415 | 416 | uint state = 1; 417 | 418 | // Set variables for the offer on-chain 419 | currentOffer.maker = maker; 420 | currentOffer.taker = taker; 421 | currentOffer.side = side; 422 | currentOffer.tokenAddress = tokenAddress; 423 | currentOffer.duration = duration; 424 | currentOffer.rate = 0; 425 | currentOffer.interest = interest; 426 | currentOffer.base = base; 427 | currentOffer.state = state; 428 | currentOffer.lockTime = lockTime; 429 | currentOffer.initialRate = cToken.exchangeRateCurrent(); 430 | 431 | offerMapping[offerKey] = currentOffer; 432 | 433 | return mintResponse; 434 | 435 | 436 | } 437 | 438 | function fillOffer(address maker, address taker, uint side, address tokenAddress, uint duration, uint rate, uint interest, uint base, bytes memory makerSignature) public returns (uint256){ 439 | 440 | /// Instantiate offer 441 | Offer memory filledOffer = Offer( 442 | maker, 443 | address(0x0000000000000000000000000000000000000000), 444 | side, 445 | tokenAddress, 446 | duration, 447 | rate, 448 | interest, 449 | base 450 | ); 451 | 452 | // Parse signature into R,S,V 453 | RPCSig memory RPCsig = signatureRPC(makerSignature); 454 | 455 | // Validate offer signature & ensure it was created by maker 456 | require(maker == ecrecover( 457 | keccak256(abi.encodePacked( 458 | "\x19\x01", 459 | DOMAIN_SEPARATOR, 460 | hashOffer(filledOffer) 461 | )), 462 | RPCsig.v, 463 | RPCsig.r, 464 | RPCsig.s), "Invalid Signature"); 465 | 466 | // Require correct taker 467 | require(msg.sender == taker, "Invalid Calling Address"); 468 | 469 | // Create unique offer hash 470 | bytes32 offerKey = keccak256(abi.encodePacked((now),msg.sender)); 471 | 472 | uint value = interest.add(base); 473 | 474 | // Settle Response 475 | offerSettle(maker,taker,side,tokenAddress,duration,interest,base,value,offerKey); 476 | 477 | offerMapping[offerKey].rate = rate; 478 | 479 | offerList.push(offerKey); 480 | 481 | emit newLockedOffer(offerKey,maker,taker,side,tokenAddress,duration,rate,interest,base); 482 | 483 | 484 | } 485 | 486 | /// Abort an offer 487 | function abort(bytes32 offerKey) public 488 | { 489 | Erc20 underlying = Erc20(onChainOfferMapping[offerKey].tokenAddress); 490 | require(msg.sender == onChainOfferMapping[offerKey].maker, "Invalid Calling Address"); 491 | require(onChainOfferMapping[offerKey].state == 0, "Invalid State"); 492 | 493 | /// Return funds to maker 494 | if (onChainOfferMapping[offerKey].side == 1) { 495 | 496 | require(underlying.transfer(onChainOfferMapping[offerKey].maker, onChainOfferMapping[offerKey].interest)); 497 | 498 | onChainOfferMapping[offerKey].state = 2; 499 | 500 | } 501 | 502 | if (onChainOfferMapping[offerKey].side == 0) { 503 | 504 | require(underlying.transfer(onChainOfferMapping[offerKey].maker, onChainOfferMapping[offerKey].base)); 505 | 506 | onChainOfferMapping[offerKey].state = 2; 507 | 508 | } 509 | 510 | emit Aborted(offerKey); 511 | } 512 | 513 | /// Release an Erc bond once if term completed 514 | function releaseErcBond(bytes32 offerKey) 515 | public 516 | returns(uint256) 517 | { 518 | 519 | 520 | // Require swap state to be active 521 | // Require swap duration to have expired 522 | require(offerMapping[offerKey].state == 1, "Invalid State"); 523 | require(now >= offerMapping[offerKey].lockTime, "Invalid Time"); 524 | 525 | CErc20 CDai = CErc20(0xdb5Ed4605C11822811a39F94314fDb8F0fb59A2C); 526 | Erc20 underlying = Erc20(offerMapping[offerKey].tokenAddress); 527 | 528 | // Calculate annualized interest-rate generated by the swap agreement 529 | uint total = offerMapping[offerKey].base.add(offerMapping[offerKey].interest); 530 | uint rate = CDai.exchangeRateCurrent(); 531 | uint yield = ((rate.mul(100000000000000000000000000)).div(offerMapping[offerKey].initialRate)).sub(100000000000000000000000000); 532 | uint annualizedRate = ((yield.mul(31536000)).div(offerMapping[offerKey].duration)); 533 | 534 | // In order to avoid subtraction underflow, ensures subtraction of smaller annualized rate 535 | if (offerMapping[offerKey].rate > annualizedRate) { 536 | 537 | // Calculates difference between annualized expected rate / real rate 538 | uint rateDifference = (offerMapping[offerKey].rate).sub(annualizedRate); 539 | 540 | // Calculates differential in expected currency from previous rate differential 541 | uint annualFloatingDifference = (rateDifference.mul(total)).div(100000000000000000000000000); 542 | 543 | // De-annualizes the differential for the given time period 544 | uint floatingDifference = (annualFloatingDifference.div(31536000)).mul(offerMapping[offerKey].duration); 545 | 546 | // Calculates difference between value and expected interest 547 | uint floatingReturned = (offerMapping[offerKey].interest).sub(floatingDifference); 548 | 549 | // Redeems appropriate CTokens 550 | redeemCToken(0xdb5Ed4605C11822811a39F94314fDb8F0fb59A2C,(total.add(floatingReturned))); 551 | 552 | // Returns funds to appropriate parties 553 | if (offerMapping[offerKey].side == 0){ 554 | underlying.transfer(offerMapping[offerKey].maker, total); 555 | underlying.transfer(offerMapping[offerKey].taker, floatingReturned); 556 | } 557 | if (offerMapping[offerKey].side == 1){ 558 | underlying.transfer(offerMapping[offerKey].maker, floatingReturned); 559 | underlying.transfer(offerMapping[offerKey].taker, total); 560 | } 561 | } 562 | 563 | if (annualizedRate > offerMapping[offerKey].rate) { 564 | uint rateDifference = annualizedRate.sub(offerMapping[offerKey].rate); 565 | uint annualFloatingDifference = (rateDifference.mul(total)).div(100000000000000000000000000); 566 | uint floatingDifference = (annualFloatingDifference.div(31536000)).mul(offerMapping[offerKey].duration); 567 | uint floatingReturned = (offerMapping[offerKey].interest).add(floatingDifference); 568 | 569 | redeemCToken(0xdb5Ed4605C11822811a39F94314fDb8F0fb59A2C,(total.add(floatingReturned))); 570 | 571 | if (offerMapping[offerKey].side == 0){ 572 | underlying.transfer(offerMapping[offerKey].maker, total); 573 | underlying.transfer(offerMapping[offerKey].taker, floatingReturned); 574 | } 575 | if (offerMapping[offerKey].side == 1){ 576 | underlying.transfer(offerMapping[offerKey].maker, floatingReturned); 577 | underlying.transfer(offerMapping[offerKey].taker, total); 578 | } 579 | } 580 | 581 | if (annualizedRate == offerMapping[offerKey].rate) { 582 | 583 | redeemCToken(0xdb5Ed4605C11822811a39F94314fDb8F0fb59A2C,(total.add(offerMapping[offerKey].interest))); 584 | 585 | if (offerMapping[offerKey].side == 0){ 586 | underlying.transfer(offerMapping[offerKey].maker, total); 587 | underlying.transfer(offerMapping[offerKey].taker, offerMapping[offerKey].interest); 588 | } 589 | if (offerMapping[offerKey].side == 1){ 590 | underlying.transfer(offerMapping[offerKey].maker, offerMapping[offerKey].interest); 591 | underlying.transfer(offerMapping[offerKey].taker, total); 592 | } 593 | } 594 | 595 | // Change state to Expired 596 | offerMapping[offerKey].state = 2; 597 | 598 | emit bondReleased(offerKey); 599 | 600 | 601 | return(offerMapping[offerKey].state); 602 | 603 | 604 | } 605 | 606 | function releaseEthBond(bytes32 offerKey) 607 | public 608 | { 609 | 610 | // Require swap state to be active 611 | // Require swap duration to have expired 612 | require(offerMapping[offerKey].state == 1, "Invalid State"); 613 | require(now >= offerMapping[offerKey].lockTime, "Invalid Time"); 614 | 615 | CEth cEth = CEth(0xBe839b6D93E3eA47eFFcCA1F27841C917a8794f3); 616 | 617 | // Calculate annualized interest-rate generated by the swap agreement 618 | uint total = offerMapping[offerKey].base.add(offerMapping[offerKey].interest); 619 | uint rate = cEth.exchangeRateCurrent(); 620 | uint yield = ((rate.mul(100000000000000000000000000)).div(offerMapping[offerKey].initialRate)).sub(100000000000000000000000000); 621 | uint annualizedRate = ((yield.mul(31536000)).div(offerMapping[offerKey].duration)); 622 | 623 | // In order to avoid subtraction underflow, ensures subtraction of smaller annualized rate 624 | if (offerMapping[offerKey].rate > annualizedRate) { 625 | 626 | // Calculates difference between annualized expected rate / real rate 627 | uint rateDifference = (offerMapping[offerKey].rate).sub(annualizedRate); 628 | 629 | // Calculates differential in expected currency from previous rate differential 630 | uint annualFloatingDifference = (rateDifference.mul(total)).div(100000000000000000000000000); 631 | 632 | // De-annualizes the differential for the given time period 633 | uint floatingDifference = (annualFloatingDifference.div(31536000)).mul(offerMapping[offerKey].duration); 634 | 635 | // Calculates difference between value and expected interest 636 | uint floatingReturned = (offerMapping[offerKey].interest).sub(floatingDifference); 637 | 638 | 639 | // Redeems appropriate CEther 640 | redeemCEther(total.add(floatingReturned)); 641 | 642 | // Returns funds to appropriate parties 643 | if (offerMapping[offerKey].side == 0){ 644 | address payable returnMaker = address(uint160(offerMapping[offerKey].maker)); 645 | address payable returnTaker = address(uint160(offerMapping[offerKey].taker)); 646 | returnMaker.transfer(total); 647 | returnTaker.transfer(floatingReturned); 648 | } 649 | if (offerMapping[offerKey].side == 1){ 650 | address payable returnMaker = address(uint160(offerMapping[offerKey].maker)); 651 | address payable returnTaker = address(uint160(offerMapping[offerKey].taker)); 652 | returnMaker.transfer(floatingReturned); 653 | returnTaker.transfer(total); 654 | } 655 | } 656 | 657 | if (annualizedRate > offerMapping[offerKey].rate) { 658 | uint rateDifference = annualizedRate.sub(offerMapping[offerKey].rate); 659 | uint annualFloatingDifference = (rateDifference.mul(total)).div(100000000000000000000000000); 660 | uint floatingDifference = (annualFloatingDifference.div(31536000)).mul(offerMapping[offerKey].duration); 661 | uint floatingReturned = (offerMapping[offerKey].interest).add(floatingDifference); 662 | 663 | redeemCEther(total.add(floatingReturned)); 664 | 665 | if (offerMapping[offerKey].side == 0){ 666 | address payable returnMaker = address(uint160(offerMapping[offerKey].maker)); 667 | address payable returnTaker = address(uint160(offerMapping[offerKey].taker)); 668 | returnMaker.transfer(total); 669 | returnTaker.transfer(floatingReturned); 670 | } 671 | if (offerMapping[offerKey].side == 1){ 672 | address payable returnMaker = address(uint160(offerMapping[offerKey].maker)); 673 | address payable returnTaker = address(uint160(offerMapping[offerKey].taker)); 674 | returnMaker.transfer(floatingReturned); 675 | returnTaker.transfer(total); 676 | } 677 | } 678 | 679 | if (annualizedRate == offerMapping[offerKey].rate) { 680 | 681 | redeemCEther(total.add(offerMapping[offerKey].interest)); 682 | 683 | if (offerMapping[offerKey].side == 0){ 684 | address payable returnMaker = address(uint160(offerMapping[offerKey].maker)); 685 | address payable returnTaker = address(uint160(offerMapping[offerKey].taker)); 686 | returnMaker.transfer(total); 687 | returnTaker.transfer(offerMapping[offerKey].interest); 688 | } 689 | if (offerMapping[offerKey].side == 1){ 690 | address payable returnMaker = address(uint160(offerMapping[offerKey].maker)); 691 | address payable returnTaker = address(uint160(offerMapping[offerKey].taker)); 692 | returnMaker.transfer(offerMapping[offerKey].interest); 693 | returnTaker.transfer(total); 694 | } 695 | } 696 | 697 | 698 | emit bondReleased(offerKey); 699 | 700 | 701 | 702 | } 703 | 704 | /// Mint Cether 705 | function mintCEther(uint value) internal returns (uint response){ 706 | 707 | address CEthAdress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 708 | CEth cEth = CEth(CEthAdress); 709 | 710 | cEth.mint.value((value))(); 711 | 712 | return response; 713 | 714 | } 715 | /// Redeem Cether 716 | function redeemCEther(uint value) internal { 717 | address CEthAdress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 718 | CEth cEth = CEth(CEthAdress); 719 | cEth.redeemUnderlying(value); 720 | } 721 | 722 | /// Mint cToken 723 | function mintCToken( 724 | address _erc20Contract, 725 | uint _numTokensToSupply 726 | ) internal returns (uint) { 727 | 728 | Erc20 underlying = Erc20(_erc20Contract); 729 | 730 | CErc20 cToken = CErc20(0xdb5Ed4605C11822811a39F94314fDb8F0fb59A2C); 731 | 732 | // Approve transfer on the ERC20 contract 733 | underlying.approve(0xdb5Ed4605C11822811a39F94314fDb8F0fb59A2C, _numTokensToSupply); 734 | 735 | 736 | uint mintResult = cToken.mint(_numTokensToSupply); 737 | 738 | return mintResult; 739 | } 740 | 741 | /// Redeem cToken 742 | function redeemCToken( 743 | address _cErc20Contract, uint _numTokensToRedeem) internal { 744 | CErc20(_cErc20Contract).redeemUnderlying(_numTokensToRedeem); 745 | } 746 | 747 | // Splits signature into RSV 748 | function signatureRPC(bytes memory sig)internal pure returns (RPCSig memory RPCsig){ 749 | bytes32 r; 750 | bytes32 s; 751 | uint8 v; 752 | 753 | if (sig.length != 65) { 754 | return RPCSig(0,'0','0'); 755 | } 756 | 757 | assembly { 758 | r := mload(add(sig, 32)) 759 | s := mload(add(sig, 64)) 760 | v := and(mload(add(sig, 65)), 255) 761 | } 762 | 763 | if (v < 27) { 764 | v += 27; 765 | } 766 | 767 | if (v == 39 || v == 40) { 768 | v = v-12; 769 | } 770 | 771 | if (v != 27 && v != 28) { 772 | return RPCSig(0,'0','0'); 773 | } 774 | 775 | return RPCSig(v,r,s); 776 | } 777 | 778 | } 779 | 780 | -------------------------------------------------------------------------------- /OnChainMVP.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./safeMath.sol"; 4 | 5 | contract Erc20 { 6 | function approve(address, uint) external returns (bool); 7 | function transfer(address, uint) external returns (bool); 8 | function balanceOf(address _owner) external returns (uint256 balance); 9 | function transferFrom(address sender, address recipient, uint256 amount) public returns (bool); 10 | } 11 | 12 | contract CErc20 is Erc20 { 13 | function mint(uint) external returns (uint); 14 | function redeem(uint redeemTokens) external returns (uint); 15 | function redeemUnderlying(uint redeemAmount) external returns (uint); 16 | function exchangeRateCurrent() external returns (uint); 17 | } 18 | 19 | contract CEth { 20 | function mint() external payable; 21 | function redeem(uint redeemTokens) external returns (uint); 22 | function balanceOf(address _owner) external returns (uint256 balance); 23 | function approve(address spender, uint tokens) public returns (bool success); 24 | function redeemUnderlying(uint redeemAmount) external returns (uint); 25 | function exchangeRateCurrent() external returns (uint); 26 | } 27 | 28 | contract DefiHedge { 29 | 30 | struct bondContract { 31 | address maker; 32 | address taker; 33 | uint side; 34 | address tokenAddress; 35 | address cTokenAddress; 36 | uint duration; 37 | uint rate; 38 | uint interest; 39 | uint base; 40 | uint lockTime; 41 | uint state; 42 | uint initialRate; 43 | } 44 | 45 | mapping (bytes32 => bondContract) bondContracts; 46 | 47 | bytes32[] public bondContractList; 48 | 49 | event newFixedSideEthContract( 50 | bytes32 offerKey, 51 | uint rate, 52 | uint duration, 53 | uint value 54 | ); 55 | 56 | event newFloatingSideEthContract( 57 | bytes32 offerKey, 58 | uint rate, 59 | uint duration, 60 | uint value 61 | ); 62 | 63 | event newFixedSideErcContract( 64 | bytes32 offerKey, 65 | uint rate, 66 | uint duration, 67 | address token, 68 | uint tokenNumber 69 | ); 70 | 71 | event newFloatingSideErcContract( 72 | bytes32 offerKey, 73 | uint rate, 74 | uint duration, 75 | address token, 76 | uint tokenNumber 77 | ); 78 | 79 | event Aborted( 80 | bytes32 offerKey 81 | ); 82 | 83 | event termEnded( 84 | bytes32 offerKey 85 | ); 86 | 87 | event Activated( 88 | bytes32 offerKey 89 | ); 90 | 91 | constructor() 92 | public 93 | { 94 | } 95 | 96 | using SafeMath for uint; 97 | 98 | function getOffer(bytes32 offerKey) 99 | public 100 | view 101 | returns (address maker, uint side, uint state, uint duration, uint rate, uint base, uint interest, address tokenAddress) 102 | { 103 | maker = bondContracts[offerKey].maker; 104 | side = bondContracts[offerKey].side; 105 | state = bondContracts[offerKey].state; 106 | duration = bondContracts[offerKey].duration; 107 | rate = bondContracts[offerKey].rate; 108 | base = bondContracts[offerKey].base; 109 | interest = bondContracts[offerKey].interest; 110 | tokenAddress = bondContracts[offerKey].tokenAddress; 111 | return (maker, side, state, duration, rate, base, interest, tokenAddress); 112 | } 113 | 114 | // deploy a new Eth fixed side lending contract 115 | function createEthFixedOffer(uint rate, uint duration) 116 | public 117 | payable 118 | returns (bytes32 _offerKey) 119 | { 120 | uint trueInterest = ((((rate.mul(msg.value)).div(365 days)).div(100)).mul(duration)); 121 | 122 | bytes32 offerKey = keccak256(abi.encodePacked((uint2str(now.mul(1000))),(address2str(msg.sender)))); 123 | bondContract storage ethContract = bondContracts[offerKey]; 124 | 125 | ethContract.maker = address(msg.sender); 126 | ethContract.side = 0; 127 | ethContract.tokenAddress = 0x0000000000000000000000000000000000000000; 128 | ethContract.cTokenAddress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 129 | ethContract.duration = duration; 130 | ethContract.rate = rate; 131 | ethContract.state = 0; 132 | ethContract.base = msg.value; 133 | ethContract.interest = ((trueInterest.add(5e11)).div(1e12)).mul(1e12); 134 | 135 | bondContractList.push(offerKey) -1; 136 | 137 | emit newFixedSideEthContract(offerKey, rate, duration, msg.value); 138 | 139 | return offerKey; 140 | } 141 | 142 | // deploy a new Eth floating side lending contract 143 | function createEthFloatingOffer(uint rate, uint duration) 144 | public 145 | payable 146 | returns (bytes32 _offerKey) 147 | { 148 | 149 | uint trueBase = (((msg.value.mul(365 days)).div((rate.div(100)).mul(duration)))); 150 | 151 | address _address = address(msg.sender); 152 | bytes32 offerKey = keccak256(abi.encodePacked((uint2str(now.mul(1000))),(address2str(_address)))); 153 | bondContract storage ethContract = bondContracts[offerKey]; 154 | 155 | ethContract.maker = address(msg.sender); 156 | ethContract.side = 1; 157 | ethContract.tokenAddress = 0x0000000000000000000000000000000000000000; 158 | ethContract.cTokenAddress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 159 | ethContract.duration = duration; 160 | ethContract.rate = rate; 161 | ethContract.state = 0; 162 | ethContract.interest = msg.value; 163 | ethContract.base = (((trueBase.add(5e11)).div(1e12)).mul(1e12)); 164 | 165 | bondContractList.push(offerKey) -1; 166 | 167 | emit newFloatingSideEthContract(offerKey, rate, duration, msg.value); 168 | 169 | return offerKey; 170 | } 171 | 172 | // deploy a new ERC20 fixed side lending contract 173 | function createErcFixedOffer( uint rate, uint duration, address erc20Contract, address cErc20Contract, uint tokenNumber) 174 | public 175 | returns (bytes32 _offerKey) 176 | { 177 | 178 | Erc20 underlying = Erc20(erc20Contract); 179 | underlying.transferFrom(msg.sender, address(this), tokenNumber); 180 | 181 | /// Hash time + user address to create a unique key 182 | address _address = address(msg.sender); 183 | bytes32 offerKey = keccak256(abi.encodePacked((uint2str(now.mul(1000))),(address2str(_address)))); 184 | bondContract storage ercContract = bondContracts[offerKey]; 185 | 186 | ercContract.maker = address(msg.sender); 187 | ercContract.side = 0; 188 | ercContract.tokenAddress = erc20Contract; 189 | ercContract.cTokenAddress = cErc20Contract; 190 | ercContract.duration = duration; 191 | ercContract.rate = rate; 192 | ercContract.state = 0; 193 | ercContract.base = tokenNumber; 194 | ercContract.interest = ((((((ercContract.rate.mul(ercContract.base)).div(365 days)).div(100)).mul(ercContract.duration)).add(5e11)).div(1e12)).mul(1e12); 195 | 196 | bondContractList.push(offerKey) -1; 197 | 198 | emit newFixedSideErcContract(offerKey, rate, duration, erc20Contract, tokenNumber); 199 | 200 | return offerKey; 201 | } 202 | 203 | 204 | /// deploy a new ERC20 floating side lending contract 205 | function createErcFloatingOffer(uint rate, uint duration, address erc20Contract, address cErc20Contract, uint tokenNumber) 206 | public 207 | returns (bytes32 _offerKey) 208 | { 209 | Erc20 underlying = Erc20(erc20Contract); 210 | underlying.transferFrom(msg.sender, address(this), tokenNumber); 211 | 212 | 213 | uint trueBase = (((tokenNumber.mul(365 days)).div((rate.div(100)).mul(duration)))); 214 | 215 | /// Hash time + user address to create a unique key 216 | address _address = address(msg.sender); 217 | bytes32 offerKey = keccak256(abi.encodePacked((uint2str(now.mul(1000))),(address2str(_address)))); 218 | bondContract storage ercContract = bondContracts[offerKey]; 219 | 220 | ercContract.maker = address(msg.sender); 221 | ercContract.side = 1; 222 | ercContract.tokenAddress = erc20Contract; 223 | ercContract.cTokenAddress = cErc20Contract; 224 | ercContract.duration = duration; 225 | ercContract.rate = rate; 226 | ercContract.state = 0; 227 | ercContract.interest = tokenNumber; 228 | ercContract.base = (((trueBase.add(5e11)).div(1e12)).mul(1e12)); 229 | 230 | bondContractList.push(offerKey) -1; 231 | 232 | emit newFloatingSideErcContract(offerKey, rate, duration, erc20Contract, tokenNumber); 233 | 234 | return offerKey; 235 | } 236 | 237 | function takeErcOffer(bytes32 offerKey) 238 | public 239 | { 240 | if (bondContracts[offerKey].side == 0) { 241 | Erc20 underlying = Erc20(bondContracts[offerKey].tokenAddress); 242 | underlying.transferFrom(msg.sender, address(this), bondContracts[offerKey].interest); 243 | 244 | bondContracts[offerKey].lockTime = now + bondContracts[offerKey].duration; 245 | 246 | uint value = bondContracts[offerKey].interest.add(bondContracts[offerKey].base); 247 | 248 | mintCToken(bondContracts[offerKey].tokenAddress, bondContracts[offerKey].cTokenAddress, value, offerKey); 249 | 250 | bondContracts[offerKey].taker = msg.sender; 251 | bondContracts[offerKey].state = 1; 252 | emit Activated(offerKey); 253 | } 254 | 255 | if (bondContracts[offerKey].side == 1) { 256 | underlying = Erc20(bondContracts[offerKey].tokenAddress); 257 | underlying.transferFrom(msg.sender, address(this), bondContracts[offerKey].base); 258 | 259 | bondContracts[offerKey].lockTime = now + bondContracts[offerKey].duration; 260 | 261 | value = bondContracts[offerKey].interest.add(bondContracts[offerKey].base); 262 | 263 | mintCToken(bondContracts[offerKey].tokenAddress, bondContracts[offerKey].cTokenAddress, value, offerKey); 264 | 265 | bondContracts[offerKey].taker = msg.sender; 266 | bondContracts[offerKey].state = 1; 267 | emit Activated(offerKey); 268 | } 269 | } 270 | 271 | function takeEthOffer(bytes32 offerKey) 272 | public 273 | payable 274 | { 275 | if (bondContracts[offerKey].side == 0) { 276 | require(msg.value >= bondContracts[offerKey].interest); 277 | 278 | uint value = bondContracts[offerKey].interest.add(bondContracts[offerKey].base); 279 | 280 | mintCEther(value, offerKey); 281 | 282 | bondContracts[offerKey].lockTime = now + bondContracts[offerKey].duration; 283 | 284 | bondContracts[offerKey].taker = msg.sender; 285 | bondContracts[offerKey].state = 1; 286 | 287 | emit Activated(offerKey); 288 | } 289 | 290 | if (bondContracts[offerKey].side == 1) { 291 | require(msg.value >= bondContracts[offerKey].base); 292 | 293 | value = bondContracts[offerKey].interest.add(bondContracts[offerKey].base); 294 | 295 | mintCEther(value, offerKey); 296 | 297 | bondContracts[offerKey].lockTime = now + bondContracts[offerKey].duration; 298 | 299 | bondContracts[offerKey].taker = msg.sender; 300 | bondContracts[offerKey].state = 1; 301 | 302 | emit Activated(offerKey); 303 | } 304 | } 305 | 306 | /// Abort an offer 307 | function abort(bytes32 offerKey) 308 | public 309 | { 310 | require(msg.sender == bondContracts[offerKey].maker); 311 | require(bondContracts[offerKey].state == 0) 312 | emit Aborted(offerKey); 313 | 314 | /// Return funds to maker 315 | if (bondContracts[offerKey].side == 1) { 316 | bondContracts[offerKey].maker.transfer(bondContracts[offerKey].interest); 317 | bondContracts[offerKey].state = 2; 318 | } 319 | if (bondContracts[offerKey].side == 0) { 320 | bondContracts[offerKey].maker.transfer(bondContracts[offerKey].base); 321 | bondContracts[offerKey].state = 2; 322 | } 323 | } 324 | 325 | /// Release an Eth bond once if term completed 326 | function releaseEthBond(bytes32 offerKey) 327 | public 328 | { 329 | require(now > bondContracts[offerKey].lockTime); 330 | 331 | /// Redeem CEther & return funds to respective parties 332 | 333 | address CEthAdress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 334 | CEth cEth = CEth(CEthAdress); 335 | 336 | uint total = bondContracts[offerKey].base.add(bondContracts[offerKey].interest); 337 | uint avgRate = (cEth.exchangeRateCurrent().sub(bondContracts[offerKey].initialRate)).div(bondContracts[offerKey].initialRate); 338 | 339 | if (bondContracts[offerKey].side == 0) { 340 | 341 | if (avgRate > bondContracts[offerKey].rate) { 342 | uint floatingProfit = (avgRate.sub(bondContracts[offerKey].rate)).mul(total); 343 | uint floatingReturned = floatingProfit.add(bondContracts[offerKey].interest); 344 | redeemCEther((total.add(floatingReturned))); 345 | bondContracts[offerKey].maker.transfer(total); 346 | bondContracts[offerKey].taker.transfer(floatingReturned); 347 | emit termEnded(offerKey); 348 | bondContracts[offerKey].state = 2; 349 | } 350 | 351 | if (avgRate < bondContracts[offerKey].rate){ 352 | uint floatingOwed = (avgRate.sub(bondContracts[offerKey].rate)).mul(total); 353 | floatingReturned = floatingOwed.add(bondContracts[offerKey].interest); 354 | redeemCEther((total.add(floatingReturned))); 355 | bondContracts[offerKey].maker.transfer(total); 356 | bondContracts[offerKey].taker.transfer(floatingReturned); 357 | emit termEnded(offerKey); 358 | bondContracts[offerKey].state = 2; 359 | } 360 | 361 | } 362 | 363 | if (bondContracts[offerKey].side == 1) { 364 | 365 | if (avgRate > bondContracts[offerKey].rate) { 366 | floatingProfit = (avgRate.sub(bondContracts[offerKey].rate)).mul(total); 367 | floatingReturned = floatingProfit.add(bondContracts[offerKey].interest); 368 | redeemCEther((total.add(floatingReturned))); 369 | bondContracts[offerKey].maker.transfer(floatingReturned); 370 | bondContracts[offerKey].taker.transfer(total); 371 | emit termEnded(offerKey); 372 | bondContracts[offerKey].state = 2; 373 | } 374 | 375 | if (avgRate < bondContracts[offerKey].rate){ 376 | floatingOwed = (avgRate.sub(bondContracts[offerKey].rate)).mul(total); 377 | floatingReturned = floatingOwed.add(bondContracts[offerKey].interest); 378 | redeemCEther((total.add(floatingReturned))); 379 | bondContracts[offerKey].maker.transfer(floatingReturned); 380 | bondContracts[offerKey].taker.transfer(total); 381 | emit termEnded(offerKey); 382 | bondContracts[offerKey].state = 2; 383 | } 384 | 385 | } 386 | 387 | 388 | } 389 | 390 | /// Release an ERC bond once if term completed 391 | function releaseErcBond(bytes32 offerKey) 392 | public 393 | { 394 | address cTokenAddress = bondContracts[offerKey].cTokenAddress; 395 | address tokenAddress = bondContracts[offerKey].tokenAddress; 396 | 397 | Erc20 underlying = Erc20(tokenAddress); 398 | CErc20 cToken = CErc20(cTokenAddress); 399 | 400 | /// Calculate interests, Redeem cTokens & return funds to respective parties 401 | uint total = bondContracts[offerKey].base.add(bondContracts[offerKey].interest); 402 | uint avgRate = (cToken.exchangeRateCurrent().sub(bondContracts[offerKey].initialRate)).div(bondContracts[offerKey].initialRate); 403 | 404 | if (bondContracts[offerKey].side == 0) { 405 | 406 | if (avgRate > bondContracts[offerKey].rate) { 407 | uint floatingProfit = (avgRate.sub(bondContracts[offerKey].rate)).mul(total); 408 | uint floatingReturned = floatingProfit.add(bondContracts[offerKey].interest); 409 | redeemCToken(cTokenAddress,(total.add(floatingReturned))); 410 | underlying.transfer(bondContracts[offerKey].maker, total); 411 | underlying.transfer(bondContracts[offerKey].taker, floatingReturned); 412 | emit termEnded(offerKey); 413 | bondContracts[offerKey].state = 2; 414 | } 415 | 416 | if (avgRate < bondContracts[offerKey].rate){ 417 | uint floatingOwed = (avgRate.sub(bondContracts[offerKey].rate)).mul(total); 418 | floatingReturned = floatingProfit.add(bondContracts[offerKey].interest); 419 | redeemCToken(cTokenAddress,(total.add(floatingReturned))); 420 | underlying.transfer(bondContracts[offerKey].maker, total); 421 | underlying.transfer(bondContracts[offerKey].taker, floatingReturned); 422 | emit termEnded(offerKey); 423 | bondContracts[offerKey].state = 2; 424 | } 425 | 426 | } 427 | 428 | if (bondContracts[offerKey].side == 1) { 429 | 430 | if (avgRate > bondContracts[offerKey].rate) { 431 | floatingProfit = (avgRate.sub(bondContracts[offerKey].rate)).mul(total); 432 | floatingReturned = floatingProfit.add(bondContracts[offerKey].interest); 433 | redeemCToken(cTokenAddress,(total.add(floatingReturned))); 434 | underlying.transfer(bondContracts[offerKey].maker, floatingReturned); 435 | underlying.transfer(bondContracts[offerKey].taker, total); 436 | emit termEnded(offerKey); 437 | bondContracts[offerKey].state = 2; 438 | } 439 | 440 | if (avgRate < bondContracts[offerKey].rate){ 441 | floatingOwed = (avgRate.sub(bondContracts[offerKey].rate)).mul(total); 442 | floatingReturned = floatingProfit.add(bondContracts[offerKey].interest); 443 | redeemCToken(cTokenAddress,(total.add(floatingReturned))); 444 | underlying.transfer(bondContracts[offerKey].maker, floatingReturned); 445 | underlying.transfer(bondContracts[offerKey].taker, total); 446 | emit termEnded(offerKey); 447 | bondContracts[offerKey].state = 2; 448 | } 449 | } 450 | } 451 | 452 | /// Mint Cether 453 | function mintCEther(uint value, bytes32 offerKey) internal { 454 | 455 | address CEthAdress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 456 | CEth cEth = CEth(CEthAdress); 457 | 458 | bondContracts[offerKey].initialRate = cEth.exchangeRateCurrent(); 459 | 460 | cEth.mint.value((value))(); 461 | 462 | } 463 | /// Redeem Cether 464 | function redeemCEther(uint value) internal { 465 | address CEthAdress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 466 | CEth cEth = CEth(CEthAdress); 467 | cEth.redeemUnderlying(value); 468 | } 469 | 470 | /// Mint cToken 471 | function mintCToken( 472 | address _erc20Contract, 473 | address _cErc20Contract, 474 | uint _numTokensToSupply, 475 | bytes32 offerKey 476 | ) internal returns (uint) { 477 | 478 | Erc20 underlying = Erc20(_erc20Contract); 479 | 480 | CErc20 cToken = CErc20(_cErc20Contract); 481 | 482 | // Approve transfer on the ERC20 contract 483 | underlying.approve(_cErc20Contract, _numTokensToSupply); 484 | 485 | bondContracts[offerKey].initialRate = cToken.exchangeRateCurrent(); 486 | 487 | uint mintResult = cToken.mint(_numTokensToSupply); 488 | return mintResult; 489 | } 490 | 491 | /// Redeem cToken 492 | function redeemCToken( 493 | address _cErc20Contract, uint _numTokensToRedeem) internal { 494 | CErc20(_cErc20Contract).redeemUnderlying(_numTokensToRedeem); 495 | } 496 | 497 | function uint2str(uint i) internal pure returns (string){ 498 | if (i == 0) return "0"; 499 | uint j = i; 500 | uint length; 501 | while (j != 0){ 502 | length++; 503 | j /= 10; 504 | } 505 | bytes memory bstr = new bytes(length); 506 | uint k = length - 1; 507 | while (i != 0){ 508 | bstr[k--] = byte(48 + i % 10); 509 | i /= 10; 510 | } 511 | return string(bstr); 512 | } 513 | function address2str(address x) internal pure returns (string) { 514 | bytes memory b = new bytes(20); 515 | for (uint i = 0; i < 20; i++) 516 | b[i] = byte(uint8(uint(x) / (2**(8*(19 - i))))); 517 | return string(b); 518 | } 519 | } 520 | 521 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swivel Finance 2 | 3 | The Decentralized Marketplace for Fixed-Rate Lending & Interest Rate Derivatives 4 | (Previously Defihedge) 5 | 6 | Run locally: 7 | 8 | ``` 9 | npm install http-server 10 | npx http-server 11 | ``` 12 | Hosted publicly on 13 | 14 | IPFS: [QmQde8Ha84B3ogD2Dxictvfs2LJYDFK73akgZArYJn3FTS](https://gateway.pinata.cloud/ipfs/QmQde8Ha84B3ogD2Dxictvfs2LJYDFK73akgZArYJn3FTS/) 15 | 16 | HTTP: [Defihedge.Finance](https://defi-hedge-protocol.vercel.app/) 17 | -------------------------------------------------------------------------------- /contracts/offerContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./safeMath.sol"; 4 | 5 | contract Erc20 { 6 | function approve(address, uint) external returns (bool); 7 | function transfer(address, uint) external returns (bool); 8 | function balanceOf(address _owner) external returns (uint256 balance); 9 | function transferFrom(address sender, address recipient, uint256 amount) public returns (bool); 10 | } 11 | 12 | contract CErc20 is Erc20 { 13 | function mint(uint) external returns (uint); 14 | function redeem(uint redeemTokens) external returns (uint); 15 | } 16 | 17 | contract CEth { 18 | function mint() external payable; 19 | function redeem(uint redeemTokens) external returns (uint); 20 | function balanceOf(address _owner) external returns (uint256 balance); 21 | function approve(address spender, uint tokens) public returns (bool success); 22 | } 23 | contract offerContract { 24 | address[] public contracts; 25 | 26 | event newFixedSideEthContract( 27 | address contractAddress, 28 | uint rate, 29 | uint duration, 30 | uint value 31 | ); 32 | 33 | event newFloatingSideEthContract( 34 | address contractAddress, 35 | uint rate, 36 | uint duration, 37 | uint value 38 | ); 39 | 40 | event newFixedSideErcContract( 41 | address contractAddress, 42 | uint rate, 43 | uint duration, 44 | address token, 45 | uint tokenNumber 46 | ); 47 | 48 | event newFloatingSideErcContract( 49 | address contractAddress, 50 | uint rate, 51 | uint duration, 52 | address token, 53 | uint tokenNumber 54 | ); 55 | 56 | constructor() 57 | public 58 | { 59 | } 60 | 61 | // deploy a new Eth fixed side lending contract 62 | function offerEthFixedSide( uint rate, uint duration) 63 | public 64 | payable 65 | returns(address newEthContract) 66 | { 67 | 68 | FixedSideEthContract EthContract = (new FixedSideEthContract).value(msg.value)(address(msg.sender), rate, duration); 69 | contracts.push(EthContract); 70 | emit newFixedSideEthContract(address(EthContract), rate, duration, msg.value); 71 | return EthContract; 72 | } 73 | 74 | // deploy a new Eth floating side lending contract 75 | function offerEthFloatingSide( uint rate, uint duration) 76 | public 77 | payable 78 | returns(address newEthContract) 79 | { 80 | 81 | FloatingSideEthContract EthContract = (new FloatingSideEthContract).value(msg.value)(address(msg.sender), rate, duration); 82 | contracts.push(EthContract); 83 | emit newFloatingSideEthContract(address(EthContract), rate, duration, msg.value); 84 | return EthContract; 85 | } 86 | 87 | // deploy a new ERC20 fixed side lending contract 88 | function offerErcFixedSide( uint rate, uint duration, address erc20Contract, address cEr20Contract, uint tokenNumber) 89 | public 90 | payable 91 | returns(address newErcContract) 92 | { 93 | Erc20 underlying = Erc20(erc20Contract); 94 | underlying.transferFrom(msg.sender, address(this), tokenNumber); 95 | FixedSideErcContract ErcContract = (new FixedSideErcContract).value(0)(address(msg.sender), rate, duration, erc20Contract, cEr20Contract, tokenNumber); 96 | contracts.push(ErcContract); 97 | underlying.transfer(address(ErcContract), tokenNumber); 98 | emit newFixedSideErcContract(address(ErcContract), rate, duration, erc20Contract, tokenNumber); 99 | return ErcContract; 100 | } 101 | 102 | // deploy a new ERC20 fixed side lending contract 103 | function offerErcFloatingSide( uint rate, uint duration, address erc20Contract, address cEr20Contract, uint tokenNumber) 104 | public 105 | payable 106 | returns(address newErcContract) 107 | { 108 | Erc20 underlying = Erc20(erc20Contract); 109 | underlying.transferFrom(msg.sender, address(this), tokenNumber); 110 | FloatingSideErcContract ErcContract = (new FloatingSideErcContract).value(0)(address(msg.sender), rate, duration, erc20Contract, cEr20Contract, tokenNumber); 111 | contracts.push(ErcContract); 112 | underlying.transfer(address(ErcContract), tokenNumber); 113 | emit newFloatingSideErcContract(address(ErcContract), rate, duration, erc20Contract, tokenNumber); 114 | return ErcContract; 115 | } 116 | 117 | 118 | } 119 | 120 | contract FixedSideEthContract { 121 | uint public value; 122 | address public offerer; 123 | address public taker; 124 | uint public rate; 125 | uint public interest; 126 | uint public duration; 127 | uint public lockTime; 128 | enum State { Created, Locked, Inactive } 129 | State public state; 130 | 131 | using SafeMath for uint; 132 | 133 | constructor(address contractOfferer, uint fixRate, uint termDuration) public payable { 134 | offerer = contractOfferer; 135 | value = msg.value; 136 | rate = fixRate; 137 | duration = termDuration; 138 | uint trueInterest = ((((rate.mul(value)).div(31622400)).div(100)).mul(duration)); 139 | uint added = trueInterest.add(500000000000); 140 | uint divided = added.div(1000000000000); 141 | interest = divided.mul(1000000000000); 142 | } 143 | 144 | modifier onlyTaker() { 145 | require(msg.sender == taker); 146 | _; 147 | } 148 | 149 | modifier onlyOfferer() { 150 | require(msg.sender == offerer); 151 | _; 152 | } 153 | 154 | modifier inState(State _state) { 155 | require(state == _state); 156 | _; 157 | } 158 | 159 | event Aborted(address contractAddress); 160 | event OfferConfirmed(address contractAddress, uint rate, uint lockTime, uint value); 161 | event termEnded(address contractAddress); 162 | 163 | 164 | /// Abort the offer and reclaim the ether. 165 | /// Can only be called by the offerer before 166 | /// the contract is locked. 167 | function abort() 168 | public 169 | onlyOfferer 170 | inState(State.Created) 171 | { 172 | emit Aborted(address(this)); 173 | state = State.Inactive; 174 | offerer.transfer(address(this).balance); 175 | } 176 | 177 | /// Confirm the offer as taker. 178 | /// The ether will be locked until bondRelease 179 | function takeOffer() 180 | public 181 | inState(State.Created) 182 | payable 183 | { 184 | require(msg.value >= interest); 185 | taker = msg.sender; 186 | state = State.Locked; 187 | lockTime = now + duration; 188 | mintCEther(); 189 | emit OfferConfirmed(address(this), rate, lockTime, value); 190 | } 191 | /// Make contract payable 192 | function () public payable { } 193 | 194 | /// This will release the locked ether. 195 | function bondRelease() 196 | public 197 | inState(State.Locked) 198 | { 199 | require(now > lockTime); 200 | emit termEnded(address(this)); 201 | 202 | state = State.Inactive; 203 | 204 | /// Redeem CEther & return funds to respective parties 205 | redeemCEther(); 206 | uint total = value.add(interest); 207 | offerer.transfer(total); 208 | taker.transfer(address(this).balance); 209 | } 210 | /// Mint Cether 211 | function mintCEther() internal { 212 | address CEthAdress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 213 | CEth(CEthAdress).mint.value((value+interest))(); 214 | 215 | } 216 | /// Redeem Cether 217 | function redeemCEther() internal { 218 | address CEthAdress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 219 | uint balance = CEth(CEthAdress).balanceOf(address(this)); 220 | CEth(CEthAdress).redeem(balance); 221 | } 222 | } 223 | 224 | contract FixedSideErcContract { 225 | uint public tokenNumber; 226 | address public erc20Contract; 227 | address public cErc20Contract; 228 | address public offerer; 229 | address public taker; 230 | uint public rate; 231 | uint public interest; 232 | uint public duration; 233 | uint public lockTime; 234 | enum State { Created, Locked, Inactive } 235 | State public state; 236 | 237 | using SafeMath for uint; 238 | 239 | constructor(address contractOfferer, uint fixRate, uint termDuration, address ercContract, address cErcContract, uint tokenNum) public payable { 240 | offerer = contractOfferer; 241 | rate = fixRate; 242 | duration = termDuration; 243 | tokenNumber = tokenNum; 244 | erc20Contract = ercContract; 245 | cErc20Contract = cErcContract; 246 | uint trueInterest = ((((rate.mul(tokenNumber)).div(31622400)).div(100)).mul(duration)); 247 | uint added = trueInterest.add(500000000000); 248 | uint divided = added.div(1000000000000); 249 | interest = divided.mul(1000000000000); 250 | } 251 | 252 | modifier onlyTaker() { 253 | require(msg.sender == taker); 254 | _; 255 | } 256 | 257 | modifier onlyOfferer() { 258 | require(msg.sender == offerer); 259 | _; 260 | } 261 | 262 | modifier inState(State _state) { 263 | require(state == _state); 264 | _; 265 | } 266 | 267 | event Aborted(address contractAddress); 268 | event OfferConfirmed(address contractAddress, uint rate, address token, uint lockTime, uint tokenNumber); 269 | event termEnded(address contractAddress); 270 | 271 | /// Abort the offer and reclaim the ether. 272 | /// Can only be called by the offerer before 273 | /// the contract is locked. 274 | function abort() 275 | public 276 | onlyOfferer 277 | inState(State.Created) 278 | { 279 | emit Aborted(address(this)); 280 | state = State.Inactive; 281 | offerer.transfer(address(this).balance); 282 | } 283 | 284 | /// Confirm the offer as taker. 285 | /// The token will be locked until bondRelease 286 | function takeOffer() 287 | public 288 | inState(State.Created) 289 | payable 290 | { 291 | Erc20 underlying = Erc20(erc20Contract); 292 | underlying.transferFrom(msg.sender, address(this), interest); 293 | taker = msg.sender; 294 | state = State.Locked; 295 | lockTime = now + duration; 296 | mintCToken(erc20Contract, cErc20Contract, (tokenNumber+interest)); 297 | emit OfferConfirmed(address(this), rate, erc20Contract, lockTime, tokenNumber); 298 | } 299 | /// Make contract payable 300 | function () public payable { } 301 | 302 | /// This will release the locked ether. 303 | function bondRelease() 304 | public 305 | inState(State.Locked) 306 | { 307 | require(now > lockTime); 308 | emit termEnded(address(this)); 309 | 310 | state = State.Inactive; 311 | 312 | // Create a reference to the underlying asset contract 313 | Erc20 underlying = Erc20(erc20Contract); 314 | 315 | /// Redeem cToken & return funds to respective parties 316 | redeemCToken(cErc20Contract); 317 | 318 | uint total = tokenNumber.add(interest); 319 | 320 | underlying.transfer(offerer, total); 321 | underlying.transfer(taker, address(this).balance); 322 | } 323 | /// Mint cToken 324 | function mintCToken( 325 | address _erc20Contract, 326 | address _cErc20Contract, 327 | uint256 _numTokensToSupply 328 | ) internal returns (uint) { 329 | 330 | // Create a reference to the underlying asset contract, like DAI. 331 | Erc20 underlying = Erc20(_erc20Contract); 332 | 333 | // Create a reference to the corresponding cToken contract, like cDAI 334 | CErc20 cToken = CErc20(_cErc20Contract); 335 | 336 | // Approve transfer on the ERC20 contract 337 | underlying.approve(_cErc20Contract, _numTokensToSupply); 338 | 339 | // Mint cTokens and return the result 340 | uint mintResult = cToken.mint(_numTokensToSupply); 341 | return mintResult; 342 | } 343 | 344 | /// Redeem cToken 345 | function redeemCToken( 346 | address _cErc20Contract) internal { 347 | uint balance = CErc20(_cErc20Contract).balanceOf(address(this)); 348 | CErc20(_cErc20Contract).redeem(balance); 349 | } 350 | } 351 | 352 | contract FloatingSideErcContract { 353 | uint public tokenNumber; 354 | address public erc20Contract; 355 | address public cErc20Contract; 356 | address public offerer; 357 | address public taker; 358 | uint public rate; 359 | uint public nominal; 360 | uint public duration; 361 | uint public lockTime; 362 | enum State { Created, Locked, Inactive } 363 | State public state; 364 | 365 | using SafeMath for uint; 366 | 367 | constructor(address contractOfferer, uint fixRate, uint termDuration, address ercContract, address cErcContract, uint tokenNum) public payable { 368 | offerer = contractOfferer; 369 | rate = fixRate; 370 | duration = termDuration; 371 | tokenNumber = tokenNum; 372 | erc20Contract = ercContract; 373 | cErc20Contract = cErcContract; 374 | uint trueNominal = (((tokenNumber.mul(31622400)).div((rate.div(100)).mul(duration)))); 375 | uint added = trueNominal.add(500000000000); 376 | uint divided = added.div(1000000000000); 377 | nominal = divided.mul(1000000000000); 378 | } 379 | 380 | modifier onlyTaker() { 381 | require(msg.sender == taker); 382 | _; 383 | } 384 | 385 | modifier onlyOfferer() { 386 | require(msg.sender == offerer); 387 | _; 388 | } 389 | 390 | modifier inState(State _state) { 391 | require(state == _state); 392 | _; 393 | } 394 | 395 | event Aborted(address contractAddress); 396 | event OfferConfirmed(address contractAddress, uint rate, address token, uint lockTime, uint tokenNumber); 397 | event termEnded(address contractAddress); 398 | 399 | /// Abort the offer and reclaim the ether. 400 | /// Can only be called by the offerer before 401 | /// the contract is locked. 402 | function abort() 403 | public 404 | onlyOfferer 405 | inState(State.Created) 406 | { 407 | emit Aborted(address(this)); 408 | state = State.Inactive; 409 | offerer.transfer(address(this).balance); 410 | } 411 | 412 | /// Confirm the offer as taker. 413 | /// The token will be locked until bondRelease 414 | function takeOffer() 415 | public 416 | inState(State.Created) 417 | payable 418 | { 419 | Erc20 underlying = Erc20(erc20Contract); 420 | underlying.transferFrom(msg.sender, address(this), nominal); 421 | taker = msg.sender; 422 | state = State.Locked; 423 | lockTime = now + duration; 424 | mintCToken(erc20Contract, cErc20Contract, (tokenNumber+nominal)); 425 | emit OfferConfirmed(address(this), rate, erc20Contract, lockTime, tokenNumber); 426 | } 427 | /// Make contract payable 428 | function () public payable { } 429 | 430 | /// This will release the locked ether. 431 | function bondRelease() 432 | public 433 | inState(State.Locked) 434 | { 435 | require(now > lockTime); 436 | emit termEnded(address(this)); 437 | 438 | state = State.Inactive; 439 | 440 | // Create a reference to the underlying asset contract 441 | Erc20 underlying = Erc20(erc20Contract); 442 | 443 | /// Redeem cToken & return funds to respective parties 444 | redeemCToken(cErc20Contract); 445 | 446 | uint total = tokenNumber.add(nominal); 447 | 448 | underlying.transfer(taker, total); 449 | underlying.transfer(offerer, address(this).balance); 450 | } 451 | /// Mint cToken 452 | function mintCToken( 453 | address _erc20Contract, 454 | address _cErc20Contract, 455 | uint256 _numTokensToSupply 456 | ) internal returns (uint) { 457 | 458 | // Create a reference to the underlying asset contract, like DAI. 459 | Erc20 underlying = Erc20(_erc20Contract); 460 | 461 | // Create a reference to the corresponding cToken contract, like cDAI 462 | CErc20 cToken = CErc20(_cErc20Contract); 463 | 464 | // Approve transfer on the ERC20 contract 465 | underlying.approve(_cErc20Contract, _numTokensToSupply); 466 | 467 | // Mint cTokens and return the result 468 | uint mintResult = cToken.mint(_numTokensToSupply); 469 | return mintResult; 470 | } 471 | 472 | /// Redeem cToken 473 | function redeemCToken( 474 | address _cErc20Contract) internal { 475 | uint balance = CErc20(_cErc20Contract).balanceOf(address(this)); 476 | CErc20(_cErc20Contract).redeem(balance); 477 | } 478 | } 479 | 480 | contract FloatingSideEthContract { 481 | uint public value; 482 | address public offerer; 483 | address public taker; 484 | uint public rate; 485 | uint public nominal; 486 | uint public duration; 487 | uint public lockTime; 488 | enum State { Created, Locked, Inactive } 489 | State public state; 490 | 491 | using SafeMath for uint; 492 | 493 | constructor(address contractOfferer, uint fixRate, uint termDuration) public payable { 494 | offerer = contractOfferer; 495 | value = msg.value; 496 | rate = fixRate; 497 | duration = termDuration; 498 | uint trueNominal = (((value.mul(31622400)).div((rate.div(100)).mul(duration)))); 499 | uint added = trueNominal.add(500000000000); 500 | uint divided = added.div(1000000000000); 501 | nominal = divided.mul(1000000000000); 502 | } 503 | 504 | modifier onlyTaker() { 505 | require(msg.sender == taker); 506 | _; 507 | } 508 | 509 | modifier onlyOfferer() { 510 | require(msg.sender == offerer); 511 | _; 512 | } 513 | 514 | modifier inState(State _state) { 515 | require(state == _state); 516 | _; 517 | } 518 | 519 | event Aborted(address contractAddress); 520 | event OfferConfirmed(address contractAddress, uint rate, uint lockTime, uint value); 521 | event termEnded(address contractAddress); 522 | 523 | 524 | /// Abort the offer and reclaim the ether. 525 | /// Can only be called by the offerer before 526 | /// the contract is locked. 527 | function abort() 528 | public 529 | onlyOfferer 530 | inState(State.Created) 531 | { 532 | emit Aborted(address(this)); 533 | state = State.Inactive; 534 | offerer.transfer(address(this).balance); 535 | } 536 | 537 | /// Confirm the offer as taker. 538 | /// The ether will be locked until bondRelease 539 | function takeOffer() 540 | public 541 | inState(State.Created) 542 | payable 543 | { 544 | require(msg.value >= nominal); 545 | taker = msg.sender; 546 | state = State.Locked; 547 | lockTime = now + duration; 548 | mintCEther(); 549 | emit OfferConfirmed(address(this), rate, lockTime, value); 550 | } 551 | /// Make contract payable 552 | function () public payable { } 553 | 554 | /// This will release the locked ether. 555 | function bondRelease() 556 | public 557 | inState(State.Locked) 558 | { 559 | require(now > lockTime); 560 | emit termEnded(address(this)); 561 | 562 | state = State.Inactive; 563 | 564 | /// Redeem CEther & return funds to respective parties 565 | redeemCEther(); 566 | uint total = value.add(nominal); 567 | taker.transfer(total); 568 | offerer.transfer(address(this).balance); 569 | } 570 | /// Mint Cether 571 | function mintCEther() internal { 572 | address CEthAdress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 573 | CEth(CEthAdress).mint.value((value+nominal))(); 574 | 575 | } 576 | /// Redeem Cether 577 | function redeemCEther() internal { 578 | address CEthAdress = 0x1d70B01A2C3e3B2e56FcdcEfe50d5c5d70109a5D; 579 | uint balance = CEth(CEthAdress).balanceOf(address(this)); 580 | CEth(CEthAdress).redeem(balance); 581 | } 582 | } -------------------------------------------------------------------------------- /css/julios-blank-site-e50fbc.webflow.css: -------------------------------------------------------------------------------- 1 | .w-layout-grid { 2 | display: -ms-grid; 3 | display: grid; 4 | grid-auto-columns: 1fr; 5 | -ms-grid-columns: 1fr 1fr; 6 | grid-template-columns: 1fr 1fr; 7 | -ms-grid-rows: auto auto; 8 | grid-template-rows: auto auto; 9 | grid-row-gap: 16px; 10 | grid-column-gap: 16px; 11 | } 12 | 13 | body { 14 | font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; 15 | color: #333; 16 | font-size: 14px; 17 | line-height: 20px; 18 | } 19 | 20 | 21 | .container { 22 | height: 1222px; 23 | border: 0px solid #000; 24 | } 25 | 26 | .columns { 27 | margin-top:-40px; 28 | float: none; 29 | } 30 | 31 | .createcolumn { 32 | height: 525px; 33 | margin-top: 133px; 34 | border-style: solid; 35 | border-width: 5px; 36 | border-color: #6a686d; 37 | border-radius: 20px; 38 | background-color: #28292e; 39 | } 40 | 41 | .offercolumn { 42 | height: 380px; 43 | margin-top: 200px; 44 | } 45 | 46 | .column-3 { 47 | height: 525px; 48 | margin-top: 133px; 49 | background-color: #28292e; 50 | } 51 | 52 | .offerdiv { 53 | height: 340px; 54 | margin-top: 22px; 55 | margin-right: -12px; 56 | margin-left: -6px; 57 | border: 5px solid #6a686d; 58 | border-radius: 20px; 59 | background-color: #28292e; 60 | } 61 | 62 | .body { 63 | background-image: url('../images/background.png'); 64 | background-position: 0px 0px; 65 | background-size: 125px; 66 | } 67 | 68 | .ercbutton { 69 | width: 110px; 70 | height: 70px; 71 | min-width: 50px; 72 | margin-top: 35px; 73 | margin-left: 25px; 74 | border-style: solid; 75 | border-width: 5px; 76 | border-color: #353535; 77 | border-radius: 20px; 78 | background-color: #232f44; 79 | box-shadow: 1px 1px 9px 4px #000; 80 | -webkit-transform: skew(0deg, 0deg); 81 | -ms-transform: skew(0deg, 0deg); 82 | transform: skew(0deg, 0deg); 83 | -webkit-transition: flex-grow 450ms ease-in-out, -webkit-box-flex 450ms ease-in-out, -webkit-flex-grow 450ms ease-in-out; 84 | transition: flex-grow 450ms ease-in-out, -webkit-box-flex 450ms ease-in-out, -webkit-flex-grow 450ms ease-in-out; 85 | transition: flex-grow 450ms ease-in-out; 86 | transition: flex-grow 450ms ease-in-out, -webkit-box-flex 450ms ease-in-out, -webkit-flex-grow 450ms ease-in-out, -ms-flex-positive 450ms ease-in-out; 87 | direction: ltr; 88 | font-size: 30px; 89 | line-height: 40px; 90 | text-align: center; 91 | letter-spacing: 0px; 92 | text-decoration: none; 93 | text-transform: none; 94 | white-space: normal; 95 | } 96 | 97 | .section { 98 | display: block; 99 | overflow: visible; 100 | float: none; 101 | grid-auto-columns: 1fr; 102 | grid-column-gap: 16px; 103 | grid-row-gap: 16px; 104 | -ms-grid-columns: 1fr 1fr; 105 | grid-template-columns: 1fr 1fr; 106 | -ms-grid-rows: auto auto; 107 | grid-template-rows: auto auto; 108 | } 109 | 110 | .ratetext { 111 | width: 200px; 112 | margin-top: 29px; 113 | margin-left: 19px; 114 | -webkit-transform: translate(0px, 20px); 115 | -ms-transform: translate(0px, 20px); 116 | transform: translate(0px, 20px); 117 | color: #7c7c7c; 118 | font-size: 26px; 119 | } 120 | 121 | .rate-field { 122 | width: 120px; 123 | margin-top: -150px; 124 | margin-left: 162px; 125 | } 126 | 127 | .fd { 128 | width: 120px; 129 | margin-left: 162px; 130 | } 131 | 132 | .token-field { 133 | width: 120px; 134 | margin-left: 162px; 135 | } 136 | 137 | .supplied-field { 138 | width: 120px; 139 | margin-left: 162px; 140 | } 141 | 142 | .createofferbutton { 143 | width: 180px; 144 | height: 80px; 145 | margin-top: 0px; 146 | margin-left: 0px; 147 | padding-top: 27px; 148 | border-style: solid; 149 | border-width: 3px; 150 | border-color: #286f35; 151 | border-radius: 11px; 152 | background-color: #141414; 153 | box-shadow: 4px 4px 20px 0 #000; 154 | -webkit-transform: translate(55px, 60px); 155 | -ms-transform: translate(55px, 60px); 156 | transform: translate(55px, 60px); 157 | -webkit-transition: opacity 200ms ease, opacity 200ms ease; 158 | transition: opacity 200ms ease, opacity 200ms ease; 159 | font-size: 25px; 160 | text-align: center; 161 | white-space: normal; 162 | } 163 | 164 | .takecolumn { 165 | height: 525px; 166 | -webkit-transform: translate(8px, 0px); 167 | -ms-transform: translate(8px, 0px); 168 | transform: translate(8px, 0px); 169 | margin-top: 133px; 170 | padding-right: 10px; 171 | border: 5px solid #6a686d; 172 | border-radius: 20px; 173 | background-color: #28292e; 174 | } 175 | 176 | .grid { 177 | width: 290px; 178 | height: 300px; 179 | margin-top: 15px; 180 | margin-left: 6px; 181 | grid-column-gap: 12px; 182 | grid-row-gap: 5px; 183 | -ms-grid-columns: 1fr; 184 | grid-template-columns: 1fr; 185 | -ms-grid-rows: auto auto auto auto auto auto auto auto auto auto auto auto; 186 | grid-template-rows: auto auto auto auto auto auto auto auto auto auto auto auto; 187 | border: 0px solid #000; 188 | border-radius: 8px; 189 | background-color: #474747; 190 | } 191 | 192 | .activelabel { 193 | height: 5px; 194 | margin-left: 13px; 195 | padding-bottom: 6px; 196 | border: 0px solid #000; 197 | border-radius: 0px; 198 | -webkit-transform: translate(0px, 5px); 199 | -ms-transform: translate(0px, 5px); 200 | transform: translate(0px, 5px); 201 | color: #e7e7e7; 202 | font-size: 12px; 203 | } 204 | .error-message { 205 | margin-left: auto; 206 | background-color: #ffe7de; 207 | } 208 | 209 | .useraddress { 210 | width: 250px; 211 | margin-right: 76px; 212 | padding-top: 8px; 213 | float: right; 214 | clear: none; 215 | -webkit-transform: translate(0px, 0px); 216 | -ms-transform: translate(0px, 0px); 217 | transform: translate(0px, 0px); 218 | color: #e7e7e7; 219 | font-size: 12px; 220 | text-align: left; 221 | text-indent: 20px; 222 | } 223 | 224 | .selectedoffer { 225 | margin-top: 25px; 226 | padding-top: 10px; 227 | padding-left: 6px; 228 | color: #e7e7e7; 229 | font-size: 12px; 230 | text-align: left 231 | } 232 | 233 | .div-block-2 { 234 | width: 120px; 235 | height: 35px; 236 | min-width: 120px; 237 | float: none; 238 | clear: none; 239 | background-color: #fff; 240 | -webkit-transform: translate(171px, 0px); 241 | -ms-transform: translate(171px, 0px); 242 | transform: translate(171px, 0px); 243 | } 244 | 245 | .div-block-3 { 246 | width: 120px; 247 | height: 35px; 248 | background-color: #fff8f8; 249 | -webkit-transform: translate(171px, -85px); 250 | -ms-transform: translate(171px, -85px); 251 | transform: translate(171px, -85px); 252 | } 253 | 254 | .div-block-3-copy { 255 | width: 120px; 256 | height: 35px; 257 | background-color: #fff8f8; 258 | -webkit-transform: translate(171px, -170px); 259 | -ms-transform: translate(171px, -170px); 260 | transform: translate(171px, -170px); 261 | } 262 | 263 | .div-block-3-copy-copy { 264 | width: 120px; 265 | height: 35px; 266 | background-color: #fff8f8; 267 | -webkit-transform: translate(171px, -300px); 268 | -ms-transform: translate(171px, -300px); 269 | transform: translate(171px, -300px); 270 | } 271 | 272 | .div-block-3-copy-copy-copy { 273 | width: 120px; 274 | height: 35px; 275 | background-color: #fff8f8; 276 | -webkit-transform: translate(171px, -288px); 277 | -ms-transform: translate(171px, -288px); 278 | transform: translate(171px, -288px); 279 | } 280 | 281 | .stakelabel { 282 | width: 120px; 283 | height: 35px; 284 | background-color: #fff; 285 | -webkit-transform: translate(171px, 0px); 286 | -ms-transform: translate(171px, 0px); 287 | transform: translate(171px, 0px); 288 | } 289 | 290 | .ratelabel { 291 | width: 120px; 292 | height: 35px; 293 | background-color: #fff; 294 | -webkit-transform: translate(171px, -233px); 295 | -ms-transform: translate(171px, -233px); 296 | transform: translate(171px, -233px); 297 | } 298 | 299 | .durationlabel { 300 | width: 120px; 301 | height: 35px; 302 | background-color: #fff; 303 | -webkit-transform: translate(171px, -219px); 304 | -ms-transform: translate(171px, -219px); 305 | transform: translate(171px, -219px); 306 | } 307 | 308 | .tokenlabel { 309 | width: 120px; 310 | height: 35px; 311 | background-color: #fff; 312 | -webkit-transform: translate(171px, -205px); 313 | -ms-transform: translate(171px, -205px); 314 | transform: translate(171px, -205px); 315 | } 316 | 317 | .suppliedlabel { 318 | width: 120px; 319 | height: 35px; 320 | background-color: #fff; 321 | -webkit-transform: translate(171px, -190px); 322 | -ms-transform: translate(171px, -190px); 323 | transform: translate(171px, -190px); 324 | } 325 | 326 | .authorizebutton1 { 327 | width: 140px; 328 | border-radius: 20px; 329 | background-color: #585858; 330 | box-shadow: 1px 0 12px 0 #000; 331 | -webkit-transform: translate(10px, -88px); 332 | -ms-transform: translate(10px, -88px); 333 | transform: translate(10px, -88px); 334 | text-align: center; 335 | } 336 | 337 | .durationtext2 { 338 | width: 200px; 339 | margin-top: 29px; 340 | margin-left: 19px; 341 | -webkit-transform: translate(0px, 30px); 342 | -ms-transform: translate(0px, 30px); 343 | transform: translate(0px, 30px); 344 | color: #7c7c7c; 345 | font-size: 26px; 346 | } 347 | 348 | .tokentext2 { 349 | width: 200px; 350 | margin-top: 29px; 351 | margin-left: 19px; 352 | -webkit-transform: translate(0px, 30px); 353 | -ms-transform: translate(0px, 30px); 354 | transform: translate(0px, 30px); 355 | color: #7c7c7c; 356 | font-size: 26px; 357 | } 358 | 359 | .suppliedtext2 { 360 | width: 200px; 361 | margin-top: 29px; 362 | margin-left: 19px; 363 | -webkit-transform: translate(0px, 30px); 364 | -ms-transform: translate(0px, 30px); 365 | transform: translate(0px, 30px); 366 | color: #7c7c7c; 367 | font-size: 26px; 368 | } 369 | 370 | .takertext { 371 | width: 200px; 372 | margin-top: 29px; 373 | margin-left: 19px; 374 | -webkit-transform: translate(0px, 30px); 375 | -ms-transform: translate(0px, 30px); 376 | transform: translate(0px, 30px); 377 | color: #7c7c7c; 378 | font-size: 26px; 379 | } 380 | 381 | .takeofferbutton { 382 | width: 180px; 383 | height: 80px; 384 | margin-bottom: -29px; 385 | padding-top: 27px; 386 | border: 3px solid #286f35; 387 | border-radius: 11px; 388 | background-color: #141414; 389 | box-shadow: 4px 4px 20px 0 #000; 390 | -webkit-transform: translate(57px, -95px); 391 | -ms-transform: translate(57px, -95px); 392 | transform: translate(57px, -95px); 393 | font-size: 25px; 394 | text-align: center; 395 | } 396 | 397 | .durationtext { 398 | width: 200px; 399 | margin-top: 29px; 400 | margin-left: 19px; 401 | -webkit-transform: translate(0px, 15px); 402 | -ms-transform: translate(0px, 15px); 403 | transform: translate(0px, 15px); 404 | color: #7c7c7c; 405 | font-size: 26px; 406 | } 407 | 408 | .tokentext { 409 | width: 200px; 410 | margin-top: 29px; 411 | margin-left: 19px; 412 | -webkit-transform: translate(0px, 15px); 413 | -ms-transform: translate(0px, 15px); 414 | transform: translate(0px, 15px); 415 | color: #7c7c7c; 416 | font-size: 26px; 417 | } 418 | 419 | .suppliedtext { 420 | width: 200px; 421 | margin-top: 29px; 422 | margin-left: 19px; 423 | -webkit-transform: translate(0px, 15px); 424 | -ms-transform: translate(0px, 15px); 425 | transform: translate(0px, 15px); 426 | color: #7c7c7c; 427 | font-size: 26px; 428 | } 429 | 430 | .ratetext2 { 431 | width: 200px; 432 | margin-top: 29px; 433 | margin-left: 19px; 434 | -webkit-transform: translate(0px, 30px); 435 | -ms-transform: translate(0px, 30px); 436 | transform: translate(0px, 30px); 437 | color: #7c7c7c; 438 | font-size: 26px; 439 | } 440 | 441 | .text-field { 442 | width: 120px; 443 | -webkit-transform: translate(162px, 0px); 444 | -ms-transform: translate(162px, 0px); 445 | transform: translate(162px, 0px); 446 | } 447 | 448 | .bannerblock { 449 | height: 40px; 450 | margin-top: 10px; 451 | border-radius: 6px; 452 | background-color: #232f44; 453 | box-shadow: 1px 1px 5px 13px #000; 454 | } 455 | 456 | .offer2 { 457 | height: 5px; 458 | margin-left: 13px; 459 | border: 0px solid #000; 460 | border-radius: 0px; 461 | color: #e7e7e7; 462 | } 463 | 464 | .offer3 { 465 | height: 5px; 466 | margin-left: 13px; 467 | border: 0px solid #000; 468 | border-radius: 0px; 469 | color: #e7e7e7; 470 | } 471 | 472 | .activecontracts { 473 | width: 800px; 474 | height: 150px; 475 | border: 3px solid #6a686d; 476 | border-radius: 20px; 477 | background-color: #28292e; 478 | transform: translate(0px,-350px); 479 | margin-left:30%; 480 | } 481 | .pocText { 482 | margin-top: 10px; 483 | color: #FFFFFF; 484 | margin-left:42.5%; 485 | transform: translate(0px,-350px); 486 | } 487 | .pocText2 { 488 | margin-left:45%; 489 | margin-right:auto; 490 | color: #FFFFFF; 491 | transform: translate(-280px,-350px); 492 | } 493 | .offer1 { 494 | height: 5px; 495 | margin-top: -3px; 496 | margin-left: 10px; 497 | padding-top: 3px; 498 | border: 0px solid #000; 499 | border-radius: 0px; 500 | color: #e7e7e7; 501 | font-size: 12px; 502 | } 503 | 504 | .offer4 { 505 | height: 5px; 506 | margin-left: 13px; 507 | border: 0px solid #000; 508 | border-radius: 0px; 509 | color: #e7e7e7; 510 | } 511 | 512 | .contractslabel { 513 | -webkit-transform: translate(15px, 0px); 514 | -ms-transform: translate(15px, 0px); 515 | transform: translate(15px, 0px); 516 | color: #fff; 517 | } 518 | 519 | .contract1 { 520 | width: 200px; 521 | -webkit-transform: translate(15px, 0px); 522 | -ms-transform: translate(15px, 0px); 523 | transform: translate(15px, 0px); 524 | color: #fff; 525 | } 526 | 527 | .contractsize1 { 528 | width: 125px; 529 | -webkit-transform: translate(290px, -20px); 530 | -ms-transform: translate(290px, -20px); 531 | transform: translate(290px, -20px); 532 | color: #fff; 533 | text-align: right; 534 | } 535 | 536 | .contractrate1 { 537 | width: 100px; 538 | float: right; 539 | -webkit-transform: translate(-70px, -40px); 540 | -ms-transform: translate(-70px, -40px); 541 | transform: translate(-70px, -40px); 542 | color: #fff; 543 | text-align: left; 544 | } 545 | 546 | .authorizebutton2 { 547 | width: 140px; 548 | border-radius: 20px; 549 | background-color: #585858; 550 | box-shadow: 1px 0 12px 0 #000; 551 | -webkit-transform: translate(10px, -124px); 552 | -ms-transform: translate(10px, -124px); 553 | transform: translate(10px, -124px); 554 | text-align: center; 555 | } 556 | 557 | .form { 558 | -webkit-transform: translate(0px, -10px); 559 | -ms-transform: translate(0px, -10px); 560 | transform: translate(0px, -10px); 561 | } 562 | 563 | .contractrate { 564 | margin-left: 6px; 565 | padding-top: 8px; 566 | } 567 | 568 | .txstatus { 569 | width: 450px; 570 | color: #fff; 571 | text-align: left; 572 | font-size: 12px; 573 | } 574 | 575 | .text-block { 576 | width: 450px; 577 | color: #fff; 578 | text-align: right; 579 | } 580 | 581 | .txstatus1 { 582 | width: 450px; 583 | -webkit-transform: translate(15px, 10px); 584 | -ms-transform: translate(15px, 10px); 585 | transform: translate(15px, 10px); 586 | color: #fff; 587 | text-align: left; 588 | font-size: 12px; 589 | } 590 | .div-block-4 { 591 | width: 290px; 592 | height: 40px; 593 | margin-top: -16px; 594 | margin-bottom: -13px; 595 | border: 0px dashed #000; 596 | border-radius: 8px; 597 | background-color: #232f44; 598 | box-shadow: 1px 1px 11px 0 #000; 599 | } 600 | 601 | .releasebutton1 { 602 | width: 60px; 603 | height: 20px; 604 | padding: 0px 5px; 605 | float: right; 606 | border-radius: 15px; 607 | background-color: #232f44; 608 | box-shadow: 1px 1px 6px 0 #000; 609 | -webkit-transform: translate(86px, -40px); 610 | -ms-transform: translate(86px, -40px); 611 | transform: translate(86px, -40px); 612 | text-align: left; 613 | } 614 | 615 | .releasebutton2 { 616 | width: 60px; 617 | height: 20px; 618 | padding: 0px 5px; 619 | float: right; 620 | border-radius: 15px; 621 | background-color: #232f44; 622 | box-shadow: 1px 1px 6px 0 #000; 623 | -webkit-transform: translate(146px, -10px); 624 | -ms-transform: translate(146px, -10px); 625 | transform: translate(146px, -10px); 626 | text-align: left; 627 | } 628 | 629 | .releasebutton2-copy { 630 | width: 60px; 631 | height: 20px; 632 | padding: 0px 5px; 633 | float: right; 634 | border-radius: 15px; 635 | background-color: #232f44; 636 | box-shadow: 1px 1px 6px 0 #000; 637 | -webkit-transform: translate(206px, 19px); 638 | -ms-transform: translate(206px, 19px); 639 | transform: translate(206px, 19px); 640 | text-align: left; 641 | } 642 | 643 | .contract1-copy { 644 | width: 200px; 645 | -webkit-transform: translate(15px, 0px); 646 | -ms-transform: translate(15px, 0px); 647 | transform: translate(15px, 0px); 648 | color: #fff; 649 | } 650 | 651 | .contract2 { 652 | width: 200px; 653 | -webkit-transform: translate(15px, -10px); 654 | -ms-transform: translate(15px, -10px); 655 | transform: translate(15px, -10px); 656 | color: #fff; 657 | } 658 | 659 | .contractsize2 { 660 | width: 125px; 661 | -webkit-transform: translate(290px, -30px); 662 | -ms-transform: translate(290px, -30px); 663 | transform: translate(290px, -30px); 664 | color: #fff; 665 | text-align: right; 666 | } 667 | 668 | .contractrate2 { 669 | width: 100px; 670 | float: right; 671 | -webkit-transform: translate(-70px, -50px); 672 | -ms-transform: translate(-70px, -50px); 673 | transform: translate(-70px, -50px); 674 | color: #fff; 675 | text-align: left; 676 | } 677 | 678 | .contract3 { 679 | width: 200px; 680 | -webkit-transform: translate(15px, -20px); 681 | -ms-transform: translate(15px, -20px); 682 | transform: translate(15px, -20px); 683 | color: #fff; 684 | } 685 | 686 | .contractsize3 { 687 | width: 125px; 688 | -webkit-transform: translate(290px, -40px); 689 | -ms-transform: translate(290px, -40px); 690 | transform: translate(290px, -40px); 691 | color: #fff; 692 | text-align: right; 693 | } 694 | 695 | .contractrate3 { 696 | width: 100px; 697 | float: right; 698 | -webkit-transform: translate(-70px, -60px); 699 | -ms-transform: translate(-70px, -60px); 700 | transform: translate(-70px, -60px); 701 | color: #fff; 702 | text-align: left; 703 | } 704 | 705 | .contractduration { 706 | margin-left: 6px; 707 | padding-top: 8px; 708 | } 709 | 710 | .contractaddress { 711 | margin-left: 6px; 712 | padding-top: 8px; 713 | } 714 | 715 | .contractsupplied { 716 | margin-left: 6px; 717 | padding-top: 8px; 718 | } 719 | 720 | .contractstake { 721 | margin-left: 6px; 722 | padding-top: 8px; 723 | } 724 | 725 | .contractexpire1 { 726 | width: 150px; 727 | float: right; 728 | -webkit-transform: translate(-100px, -120px); 729 | -ms-transform: translate(-100px, -120px); 730 | transform: translate(-100px, -120px); 731 | color: #fff; 732 | text-align: left; 733 | } 734 | 735 | 736 | .contractexpire2 { 737 | width: 150px; 738 | float: right; 739 | -webkit-transform: translate(49px, -90px); 740 | -ms-transform: translate(49px, -90px); 741 | transform: translate(49px, -90px); 742 | color: #fff; 743 | text-align: left; 744 | } 745 | 746 | .contractexpire3 { 747 | width: 150px; 748 | float: right; 749 | -webkit-transform: translate(200px, -60px); 750 | -ms-transform: translate(200px, -60px); 751 | transform: translate(200px, -60px); 752 | color: #fff; 753 | text-align: left; 754 | } 755 | 756 | .useraddresslabel { 757 | width: 120px; 758 | margin-right: 76px; 759 | padding-top: 8px; 760 | float: right; 761 | clear: none; 762 | -webkit-transform: translate(95px, -20px); 763 | -ms-transform: translate(95px, -20px); 764 | transform: translate(95px, -20px); 765 | color: #e7e7e7; 766 | font-size: 14px; 767 | text-align: left; 768 | text-indent: 20px; 769 | font-size: 12px; 770 | } 771 | 772 | .image { 773 | margin:auto; 774 | position: relative; 775 | transform: translate(0px, 50px); 776 | right: -35%; 777 | float: none; 778 | clear: none; 779 | background-color: #020202; 780 | } -------------------------------------------------------------------------------- /css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ 2 | /** 3 | * 1. Set default font family to sans-serif. 4 | * 2. Prevent iOS and IE text size adjust after device orientation change, 5 | * without disabling user zoom. 6 | */ 7 | html { 8 | font-family: sans-serif; 9 | /* 1 */ 10 | -ms-text-size-adjust: 100%; 11 | /* 2 */ 12 | -webkit-text-size-adjust: 100%; 13 | /* 2 */ 14 | } 15 | /** 16 | * Remove default margin. 17 | */ 18 | body { 19 | margin: 0; 20 | } 21 | /* HTML5 display definitions 22 | ========================================================================== */ 23 | /** 24 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 25 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 26 | * and Firefox. 27 | * Correct `block` display not defined for `main` in IE 11. 28 | */ 29 | article, 30 | aside, 31 | details, 32 | figcaption, 33 | figure, 34 | footer, 35 | header, 36 | hgroup, 37 | main, 38 | menu, 39 | nav, 40 | section, 41 | summary { 42 | display: block; 43 | } 44 | /** 45 | * 1. Correct `inline-block` display not defined in IE 8/9. 46 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 47 | */ 48 | audio, 49 | canvas, 50 | progress, 51 | video { 52 | display: inline-block; 53 | /* 1 */ 54 | vertical-align: baseline; 55 | /* 2 */ 56 | } 57 | /** 58 | * Prevent modern browsers from displaying `audio` without controls. 59 | * Remove excess height in iOS 5 devices. 60 | */ 61 | audio:not([controls]) { 62 | display: none; 63 | height: 0; 64 | } 65 | /** 66 | * Address `[hidden]` styling not present in IE 8/9/10. 67 | * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22. 68 | */ 69 | [hidden], 70 | template { 71 | display: none; 72 | } 73 | /* Links 74 | ========================================================================== */ 75 | /** 76 | * Remove the gray background color from active links in IE 10. 77 | */ 78 | a { 79 | background-color: transparent; 80 | } 81 | /** 82 | * Improve readability of focused elements when they are also in an 83 | * active/hover state. 84 | */ 85 | a:active, 86 | a:hover { 87 | outline: 0; 88 | } 89 | /* Text-level semantics 90 | ========================================================================== */ 91 | /** 92 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 93 | */ 94 | abbr[title] { 95 | border-bottom: 1px dotted; 96 | } 97 | /** 98 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 99 | */ 100 | b, 101 | strong { 102 | font-weight: bold; 103 | } 104 | /** 105 | * Address styling not present in Safari and Chrome. 106 | */ 107 | dfn { 108 | font-style: italic; 109 | } 110 | /** 111 | * Address variable `h1` font-size and margin within `section` and `article` 112 | * contexts in Firefox 4+, Safari, and Chrome. 113 | */ 114 | h1 { 115 | font-size: 2em; 116 | margin: 0.67em 0; 117 | } 118 | /** 119 | * Address styling not present in IE 8/9. 120 | */ 121 | mark { 122 | background: #ff0; 123 | color: #000; 124 | } 125 | /** 126 | * Address inconsistent and variable font size in all browsers. 127 | */ 128 | small { 129 | font-size: 80%; 130 | } 131 | /** 132 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 133 | */ 134 | sub, 135 | sup { 136 | font-size: 75%; 137 | line-height: 0; 138 | position: relative; 139 | vertical-align: baseline; 140 | } 141 | sup { 142 | top: -0.5em; 143 | } 144 | sub { 145 | bottom: -0.25em; 146 | } 147 | /* Embedded content 148 | ========================================================================== */ 149 | /** 150 | * Remove border when inside `a` element in IE 8/9/10. 151 | */ 152 | img { 153 | border: 0; 154 | } 155 | /** 156 | * Correct overflow not hidden in IE 9/10/11. 157 | */ 158 | svg:not(:root) { 159 | overflow: hidden; 160 | } 161 | /* Grouping content 162 | ========================================================================== */ 163 | /** 164 | * Address margin not present in IE 8/9 and Safari. 165 | */ 166 | figure { 167 | margin: 1em 40px; 168 | } 169 | /** 170 | * Address differences between Firefox and other browsers. 171 | */ 172 | hr { 173 | box-sizing: content-box; 174 | height: 0; 175 | } 176 | /** 177 | * Contain overflow in all browsers. 178 | */ 179 | pre { 180 | overflow: auto; 181 | } 182 | /** 183 | * Address odd `em`-unit font size rendering in all browsers. 184 | */ 185 | code, 186 | kbd, 187 | pre, 188 | samp { 189 | font-family: monospace, monospace; 190 | font-size: 1em; 191 | } 192 | /* Forms 193 | ========================================================================== */ 194 | /** 195 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 196 | * styling of `select`, unless a `border` property is set. 197 | */ 198 | /** 199 | * 1. Correct color not being inherited. 200 | * Known issue: affects color of disabled elements. 201 | * 2. Correct font properties not being inherited. 202 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 203 | */ 204 | button, 205 | input, 206 | optgroup, 207 | select, 208 | textarea { 209 | color: inherit; 210 | /* 1 */ 211 | font: inherit; 212 | /* 2 */ 213 | margin: 0; 214 | /* 3 */ 215 | } 216 | /** 217 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 218 | */ 219 | button { 220 | overflow: visible; 221 | } 222 | /** 223 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 224 | * All other form control elements do not inherit `text-transform` values. 225 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 226 | * Correct `select` style inheritance in Firefox. 227 | */ 228 | button, 229 | select { 230 | text-transform: none; 231 | } 232 | /** 233 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 234 | * and `video` controls. 235 | * 2. Correct inability to style clickable `input` types in iOS. 236 | * 3. Improve usability and consistency of cursor style between image-type 237 | * `input` and others. 238 | * 4. CUSTOM FOR WEBFLOW: Removed the input[type="submit"] selector to reduce 239 | * specificity and defer to the .w-button selector 240 | */ 241 | button, 242 | html input[type="button"], 243 | input[type="reset"] { 244 | -webkit-appearance: button; 245 | /* 2 */ 246 | cursor: pointer; 247 | /* 3 */ 248 | } 249 | /** 250 | * Re-set default cursor for disabled elements. 251 | */ 252 | button[disabled], 253 | html input[disabled] { 254 | cursor: default; 255 | } 256 | /** 257 | * Remove inner padding and border in Firefox 4+. 258 | */ 259 | button::-moz-focus-inner, 260 | input::-moz-focus-inner { 261 | border: 0; 262 | padding: 0; 263 | } 264 | /** 265 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 266 | * the UA stylesheet. 267 | */ 268 | input { 269 | line-height: normal; 270 | } 271 | /** 272 | * It's recommended that you don't attempt to style these elements. 273 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 274 | * 275 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 276 | * 2. Remove excess padding in IE 8/9/10. 277 | */ 278 | input[type="checkbox"], 279 | input[type="radio"] { 280 | box-sizing: border-box; 281 | /* 1 */ 282 | padding: 0; 283 | /* 2 */ 284 | } 285 | /** 286 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 287 | * `font-size` values of the `input`, it causes the cursor style of the 288 | * decrement button to change from `default` to `text`. 289 | */ 290 | input[type="number"]::-webkit-inner-spin-button, 291 | input[type="number"]::-webkit-outer-spin-button { 292 | height: auto; 293 | } 294 | /** 295 | * 1. CUSTOM FOR WEBFLOW: changed from `textfield` to `none` to normalize iOS rounded input 296 | * 2. CUSTOM FOR WEBFLOW: box-sizing: content-box rule removed 297 | * (similar to normalize.css >=4.0.0) 298 | */ 299 | input[type="search"] { 300 | -webkit-appearance: none; 301 | /* 1 */ 302 | } 303 | /** 304 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 305 | * Safari (but not Chrome) clips the cancel button when the search input has 306 | * padding (and `textfield` appearance). 307 | */ 308 | input[type="search"]::-webkit-search-cancel-button, 309 | input[type="search"]::-webkit-search-decoration { 310 | -webkit-appearance: none; 311 | } 312 | /** 313 | * Define consistent border, margin, and padding. 314 | */ 315 | fieldset { 316 | border: 1px solid #c0c0c0; 317 | margin: 0 2px; 318 | padding: 0.35em 0.625em 0.75em; 319 | } 320 | /** 321 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 322 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 323 | */ 324 | legend { 325 | border: 0; 326 | /* 1 */ 327 | padding: 0; 328 | /* 2 */ 329 | } 330 | /** 331 | * Remove default vertical scrollbar in IE 8/9/10/11. 332 | */ 333 | textarea { 334 | overflow: auto; 335 | } 336 | /** 337 | * Don't inherit the `font-weight` (applied by a rule above). 338 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 339 | */ 340 | optgroup { 341 | font-weight: bold; 342 | } 343 | /* Tables 344 | ========================================================================== */ 345 | /** 346 | * Remove most spacing between table cells. 347 | */ 348 | table { 349 | border-collapse: collapse; 350 | border-spacing: 0; 351 | } 352 | td, 353 | th { 354 | padding: 0; 355 | } 356 | -------------------------------------------------------------------------------- /css/webflow.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'webflow-icons'; 3 | src: url("data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBiUAAAC8AAAAYGNtYXDpP+a4AAABHAAAAFxnYXNwAAAAEAAAAXgAAAAIZ2x5ZmhS2XEAAAGAAAADHGhlYWQTFw3HAAAEnAAAADZoaGVhCXYFgQAABNQAAAAkaG10eCe4A1oAAAT4AAAAMGxvY2EDtALGAAAFKAAAABptYXhwABAAPgAABUQAAAAgbmFtZSoCsMsAAAVkAAABznBvc3QAAwAAAAAHNAAAACAAAwP4AZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpAwPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAQAAAAAwACAACAAQAAQAg5gPpA//9//8AAAAAACDmAOkA//3//wAB/+MaBBcIAAMAAQAAAAAAAAAAAAAAAAABAAH//wAPAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEBIAAAAyADgAAFAAAJAQcJARcDIP5AQAGA/oBAAcABwED+gP6AQAABAOAAAALgA4AABQAAEwEXCQEH4AHAQP6AAYBAAcABwED+gP6AQAAAAwDAAOADQALAAA8AHwAvAAABISIGHQEUFjMhMjY9ATQmByEiBh0BFBYzITI2PQE0JgchIgYdARQWMyEyNj0BNCYDIP3ADRMTDQJADRMTDf3ADRMTDQJADRMTDf3ADRMTDQJADRMTAsATDSANExMNIA0TwBMNIA0TEw0gDRPAEw0gDRMTDSANEwAAAAABAJ0AtAOBApUABQAACQIHCQEDJP7r/upcAXEBcgKU/usBFVz+fAGEAAAAAAL//f+9BAMDwwAEAAkAABcBJwEXAwE3AQdpA5ps/GZsbAOabPxmbEMDmmz8ZmwDmvxmbAOabAAAAgAA/8AEAAPAAB0AOwAABSInLgEnJjU0Nz4BNzYzMTIXHgEXFhUUBw4BBwYjNTI3PgE3NjU0Jy4BJyYjMSIHDgEHBhUUFx4BFxYzAgBqXV6LKCgoKIteXWpqXV6LKCgoKIteXWpVSktvICEhIG9LSlVVSktvICEhIG9LSlVAKCiLXl1qal1eiygoKCiLXl1qal1eiygoZiEgb0tKVVVKS28gISEgb0tKVVVKS28gIQABAAABwAIAA8AAEgAAEzQ3PgE3NjMxFSIHDgEHBhUxIwAoKIteXWpVSktvICFmAcBqXV6LKChmISBvS0pVAAAAAgAA/8AFtgPAADIAOgAAARYXHgEXFhUUBw4BBwYHIxUhIicuAScmNTQ3PgE3NjMxOAExNDc+ATc2MzIXHgEXFhcVATMJATMVMzUEjD83NlAXFxYXTjU1PQL8kz01Nk8XFxcXTzY1PSIjd1BQWlJJSXInJw3+mdv+2/7c25MCUQYcHFg5OUA/ODlXHBwIAhcXTzY1PTw1Nk8XF1tQUHcjIhwcYUNDTgL+3QFt/pOTkwABAAAAAQAAmM7nP18PPPUACwQAAAAAANciZKUAAAAA1yJkpf/9/70FtgPDAAAACAACAAAAAAAAAAEAAAPA/8AAAAW3//3//QW2AAEAAAAAAAAAAAAAAAAAAAAMBAAAAAAAAAAAAAAAAgAAAAQAASAEAADgBAAAwAQAAJ0EAP/9BAAAAAQAAAAFtwAAAAAAAAAKABQAHgAyAEYAjACiAL4BFgE2AY4AAAABAAAADAA8AAMAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEADQAAAAEAAAAAAAIABwCWAAEAAAAAAAMADQBIAAEAAAAAAAQADQCrAAEAAAAAAAUACwAnAAEAAAAAAAYADQBvAAEAAAAAAAoAGgDSAAMAAQQJAAEAGgANAAMAAQQJAAIADgCdAAMAAQQJAAMAGgBVAAMAAQQJAAQAGgC4AAMAAQQJAAUAFgAyAAMAAQQJAAYAGgB8AAMAAQQJAAoANADsd2ViZmxvdy1pY29ucwB3AGUAYgBmAGwAbwB3AC0AaQBjAG8AbgBzVmVyc2lvbiAxLjAAVgBlAHIAcwBpAG8AbgAgADEALgAwd2ViZmxvdy1pY29ucwB3AGUAYgBmAGwAbwB3AC0AaQBjAG8AbgBzd2ViZmxvdy1pY29ucwB3AGUAYgBmAGwAbwB3AC0AaQBjAG8AbgBzUmVndWxhcgBSAGUAZwB1AGwAYQByd2ViZmxvdy1pY29ucwB3AGUAYgBmAGwAbwB3AC0AaQBjAG8AbgBzRm9udCBnZW5lcmF0ZWQgYnkgSWNvTW9vbi4ARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") format('truetype'); 4 | font-weight: normal; 5 | font-style: normal; 6 | } 7 | [class^="w-icon-"], 8 | [class*=" w-icon-"] { 9 | /* use !important to prevent issues with browser extensions that change fonts */ 10 | font-family: 'webflow-icons' !important; 11 | speak: none; 12 | font-style: normal; 13 | font-weight: normal; 14 | font-variant: normal; 15 | text-transform: none; 16 | line-height: 1; 17 | /* Better Font Rendering =========== */ 18 | -webkit-font-smoothing: antialiased; 19 | -moz-osx-font-smoothing: grayscale; 20 | } 21 | .w-icon-slider-right:before { 22 | content: "\e600"; 23 | } 24 | .w-icon-slider-left:before { 25 | content: "\e601"; 26 | } 27 | .w-icon-nav-menu:before { 28 | content: "\e602"; 29 | } 30 | .w-icon-arrow-down:before, 31 | .w-icon-dropdown-toggle:before { 32 | content: "\e603"; 33 | } 34 | .w-icon-file-upload-remove:before { 35 | content: "\e900"; 36 | } 37 | .w-icon-file-upload-icon:before { 38 | content: "\e903"; 39 | } 40 | * { 41 | -webkit-box-sizing: border-box; 42 | -moz-box-sizing: border-box; 43 | box-sizing: border-box; 44 | } 45 | html { 46 | height: 100%; 47 | } 48 | body { 49 | margin: 0; 50 | min-height: 100%; 51 | background-color: #fff; 52 | font-family: Arial, sans-serif; 53 | font-size: 14px; 54 | line-height: 20px; 55 | color: #333; 56 | } 57 | img { 58 | max-width: 100%; 59 | vertical-align: middle; 60 | display: inline-block; 61 | } 62 | html.w-mod-touch * { 63 | background-attachment: scroll !important; 64 | } 65 | .w-block { 66 | display: block; 67 | } 68 | .w-inline-block { 69 | max-width: 100%; 70 | display: inline-block; 71 | } 72 | .w-clearfix:before, 73 | .w-clearfix:after { 74 | content: " "; 75 | display: table; 76 | grid-column-start: 1; 77 | grid-row-start: 1; 78 | grid-column-end: 2; 79 | grid-row-end: 2; 80 | } 81 | .w-clearfix:after { 82 | clear: both; 83 | } 84 | .w-hidden { 85 | display: none; 86 | } 87 | .w-button { 88 | display: inline-block; 89 | padding: 9px 15px; 90 | background-color: #3898EC; 91 | color: white; 92 | border: 0; 93 | line-height: inherit; 94 | text-decoration: none; 95 | cursor: pointer; 96 | border-radius: 0; 97 | } 98 | input.w-button { 99 | -webkit-appearance: button; 100 | } 101 | html[data-w-dynpage] [data-w-cloak] { 102 | color: transparent !important; 103 | } 104 | .w-webflow-badge, 105 | .w-webflow-badge * { 106 | position: static; 107 | left: auto; 108 | top: auto; 109 | right: auto; 110 | bottom: auto; 111 | z-index: auto; 112 | display: block; 113 | visibility: visible; 114 | overflow: visible; 115 | overflow-x: visible; 116 | overflow-y: visible; 117 | box-sizing: border-box; 118 | width: auto; 119 | height: auto; 120 | max-height: none; 121 | max-width: none; 122 | min-height: 0; 123 | min-width: 0; 124 | margin: 0; 125 | padding: 0; 126 | float: none; 127 | clear: none; 128 | border: 0 none transparent; 129 | border-radius: 0; 130 | background: none; 131 | background-image: none; 132 | background-position: 0% 0%; 133 | background-size: auto auto; 134 | background-repeat: repeat; 135 | background-origin: padding-box; 136 | background-clip: border-box; 137 | background-attachment: scroll; 138 | background-color: transparent; 139 | box-shadow: none; 140 | opacity: 1.0; 141 | transform: none; 142 | transition: none; 143 | direction: ltr; 144 | font-family: inherit; 145 | font-weight: inherit; 146 | color: inherit; 147 | font-size: inherit; 148 | line-height: inherit; 149 | font-style: inherit; 150 | font-variant: inherit; 151 | text-align: inherit; 152 | letter-spacing: inherit; 153 | text-decoration: inherit; 154 | text-indent: 0; 155 | text-transform: inherit; 156 | list-style-type: disc; 157 | text-shadow: none; 158 | font-smoothing: auto; 159 | vertical-align: baseline; 160 | cursor: inherit; 161 | white-space: inherit; 162 | word-break: normal; 163 | word-spacing: normal; 164 | word-wrap: normal; 165 | } 166 | .w-webflow-badge { 167 | position: fixed !important; 168 | display: inline-block !important; 169 | visibility: visible !important; 170 | opacity: 1 !important; 171 | z-index: 2147483647 !important; 172 | top: auto !important; 173 | right: 12px !important; 174 | bottom: 12px !important; 175 | left: auto !important; 176 | color: #AAADB0 !important; 177 | background-color: #fff !important; 178 | border-radius: 3px !important; 179 | padding: 6px 8px 6px 6px !important; 180 | font-size: 12px !important; 181 | opacity: 1.0 !important; 182 | line-height: 14px !important; 183 | text-decoration: none !important; 184 | transform: none !important; 185 | margin: 0 !important; 186 | width: auto !important; 187 | height: auto !important; 188 | overflow: visible !important; 189 | white-space: nowrap; 190 | box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0px 1px 3px rgba(0, 0, 0, 0.1); 191 | cursor: pointer; 192 | } 193 | .w-webflow-badge > img { 194 | display: inline-block !important; 195 | visibility: visible !important; 196 | opacity: 1 !important; 197 | vertical-align: middle !important; 198 | } 199 | h1, 200 | h2, 201 | h3, 202 | h4, 203 | h5, 204 | h6 { 205 | font-weight: bold; 206 | margin-bottom: 10px; 207 | } 208 | h1 { 209 | font-size: 38px; 210 | line-height: 44px; 211 | margin-top: 20px; 212 | } 213 | h2 { 214 | font-size: 32px; 215 | line-height: 36px; 216 | margin-top: 20px; 217 | } 218 | h3 { 219 | font-size: 24px; 220 | line-height: 30px; 221 | margin-top: 20px; 222 | } 223 | h4 { 224 | font-size: 18px; 225 | line-height: 24px; 226 | margin-top: 10px; 227 | } 228 | h5 { 229 | font-size: 14px; 230 | line-height: 20px; 231 | margin-top: 10px; 232 | } 233 | h6 { 234 | font-size: 12px; 235 | line-height: 18px; 236 | margin-top: 10px; 237 | } 238 | p { 239 | margin-top: 0; 240 | margin-bottom: 10px; 241 | } 242 | blockquote { 243 | margin: 0 0 10px 0; 244 | padding: 10px 20px; 245 | border-left: 5px solid #E2E2E2; 246 | font-size: 18px; 247 | line-height: 22px; 248 | } 249 | figure { 250 | margin: 0; 251 | margin-bottom: 10px; 252 | } 253 | figcaption { 254 | margin-top: 5px; 255 | text-align: center; 256 | } 257 | ul, 258 | ol { 259 | margin-top: 0px; 260 | margin-bottom: 10px; 261 | padding-left: 40px; 262 | } 263 | .w-list-unstyled { 264 | padding-left: 0; 265 | list-style: none; 266 | } 267 | .w-embed:before, 268 | .w-embed:after { 269 | content: " "; 270 | display: table; 271 | grid-column-start: 1; 272 | grid-row-start: 1; 273 | grid-column-end: 2; 274 | grid-row-end: 2; 275 | } 276 | .w-embed:after { 277 | clear: both; 278 | } 279 | .w-video { 280 | width: 100%; 281 | position: relative; 282 | padding: 0; 283 | } 284 | .w-video iframe, 285 | .w-video object, 286 | .w-video embed { 287 | position: absolute; 288 | top: 0; 289 | left: 0; 290 | width: 100%; 291 | height: 100%; 292 | } 293 | fieldset { 294 | padding: 0; 295 | margin: 0; 296 | border: 0; 297 | } 298 | button, 299 | html input[type="button"], 300 | input[type="reset"] { 301 | border: 0; 302 | cursor: pointer; 303 | -webkit-appearance: button; 304 | } 305 | .w-form { 306 | margin: 0 0 15px; 307 | } 308 | .w-form-done { 309 | display: none; 310 | padding: 20px; 311 | text-align: center; 312 | background-color: #dddddd; 313 | } 314 | .w-form-fail { 315 | display: none; 316 | margin-top: 10px; 317 | padding: 10px; 318 | background-color: #ffdede; 319 | } 320 | label { 321 | display: block; 322 | margin-bottom: 5px; 323 | font-weight: bold; 324 | } 325 | .w-input, 326 | .w-select { 327 | display: block; 328 | width: 100%; 329 | height: 38px; 330 | padding: 8px 12px; 331 | margin-bottom: 10px; 332 | font-size: 14px; 333 | line-height: 1.428571429; 334 | color: #333333; 335 | vertical-align: middle; 336 | background-color: #ffffff; 337 | border: 1px solid #cccccc; 338 | } 339 | .w-input:-moz-placeholder, 340 | .w-select:-moz-placeholder { 341 | color: #999; 342 | } 343 | .w-input::-moz-placeholder, 344 | .w-select::-moz-placeholder { 345 | color: #999; 346 | opacity: 1; 347 | } 348 | .w-input:-ms-input-placeholder, 349 | .w-select:-ms-input-placeholder { 350 | color: #999; 351 | } 352 | .w-input::-webkit-input-placeholder, 353 | .w-select::-webkit-input-placeholder { 354 | color: #999; 355 | } 356 | .w-input:focus, 357 | .w-select:focus { 358 | border-color: #3898EC; 359 | outline: 0; 360 | } 361 | .w-input[disabled], 362 | .w-select[disabled], 363 | .w-input[readonly], 364 | .w-select[readonly], 365 | fieldset[disabled] .w-input, 366 | fieldset[disabled] .w-select { 367 | cursor: not-allowed; 368 | background-color: #eeeeee; 369 | } 370 | textarea.w-input, 371 | textarea.w-select { 372 | height: auto; 373 | } 374 | .w-select { 375 | background-color: #f3f3f3; 376 | } 377 | .w-select[multiple] { 378 | height: auto; 379 | } 380 | .w-form-label { 381 | display: inline-block; 382 | cursor: pointer; 383 | font-weight: normal; 384 | margin-bottom: 0px; 385 | } 386 | .w-radio { 387 | display: block; 388 | margin-bottom: 5px; 389 | padding-left: 20px; 390 | } 391 | .w-radio:before, 392 | .w-radio:after { 393 | content: " "; 394 | display: table; 395 | grid-column-start: 1; 396 | grid-row-start: 1; 397 | grid-column-end: 2; 398 | grid-row-end: 2; 399 | } 400 | .w-radio:after { 401 | clear: both; 402 | } 403 | .w-radio-input { 404 | margin: 4px 0 0; 405 | margin-top: 1px \9; 406 | line-height: normal; 407 | float: left; 408 | margin-left: -20px; 409 | } 410 | .w-radio-input { 411 | margin-top: 3px; 412 | } 413 | .w-file-upload { 414 | display: block; 415 | margin-bottom: 10px; 416 | } 417 | .w-file-upload-input { 418 | width: 0.1px; 419 | height: 0.1px; 420 | opacity: 0; 421 | overflow: hidden; 422 | position: absolute; 423 | z-index: -100; 424 | } 425 | .w-file-upload-default, 426 | .w-file-upload-uploading, 427 | .w-file-upload-success { 428 | display: inline-block; 429 | color: #333333; 430 | } 431 | .w-file-upload-error { 432 | display: block; 433 | margin-top: 10px; 434 | } 435 | .w-file-upload-default.w-hidden, 436 | .w-file-upload-uploading.w-hidden, 437 | .w-file-upload-error.w-hidden, 438 | .w-file-upload-success.w-hidden { 439 | display: none; 440 | } 441 | .w-file-upload-uploading-btn { 442 | display: flex; 443 | font-size: 14px; 444 | font-weight: normal; 445 | cursor: pointer; 446 | margin: 0; 447 | padding: 8px 12px; 448 | border: 1px solid #cccccc; 449 | background-color: #fafafa; 450 | } 451 | .w-file-upload-file { 452 | display: flex; 453 | flex-grow: 1; 454 | justify-content: space-between; 455 | margin: 0; 456 | padding: 8px 9px 8px 11px; 457 | border: 1px solid #cccccc; 458 | background-color: #fafafa; 459 | } 460 | .w-file-upload-file-name { 461 | font-size: 14px; 462 | font-weight: normal; 463 | display: block; 464 | } 465 | .w-file-remove-link { 466 | margin-top: 3px; 467 | margin-left: 10px; 468 | width: auto; 469 | height: auto; 470 | padding: 3px; 471 | display: block; 472 | cursor: pointer; 473 | } 474 | .w-icon-file-upload-remove { 475 | margin: auto; 476 | font-size: 10px; 477 | } 478 | .w-file-upload-error-msg { 479 | display: inline-block; 480 | color: #ea384c; 481 | padding: 2px 0; 482 | } 483 | .w-file-upload-info { 484 | display: inline-block; 485 | line-height: 38px; 486 | padding: 0 12px; 487 | } 488 | .w-file-upload-label { 489 | display: inline-block; 490 | font-size: 14px; 491 | font-weight: normal; 492 | cursor: pointer; 493 | margin: 0; 494 | padding: 8px 12px; 495 | border: 1px solid #cccccc; 496 | background-color: #fafafa; 497 | } 498 | .w-icon-file-upload-icon, 499 | .w-icon-file-upload-uploading { 500 | display: inline-block; 501 | margin-right: 8px; 502 | width: 20px; 503 | } 504 | .w-icon-file-upload-uploading { 505 | height: 20px; 506 | } 507 | .w-container { 508 | margin-left: auto; 509 | margin-right: auto; 510 | max-width: 940px; 511 | } 512 | .w-container:before, 513 | .w-container:after { 514 | content: " "; 515 | display: table; 516 | grid-column-start: 1; 517 | grid-row-start: 1; 518 | grid-column-end: 2; 519 | grid-row-end: 2; 520 | } 521 | .w-container:after { 522 | clear: both; 523 | } 524 | .w-container .w-row { 525 | margin-left: -10px; 526 | margin-right: -10px; 527 | } 528 | .w-row:before, 529 | .w-row:after { 530 | content: " "; 531 | display: table; 532 | grid-column-start: 1; 533 | grid-row-start: 1; 534 | grid-column-end: 2; 535 | grid-row-end: 2; 536 | } 537 | .w-row:after { 538 | clear: both; 539 | } 540 | .w-row .w-row { 541 | margin-left: 0; 542 | margin-right: 0; 543 | } 544 | .w-col { 545 | position: relative; 546 | float: left; 547 | width: 100%; 548 | min-height: 1px; 549 | padding-left: 10px; 550 | padding-right: 10px; 551 | } 552 | .w-col .w-col { 553 | padding-left: 0; 554 | padding-right: 0; 555 | } 556 | .w-col-1 { 557 | width: 8.33333333%; 558 | } 559 | .w-col-2 { 560 | width: 16.66666667%; 561 | } 562 | .w-col-3 { 563 | width: 25%; 564 | } 565 | .w-col-4 { 566 | width: 33.33333333%; 567 | } 568 | .w-col-5 { 569 | width: 41.66666667%; 570 | } 571 | .w-col-6 { 572 | width: 50%; 573 | } 574 | .w-col-7 { 575 | width: 58.33333333%; 576 | } 577 | .w-col-8 { 578 | width: 66.66666667%; 579 | } 580 | .w-col-9 { 581 | width: 75%; 582 | } 583 | .w-col-10 { 584 | width: 83.33333333%; 585 | } 586 | .w-col-11 { 587 | width: 91.66666667%; 588 | } 589 | .w-col-12 { 590 | width: 100%; 591 | } 592 | .w-hidden-main { 593 | display: none !important; 594 | } 595 | @media screen and (max-width: 991px) { 596 | .w-container { 597 | max-width: 728px; 598 | } 599 | .w-hidden-main { 600 | display: inherit !important; 601 | } 602 | .w-hidden-medium { 603 | display: none !important; 604 | } 605 | .w-col-medium-1 { 606 | width: 8.33333333%; 607 | } 608 | .w-col-medium-2 { 609 | width: 16.66666667%; 610 | } 611 | .w-col-medium-3 { 612 | width: 25%; 613 | } 614 | .w-col-medium-4 { 615 | width: 33.33333333%; 616 | } 617 | .w-col-medium-5 { 618 | width: 41.66666667%; 619 | } 620 | .w-col-medium-6 { 621 | width: 50%; 622 | } 623 | .w-col-medium-7 { 624 | width: 58.33333333%; 625 | } 626 | .w-col-medium-8 { 627 | width: 66.66666667%; 628 | } 629 | .w-col-medium-9 { 630 | width: 75%; 631 | } 632 | .w-col-medium-10 { 633 | width: 83.33333333%; 634 | } 635 | .w-col-medium-11 { 636 | width: 91.66666667%; 637 | } 638 | .w-col-medium-12 { 639 | width: 100%; 640 | } 641 | .w-col-stack { 642 | width: 100%; 643 | left: auto; 644 | right: auto; 645 | } 646 | } 647 | @media screen and (max-width: 767px) { 648 | .w-hidden-main { 649 | display: inherit !important; 650 | } 651 | .w-hidden-medium { 652 | display: inherit !important; 653 | } 654 | .w-hidden-small { 655 | display: none !important; 656 | } 657 | .w-row, 658 | .w-container .w-row { 659 | margin-left: 0; 660 | margin-right: 0; 661 | } 662 | .w-col { 663 | width: 100%; 664 | left: auto; 665 | right: auto; 666 | } 667 | .w-col-small-1 { 668 | width: 8.33333333%; 669 | } 670 | .w-col-small-2 { 671 | width: 16.66666667%; 672 | } 673 | .w-col-small-3 { 674 | width: 25%; 675 | } 676 | .w-col-small-4 { 677 | width: 33.33333333%; 678 | } 679 | .w-col-small-5 { 680 | width: 41.66666667%; 681 | } 682 | .w-col-small-6 { 683 | width: 50%; 684 | } 685 | .w-col-small-7 { 686 | width: 58.33333333%; 687 | } 688 | .w-col-small-8 { 689 | width: 66.66666667%; 690 | } 691 | .w-col-small-9 { 692 | width: 75%; 693 | } 694 | .w-col-small-10 { 695 | width: 83.33333333%; 696 | } 697 | .w-col-small-11 { 698 | width: 91.66666667%; 699 | } 700 | .w-col-small-12 { 701 | width: 100%; 702 | } 703 | } 704 | @media screen and (max-width: 479px) { 705 | .w-container { 706 | max-width: none; 707 | } 708 | .w-hidden-main { 709 | display: inherit !important; 710 | } 711 | .w-hidden-medium { 712 | display: inherit !important; 713 | } 714 | .w-hidden-small { 715 | display: inherit !important; 716 | } 717 | .w-hidden-tiny { 718 | display: none !important; 719 | } 720 | .w-col { 721 | width: 100%; 722 | } 723 | .w-col-tiny-1 { 724 | width: 8.33333333%; 725 | } 726 | .w-col-tiny-2 { 727 | width: 16.66666667%; 728 | } 729 | .w-col-tiny-3 { 730 | width: 25%; 731 | } 732 | .w-col-tiny-4 { 733 | width: 33.33333333%; 734 | } 735 | .w-col-tiny-5 { 736 | width: 41.66666667%; 737 | } 738 | .w-col-tiny-6 { 739 | width: 50%; 740 | } 741 | .w-col-tiny-7 { 742 | width: 58.33333333%; 743 | } 744 | .w-col-tiny-8 { 745 | width: 66.66666667%; 746 | } 747 | .w-col-tiny-9 { 748 | width: 75%; 749 | } 750 | .w-col-tiny-10 { 751 | width: 83.33333333%; 752 | } 753 | .w-col-tiny-11 { 754 | width: 91.66666667%; 755 | } 756 | .w-col-tiny-12 { 757 | width: 100%; 758 | } 759 | } 760 | .w-widget { 761 | position: relative; 762 | } 763 | .w-widget-map { 764 | width: 100%; 765 | height: 400px; 766 | } 767 | .w-widget-map label { 768 | width: auto; 769 | display: inline; 770 | } 771 | .w-widget-map img { 772 | max-width: inherit; 773 | } 774 | .w-widget-map .gm-style-iw { 775 | text-align: center; 776 | } 777 | .w-widget-map .gm-style-iw > button { 778 | display: none !important; 779 | } 780 | .w-widget-twitter { 781 | overflow: hidden; 782 | } 783 | .w-widget-twitter-count-shim { 784 | display: inline-block; 785 | vertical-align: top; 786 | position: relative; 787 | width: 28px; 788 | height: 20px; 789 | text-align: center; 790 | background: white; 791 | border: #758696 solid 1px; 792 | border-radius: 3px; 793 | } 794 | .w-widget-twitter-count-shim * { 795 | pointer-events: none; 796 | -webkit-user-select: none; 797 | -moz-user-select: none; 798 | -ms-user-select: none; 799 | user-select: none; 800 | } 801 | .w-widget-twitter-count-shim .w-widget-twitter-count-inner { 802 | position: relative; 803 | font-size: 15px; 804 | line-height: 12px; 805 | text-align: center; 806 | color: #999; 807 | font-family: serif; 808 | } 809 | .w-widget-twitter-count-shim .w-widget-twitter-count-clear { 810 | position: relative; 811 | display: block; 812 | } 813 | .w-widget-twitter-count-shim.w--large { 814 | width: 36px; 815 | height: 28px; 816 | } 817 | .w-widget-twitter-count-shim.w--large .w-widget-twitter-count-inner { 818 | font-size: 18px; 819 | line-height: 18px; 820 | } 821 | .w-widget-twitter-count-shim:not(.w--vertical) { 822 | margin-left: 5px; 823 | margin-right: 8px; 824 | } 825 | .w-widget-twitter-count-shim:not(.w--vertical).w--large { 826 | margin-left: 6px; 827 | } 828 | .w-widget-twitter-count-shim:not(.w--vertical):before, 829 | .w-widget-twitter-count-shim:not(.w--vertical):after { 830 | top: 50%; 831 | left: 0; 832 | border: solid transparent; 833 | content: " "; 834 | height: 0; 835 | width: 0; 836 | position: absolute; 837 | pointer-events: none; 838 | } 839 | .w-widget-twitter-count-shim:not(.w--vertical):before { 840 | border-color: rgba(117, 134, 150, 0); 841 | border-right-color: #5d6c7b; 842 | border-width: 4px; 843 | margin-left: -9px; 844 | margin-top: -4px; 845 | } 846 | .w-widget-twitter-count-shim:not(.w--vertical).w--large:before { 847 | border-width: 5px; 848 | margin-left: -10px; 849 | margin-top: -5px; 850 | } 851 | .w-widget-twitter-count-shim:not(.w--vertical):after { 852 | border-color: rgba(255, 255, 255, 0); 853 | border-right-color: white; 854 | border-width: 4px; 855 | margin-left: -8px; 856 | margin-top: -4px; 857 | } 858 | .w-widget-twitter-count-shim:not(.w--vertical).w--large:after { 859 | border-width: 5px; 860 | margin-left: -9px; 861 | margin-top: -5px; 862 | } 863 | .w-widget-twitter-count-shim.w--vertical { 864 | width: 61px; 865 | height: 33px; 866 | margin-bottom: 8px; 867 | } 868 | .w-widget-twitter-count-shim.w--vertical:before, 869 | .w-widget-twitter-count-shim.w--vertical:after { 870 | top: 100%; 871 | left: 50%; 872 | border: solid transparent; 873 | content: " "; 874 | height: 0; 875 | width: 0; 876 | position: absolute; 877 | pointer-events: none; 878 | } 879 | .w-widget-twitter-count-shim.w--vertical:before { 880 | border-color: rgba(117, 134, 150, 0); 881 | border-top-color: #5d6c7b; 882 | border-width: 5px; 883 | margin-left: -5px; 884 | } 885 | .w-widget-twitter-count-shim.w--vertical:after { 886 | border-color: rgba(255, 255, 255, 0); 887 | border-top-color: white; 888 | border-width: 4px; 889 | margin-left: -4px; 890 | } 891 | .w-widget-twitter-count-shim.w--vertical .w-widget-twitter-count-inner { 892 | font-size: 18px; 893 | line-height: 22px; 894 | } 895 | .w-widget-twitter-count-shim.w--vertical.w--large { 896 | width: 76px; 897 | } 898 | .w-widget-gplus { 899 | overflow: hidden; 900 | } 901 | .w-background-video { 902 | position: relative; 903 | overflow: hidden; 904 | height: 500px; 905 | color: white; 906 | } 907 | .w-background-video > video { 908 | background-size: cover; 909 | background-position: 50% 50%; 910 | position: absolute; 911 | margin: auto; 912 | width: 100%; 913 | height: 100%; 914 | right: -100%; 915 | bottom: -100%; 916 | top: -100%; 917 | left: -100%; 918 | object-fit: cover; 919 | z-index: -100; 920 | } 921 | .w-background-video > video::-webkit-media-controls-start-playback-button { 922 | display: none !important; 923 | -webkit-appearance: none; 924 | } 925 | .w-slider { 926 | position: relative; 927 | height: 300px; 928 | text-align: center; 929 | background: #dddddd; 930 | clear: both; 931 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 932 | tap-highlight-color: rgba(0, 0, 0, 0); 933 | } 934 | .w-slider-mask { 935 | position: relative; 936 | display: block; 937 | overflow: hidden; 938 | z-index: 1; 939 | left: 0; 940 | right: 0; 941 | height: 100%; 942 | white-space: nowrap; 943 | } 944 | .w-slide { 945 | position: relative; 946 | display: inline-block; 947 | vertical-align: top; 948 | width: 100%; 949 | height: 100%; 950 | white-space: normal; 951 | text-align: left; 952 | } 953 | .w-slider-nav { 954 | position: absolute; 955 | z-index: 2; 956 | top: auto; 957 | right: 0; 958 | bottom: 0; 959 | left: 0; 960 | margin: auto; 961 | padding-top: 10px; 962 | height: 40px; 963 | text-align: center; 964 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 965 | tap-highlight-color: rgba(0, 0, 0, 0); 966 | } 967 | .w-slider-nav.w-round > div { 968 | border-radius: 100%; 969 | } 970 | .w-slider-nav.w-num > div { 971 | width: auto; 972 | height: auto; 973 | padding: 0.2em 0.5em; 974 | font-size: inherit; 975 | line-height: inherit; 976 | } 977 | .w-slider-nav.w-shadow > div { 978 | box-shadow: 0 0 3px rgba(51, 51, 51, 0.4); 979 | } 980 | .w-slider-nav-invert { 981 | color: #fff; 982 | } 983 | .w-slider-nav-invert > div { 984 | background-color: rgba(34, 34, 34, 0.4); 985 | } 986 | .w-slider-nav-invert > div.w-active { 987 | background-color: #222; 988 | } 989 | .w-slider-dot { 990 | position: relative; 991 | display: inline-block; 992 | width: 1em; 993 | height: 1em; 994 | background-color: rgba(255, 255, 255, 0.4); 995 | cursor: pointer; 996 | margin: 0 3px 0.5em; 997 | transition: background-color 100ms, color 100ms; 998 | } 999 | .w-slider-dot.w-active { 1000 | background-color: #fff; 1001 | } 1002 | .w-slider-arrow-left, 1003 | .w-slider-arrow-right { 1004 | position: absolute; 1005 | width: 80px; 1006 | top: 0; 1007 | right: 0; 1008 | bottom: 0; 1009 | left: 0; 1010 | margin: auto; 1011 | cursor: pointer; 1012 | overflow: hidden; 1013 | color: white; 1014 | font-size: 40px; 1015 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 1016 | tap-highlight-color: rgba(0, 0, 0, 0); 1017 | -webkit-user-select: none; 1018 | -moz-user-select: none; 1019 | -ms-user-select: none; 1020 | user-select: none; 1021 | } 1022 | .w-slider-arrow-left [class^="w-icon-"], 1023 | .w-slider-arrow-right [class^="w-icon-"], 1024 | .w-slider-arrow-left [class*=" w-icon-"], 1025 | .w-slider-arrow-right [class*=" w-icon-"] { 1026 | position: absolute; 1027 | } 1028 | .w-slider-arrow-left { 1029 | z-index: 3; 1030 | right: auto; 1031 | } 1032 | .w-slider-arrow-right { 1033 | z-index: 4; 1034 | left: auto; 1035 | } 1036 | .w-icon-slider-left, 1037 | .w-icon-slider-right { 1038 | top: 0; 1039 | right: 0; 1040 | bottom: 0; 1041 | left: 0; 1042 | margin: auto; 1043 | width: 1em; 1044 | height: 1em; 1045 | } 1046 | .w-dropdown { 1047 | display: inline-block; 1048 | position: relative; 1049 | text-align: left; 1050 | margin-left: auto; 1051 | margin-right: auto; 1052 | z-index: 900; 1053 | } 1054 | .w-dropdown-btn, 1055 | .w-dropdown-toggle, 1056 | .w-dropdown-link { 1057 | position: relative; 1058 | vertical-align: top; 1059 | text-decoration: none; 1060 | color: #222222; 1061 | padding: 20px; 1062 | text-align: left; 1063 | margin-left: auto; 1064 | margin-right: auto; 1065 | white-space: nowrap; 1066 | } 1067 | .w-dropdown-toggle { 1068 | -webkit-user-select: none; 1069 | -moz-user-select: none; 1070 | -ms-user-select: none; 1071 | user-select: none; 1072 | display: inline-block; 1073 | cursor: pointer; 1074 | padding-right: 40px; 1075 | } 1076 | .w-icon-dropdown-toggle { 1077 | position: absolute; 1078 | top: 0; 1079 | right: 0; 1080 | bottom: 0; 1081 | margin: auto; 1082 | margin-right: 20px; 1083 | width: 1em; 1084 | height: 1em; 1085 | } 1086 | .w-dropdown-list { 1087 | position: absolute; 1088 | background: #dddddd; 1089 | display: none; 1090 | min-width: 100%; 1091 | } 1092 | .w-dropdown-list.w--open { 1093 | display: block; 1094 | } 1095 | .w-dropdown-link { 1096 | padding: 10px 20px; 1097 | display: block; 1098 | color: #222222; 1099 | } 1100 | .w-dropdown-link.w--current { 1101 | color: #0082f3; 1102 | } 1103 | @media screen and (max-width: 767px) { 1104 | .w-nav-brand { 1105 | padding-left: 10px; 1106 | } 1107 | } 1108 | /** 1109 | * ## Note 1110 | * Safari (on both iOS and OS X) does not handle viewport units (vh, vw) well. 1111 | * For example percentage units do not work on descendants of elements that 1112 | * have any dimensions expressed in viewport units. It also doesn’t handle them at 1113 | * all in `calc()`. 1114 | */ 1115 | /** 1116 | * Wrapper around all lightbox elements 1117 | * 1118 | * 1. Since the lightbox can receive focus, IE also gives it an outline. 1119 | * 2. Fixes flickering on Chrome when a transition is in progress 1120 | * underneath the lightbox. 1121 | */ 1122 | .w-lightbox-backdrop { 1123 | color: #000; 1124 | cursor: auto; 1125 | font-family: serif; 1126 | font-size: medium; 1127 | font-style: normal; 1128 | font-variant: normal; 1129 | font-weight: normal; 1130 | letter-spacing: normal; 1131 | line-height: normal; 1132 | list-style: disc; 1133 | text-align: start; 1134 | text-indent: 0; 1135 | text-shadow: none; 1136 | text-transform: none; 1137 | visibility: visible; 1138 | white-space: normal; 1139 | word-break: normal; 1140 | word-spacing: normal; 1141 | word-wrap: normal; 1142 | position: fixed; 1143 | top: 0; 1144 | right: 0; 1145 | bottom: 0; 1146 | left: 0; 1147 | color: #fff; 1148 | font-family: "Helvetica Neue", Helvetica, Ubuntu, "Segoe UI", Verdana, sans-serif; 1149 | font-size: 17px; 1150 | line-height: 1.2; 1151 | font-weight: 300; 1152 | text-align: center; 1153 | background: rgba(0, 0, 0, 0.9); 1154 | z-index: 2000; 1155 | outline: 0; 1156 | /* 1 */ 1157 | opacity: 0; 1158 | -webkit-user-select: none; 1159 | -moz-user-select: none; 1160 | -ms-user-select: none; 1161 | -webkit-tap-highlight-color: transparent; 1162 | -webkit-transform: translate(0, 0); 1163 | /* 2 */ 1164 | } 1165 | /** 1166 | * Neat trick to bind the rubberband effect to our canvas instead of the whole 1167 | * document on iOS. It also prevents a bug that causes the document underneath to scroll. 1168 | */ 1169 | .w-lightbox-backdrop, 1170 | .w-lightbox-container { 1171 | height: 100%; 1172 | overflow: auto; 1173 | -webkit-overflow-scrolling: touch; 1174 | } 1175 | .w-lightbox-content { 1176 | position: relative; 1177 | height: 100vh; 1178 | overflow: hidden; 1179 | } 1180 | .w-lightbox-view { 1181 | position: absolute; 1182 | width: 100vw; 1183 | height: 100vh; 1184 | opacity: 0; 1185 | } 1186 | .w-lightbox-view:before { 1187 | content: ""; 1188 | height: 100vh; 1189 | } 1190 | /* .w-lightbox-content */ 1191 | .w-lightbox-group, 1192 | .w-lightbox-group .w-lightbox-view, 1193 | .w-lightbox-group .w-lightbox-view:before { 1194 | height: 86vh; 1195 | } 1196 | .w-lightbox-frame, 1197 | .w-lightbox-view:before { 1198 | display: inline-block; 1199 | vertical-align: middle; 1200 | } 1201 | /* 1202 | * 1. Remove default margin set by user-agent on the
element. 1203 | */ 1204 | .w-lightbox-figure { 1205 | position: relative; 1206 | margin: 0; 1207 | /* 1 */ 1208 | } 1209 | .w-lightbox-group .w-lightbox-figure { 1210 | cursor: pointer; 1211 | } 1212 | /** 1213 | * IE adds image dimensions as width and height attributes on the IMG tag, 1214 | * but we need both width and height to be set to auto to enable scaling. 1215 | */ 1216 | .w-lightbox-img { 1217 | width: auto; 1218 | height: auto; 1219 | max-width: none; 1220 | } 1221 | /** 1222 | * 1. Reset if style is set by user on "All Images" 1223 | */ 1224 | .w-lightbox-image { 1225 | display: block; 1226 | float: none; 1227 | /* 1 */ 1228 | max-width: 100vw; 1229 | max-height: 100vh; 1230 | } 1231 | .w-lightbox-group .w-lightbox-image { 1232 | max-height: 86vh; 1233 | } 1234 | .w-lightbox-caption { 1235 | position: absolute; 1236 | right: 0; 1237 | bottom: 0; 1238 | left: 0; 1239 | padding: .5em 1em; 1240 | background: rgba(0, 0, 0, 0.4); 1241 | text-align: left; 1242 | text-overflow: ellipsis; 1243 | white-space: nowrap; 1244 | overflow: hidden; 1245 | } 1246 | .w-lightbox-embed { 1247 | position: absolute; 1248 | top: 0; 1249 | right: 0; 1250 | bottom: 0; 1251 | left: 0; 1252 | width: 100%; 1253 | height: 100%; 1254 | } 1255 | .w-lightbox-control { 1256 | position: absolute; 1257 | top: 0; 1258 | width: 4em; 1259 | background-size: 24px; 1260 | background-repeat: no-repeat; 1261 | background-position: center; 1262 | cursor: pointer; 1263 | -webkit-transition: all .3s; 1264 | transition: all .3s; 1265 | } 1266 | .w-lightbox-left { 1267 | display: none; 1268 | bottom: 0; 1269 | left: 0; 1270 | /* */ 1271 | background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0yMCAwIDI0IDQwIiB3aWR0aD0iMjQiIGhlaWdodD0iNDAiPjxnIHRyYW5zZm9ybT0icm90YXRlKDQ1KSI+PHBhdGggZD0ibTAgMGg1djIzaDIzdjVoLTI4eiIgb3BhY2l0eT0iLjQiLz48cGF0aCBkPSJtMSAxaDN2MjNoMjN2M2gtMjZ6IiBmaWxsPSIjZmZmIi8+PC9nPjwvc3ZnPg=="); 1272 | } 1273 | .w-lightbox-right { 1274 | display: none; 1275 | right: 0; 1276 | bottom: 0; 1277 | /* */ 1278 | background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii00IDAgMjQgNDAiIHdpZHRoPSIyNCIgaGVpZ2h0PSI0MCI+PGcgdHJhbnNmb3JtPSJyb3RhdGUoNDUpIj48cGF0aCBkPSJtMC0waDI4djI4aC01di0yM2gtMjN6IiBvcGFjaXR5PSIuNCIvPjxwYXRoIGQ9Im0xIDFoMjZ2MjZoLTN2LTIzaC0yM3oiIGZpbGw9IiNmZmYiLz48L2c+PC9zdmc+"); 1279 | } 1280 | /* 1281 | * Without specifying the with and height inside the SVG, all versions of IE render the icon too small. 1282 | * The bug does not seem to manifest itself if the elements are tall enough such as the above arrows. 1283 | * (http://stackoverflow.com/questions/16092114/background-size-differs-in-internet-explorer) 1284 | */ 1285 | .w-lightbox-close { 1286 | right: 0; 1287 | height: 2.6em; 1288 | /* */ 1289 | background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii00IDAgMTggMTciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxNyI+PGcgdHJhbnNmb3JtPSJyb3RhdGUoNDUpIj48cGF0aCBkPSJtMCAwaDd2LTdoNXY3aDd2NWgtN3Y3aC01di03aC03eiIgb3BhY2l0eT0iLjQiLz48cGF0aCBkPSJtMSAxaDd2LTdoM3Y3aDd2M2gtN3Y3aC0zdi03aC03eiIgZmlsbD0iI2ZmZiIvPjwvZz48L3N2Zz4="); 1290 | background-size: 18px; 1291 | } 1292 | /** 1293 | * 1. All IE versions add extra space at the bottom without this. 1294 | */ 1295 | .w-lightbox-strip { 1296 | position: absolute; 1297 | bottom: 0; 1298 | left: 0; 1299 | right: 0; 1300 | padding: 0 1vh; 1301 | line-height: 0; 1302 | /* 1 */ 1303 | white-space: nowrap; 1304 | overflow-x: auto; 1305 | overflow-y: hidden; 1306 | } 1307 | /* 1308 | * 1. We use content-box to avoid having to do `width: calc(10vh + 2vw)` 1309 | * which doesn’t work in Safari anyway. 1310 | * 2. Chrome renders images pixelated when switching to GPU. Making sure 1311 | * the parent is also rendered on the GPU (by setting translate3d for 1312 | * example) fixes this behavior. 1313 | */ 1314 | .w-lightbox-item { 1315 | display: inline-block; 1316 | width: 10vh; 1317 | padding: 2vh 1vh; 1318 | box-sizing: content-box; 1319 | /* 1 */ 1320 | cursor: pointer; 1321 | -webkit-transform: translate3d(0, 0, 0); 1322 | /* 2 */ 1323 | } 1324 | .w-lightbox-active { 1325 | opacity: .3; 1326 | } 1327 | .w-lightbox-thumbnail { 1328 | position: relative; 1329 | height: 10vh; 1330 | background: #222; 1331 | overflow: hidden; 1332 | } 1333 | .w-lightbox-thumbnail-image { 1334 | position: absolute; 1335 | top: 0; 1336 | left: 0; 1337 | } 1338 | .w-lightbox-thumbnail .w-lightbox-tall { 1339 | top: 50%; 1340 | width: 100%; 1341 | -webkit-transform: translate(0, -50%); 1342 | -ms-transform: translate(0, -50%); 1343 | transform: translate(0, -50%); 1344 | } 1345 | .w-lightbox-thumbnail .w-lightbox-wide { 1346 | left: 50%; 1347 | height: 100%; 1348 | -webkit-transform: translate(-50%, 0); 1349 | -ms-transform: translate(-50%, 0); 1350 | transform: translate(-50%, 0); 1351 | } 1352 | /* 1353 | * Spinner 1354 | * 1355 | * Absolute pixel values are used to avoid rounding errors that would cause 1356 | * the white spinning element to be misaligned with the track. 1357 | */ 1358 | .w-lightbox-spinner { 1359 | position: absolute; 1360 | top: 50%; 1361 | left: 50%; 1362 | box-sizing: border-box; 1363 | width: 40px; 1364 | height: 40px; 1365 | margin-top: -20px; 1366 | margin-left: -20px; 1367 | border: 5px solid rgba(0, 0, 0, 0.4); 1368 | border-radius: 50%; 1369 | -webkit-animation: spin .8s infinite linear; 1370 | animation: spin .8s infinite linear; 1371 | } 1372 | .w-lightbox-spinner:after { 1373 | content: ""; 1374 | position: absolute; 1375 | top: -4px; 1376 | right: -4px; 1377 | bottom: -4px; 1378 | left: -4px; 1379 | border: 3px solid transparent; 1380 | border-bottom-color: #fff; 1381 | border-radius: 50%; 1382 | } 1383 | /* 1384 | * Utility classes 1385 | */ 1386 | .w-lightbox-hide { 1387 | display: none; 1388 | } 1389 | .w-lightbox-noscroll { 1390 | overflow: hidden; 1391 | } 1392 | @media (min-width: 768px) { 1393 | .w-lightbox-content { 1394 | height: 96vh; 1395 | margin-top: 2vh; 1396 | } 1397 | .w-lightbox-view, 1398 | .w-lightbox-view:before { 1399 | height: 96vh; 1400 | } 1401 | /* .w-lightbox-content */ 1402 | .w-lightbox-group, 1403 | .w-lightbox-group .w-lightbox-view, 1404 | .w-lightbox-group .w-lightbox-view:before { 1405 | height: 84vh; 1406 | } 1407 | .w-lightbox-image { 1408 | max-width: 96vw; 1409 | max-height: 96vh; 1410 | } 1411 | .w-lightbox-group .w-lightbox-image { 1412 | max-width: 82.3vw; 1413 | max-height: 84vh; 1414 | } 1415 | .w-lightbox-left, 1416 | .w-lightbox-right { 1417 | display: block; 1418 | opacity: .5; 1419 | } 1420 | .w-lightbox-close { 1421 | opacity: .8; 1422 | } 1423 | .w-lightbox-control:hover { 1424 | opacity: 1; 1425 | } 1426 | } 1427 | .w-lightbox-inactive, 1428 | .w-lightbox-inactive:hover { 1429 | opacity: 0; 1430 | } 1431 | .w-richtext:before, 1432 | .w-richtext:after { 1433 | content: " "; 1434 | display: table; 1435 | grid-column-start: 1; 1436 | grid-row-start: 1; 1437 | grid-column-end: 2; 1438 | grid-row-end: 2; 1439 | } 1440 | .w-richtext:after { 1441 | clear: both; 1442 | } 1443 | .w-richtext[contenteditable="true"]:before, 1444 | .w-richtext[contenteditable="true"]:after { 1445 | white-space: initial; 1446 | } 1447 | .w-richtext ol, 1448 | .w-richtext ul { 1449 | overflow: hidden; 1450 | } 1451 | .w-richtext .w-richtext-figure-selected.w-richtext-figure-type-video div:after, 1452 | .w-richtext .w-richtext-figure-selected[data-rt-type="video"] div:after { 1453 | outline: 2px solid #2895f7; 1454 | } 1455 | .w-richtext .w-richtext-figure-selected.w-richtext-figure-type-image div, 1456 | .w-richtext .w-richtext-figure-selected[data-rt-type="image"] div { 1457 | outline: 2px solid #2895f7; 1458 | } 1459 | .w-richtext figure.w-richtext-figure-type-video > div:after, 1460 | .w-richtext figure[data-rt-type="video"] > div:after { 1461 | content: ''; 1462 | position: absolute; 1463 | display: none; 1464 | left: 0; 1465 | top: 0; 1466 | right: 0; 1467 | bottom: 0; 1468 | } 1469 | .w-richtext figure { 1470 | position: relative; 1471 | max-width: 60%; 1472 | } 1473 | .w-richtext figure > div:before { 1474 | cursor: default!important; 1475 | } 1476 | .w-richtext figure img { 1477 | width: 100%; 1478 | } 1479 | .w-richtext figure figcaption.w-richtext-figcaption-placeholder { 1480 | opacity: 0.6; 1481 | } 1482 | .w-richtext figure div { 1483 | /* fix incorrectly sized selection border in the data manager */ 1484 | font-size: 0px; 1485 | color: transparent; 1486 | } 1487 | .w-richtext figure.w-richtext-figure-type-image, 1488 | .w-richtext figure[data-rt-type="image"] { 1489 | display: table; 1490 | } 1491 | .w-richtext figure.w-richtext-figure-type-image > div, 1492 | .w-richtext figure[data-rt-type="image"] > div { 1493 | display: inline-block; 1494 | } 1495 | .w-richtext figure.w-richtext-figure-type-image > figcaption, 1496 | .w-richtext figure[data-rt-type="image"] > figcaption { 1497 | display: table-caption; 1498 | caption-side: bottom; 1499 | } 1500 | .w-richtext figure.w-richtext-figure-type-video, 1501 | .w-richtext figure[data-rt-type="video"] { 1502 | width: 60%; 1503 | height: 0; 1504 | } 1505 | .w-richtext figure.w-richtext-figure-type-video iframe, 1506 | .w-richtext figure[data-rt-type="video"] iframe { 1507 | position: absolute; 1508 | top: 0; 1509 | left: 0; 1510 | width: 100%; 1511 | height: 100%; 1512 | } 1513 | .w-richtext figure.w-richtext-figure-type-video > div, 1514 | .w-richtext figure[data-rt-type="video"] > div { 1515 | width: 100%; 1516 | } 1517 | .w-richtext figure.w-richtext-align-center { 1518 | margin-right: auto; 1519 | margin-left: auto; 1520 | clear: both; 1521 | } 1522 | .w-richtext figure.w-richtext-align-center.w-richtext-figure-type-image > div, 1523 | .w-richtext figure.w-richtext-align-center[data-rt-type="image"] > div { 1524 | max-width: 100%; 1525 | } 1526 | .w-richtext figure.w-richtext-align-normal { 1527 | clear: both; 1528 | } 1529 | .w-richtext figure.w-richtext-align-fullwidth { 1530 | width: 100%; 1531 | max-width: 100%; 1532 | text-align: center; 1533 | clear: both; 1534 | display: block; 1535 | margin-right: auto; 1536 | margin-left: auto; 1537 | } 1538 | .w-richtext figure.w-richtext-align-fullwidth > div { 1539 | display: inline-block; 1540 | /* padding-bottom is used for aspect ratios in video figures 1541 | we want the div to inherit that so hover/selection borders in the designer-canvas 1542 | fit right*/ 1543 | padding-bottom: inherit; 1544 | } 1545 | .w-richtext figure.w-richtext-align-fullwidth > figcaption { 1546 | display: block; 1547 | } 1548 | .w-richtext figure.w-richtext-align-floatleft { 1549 | float: left; 1550 | margin-right: 15px; 1551 | clear: none; 1552 | } 1553 | .w-richtext figure.w-richtext-align-floatright { 1554 | float: right; 1555 | margin-left: 15px; 1556 | clear: none; 1557 | } 1558 | .w-nav { 1559 | position: relative; 1560 | background: #dddddd; 1561 | z-index: 1000; 1562 | } 1563 | .w-nav:before, 1564 | .w-nav:after { 1565 | content: " "; 1566 | display: table; 1567 | grid-column-start: 1; 1568 | grid-row-start: 1; 1569 | grid-column-end: 2; 1570 | grid-row-end: 2; 1571 | } 1572 | .w-nav:after { 1573 | clear: both; 1574 | } 1575 | .w-nav-brand { 1576 | position: relative; 1577 | float: left; 1578 | text-decoration: none; 1579 | color: #333333; 1580 | } 1581 | .w-nav-link { 1582 | position: relative; 1583 | display: inline-block; 1584 | vertical-align: top; 1585 | text-decoration: none; 1586 | color: #222222; 1587 | padding: 20px; 1588 | text-align: left; 1589 | margin-left: auto; 1590 | margin-right: auto; 1591 | } 1592 | .w-nav-link.w--current { 1593 | color: #0082f3; 1594 | } 1595 | .w-nav-menu { 1596 | position: relative; 1597 | float: right; 1598 | } 1599 | [data-nav-menu-open] { 1600 | display: block !important; 1601 | position: absolute; 1602 | top: 100%; 1603 | left: 0; 1604 | right: 0; 1605 | background: #C8C8C8; 1606 | text-align: center; 1607 | overflow: visible; 1608 | min-width: 200px; 1609 | } 1610 | .w--nav-link-open { 1611 | display: block; 1612 | position: relative; 1613 | } 1614 | .w-nav-overlay { 1615 | position: absolute; 1616 | overflow: hidden; 1617 | display: none; 1618 | top: 100%; 1619 | left: 0; 1620 | right: 0; 1621 | width: 100%; 1622 | } 1623 | .w-nav-overlay [data-nav-menu-open] { 1624 | top: 0; 1625 | } 1626 | .w-nav[data-animation="over-left"] .w-nav-overlay { 1627 | width: auto; 1628 | } 1629 | .w-nav[data-animation="over-left"] .w-nav-overlay, 1630 | .w-nav[data-animation="over-left"] [data-nav-menu-open] { 1631 | right: auto; 1632 | z-index: 1; 1633 | top: 0; 1634 | } 1635 | .w-nav[data-animation="over-right"] .w-nav-overlay { 1636 | width: auto; 1637 | } 1638 | .w-nav[data-animation="over-right"] .w-nav-overlay, 1639 | .w-nav[data-animation="over-right"] [data-nav-menu-open] { 1640 | left: auto; 1641 | z-index: 1; 1642 | top: 0; 1643 | } 1644 | .w-nav-button { 1645 | position: relative; 1646 | float: right; 1647 | padding: 18px; 1648 | font-size: 24px; 1649 | display: none; 1650 | cursor: pointer; 1651 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 1652 | tap-highlight-color: rgba(0, 0, 0, 0); 1653 | -webkit-user-select: none; 1654 | -moz-user-select: none; 1655 | -ms-user-select: none; 1656 | user-select: none; 1657 | } 1658 | .w-nav-button.w--open { 1659 | background-color: #C8C8C8; 1660 | color: white; 1661 | } 1662 | .w-nav[data-collapse="all"] .w-nav-menu { 1663 | display: none; 1664 | } 1665 | .w-nav[data-collapse="all"] .w-nav-button { 1666 | display: block; 1667 | } 1668 | .w--nav-dropdown-open { 1669 | display: block; 1670 | } 1671 | .w--nav-dropdown-toggle-open { 1672 | display: block; 1673 | } 1674 | .w--nav-dropdown-list-open { 1675 | position: static; 1676 | } 1677 | @media screen and (max-width: 991px) { 1678 | .w-nav[data-collapse="medium"] .w-nav-menu { 1679 | display: none; 1680 | } 1681 | .w-nav[data-collapse="medium"] .w-nav-button { 1682 | display: block; 1683 | } 1684 | } 1685 | @media screen and (max-width: 767px) { 1686 | .w-nav[data-collapse="small"] .w-nav-menu { 1687 | display: none; 1688 | } 1689 | .w-nav[data-collapse="small"] .w-nav-button { 1690 | display: block; 1691 | } 1692 | .w-nav-brand { 1693 | padding-left: 10px; 1694 | } 1695 | } 1696 | @media screen and (max-width: 479px) { 1697 | .w-nav[data-collapse="tiny"] .w-nav-menu { 1698 | display: none; 1699 | } 1700 | .w-nav[data-collapse="tiny"] .w-nav-button { 1701 | display: block; 1702 | } 1703 | } 1704 | .w-tabs { 1705 | position: relative; 1706 | } 1707 | .w-tabs:before, 1708 | .w-tabs:after { 1709 | content: " "; 1710 | display: table; 1711 | grid-column-start: 1; 1712 | grid-row-start: 1; 1713 | grid-column-end: 2; 1714 | grid-row-end: 2; 1715 | } 1716 | .w-tabs:after { 1717 | clear: both; 1718 | } 1719 | .w-tab-menu { 1720 | position: relative; 1721 | } 1722 | .w-tab-link { 1723 | position: relative; 1724 | display: inline-block; 1725 | vertical-align: top; 1726 | text-decoration: none; 1727 | padding: 9px 30px; 1728 | text-align: left; 1729 | cursor: pointer; 1730 | color: #222222; 1731 | background-color: #dddddd; 1732 | } 1733 | .w-tab-link.w--current { 1734 | background-color: #C8C8C8; 1735 | } 1736 | .w-tab-content { 1737 | position: relative; 1738 | display: block; 1739 | overflow: hidden; 1740 | } 1741 | .w-tab-pane { 1742 | position: relative; 1743 | display: none; 1744 | } 1745 | .w--tab-active { 1746 | display: block; 1747 | } 1748 | @media screen and (max-width: 479px) { 1749 | .w-tab-link { 1750 | display: block; 1751 | } 1752 | } 1753 | .w-ix-emptyfix:after { 1754 | content: ""; 1755 | } 1756 | @keyframes spin { 1757 | 0% { 1758 | transform: rotate(0deg); 1759 | } 1760 | 100% { 1761 | transform: rotate(360deg); 1762 | } 1763 | } 1764 | .w-dyn-empty { 1765 | padding: 10px; 1766 | background-color: #dddddd; 1767 | } 1768 | .w-dyn-hide { 1769 | display: none !important; 1770 | } 1771 | .w-dyn-bind-empty { 1772 | display: none !important; 1773 | } 1774 | .w-condition-invisible { 1775 | display: none !important; 1776 | } 1777 | -------------------------------------------------------------------------------- /images/LightDefi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JTraversa/DefiHedge-Protocol/ac5227bc9fc898145963333ecf4a54339789a6f1/images/LightDefi.png -------------------------------------------------------------------------------- /images/background-p-1080.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JTraversa/DefiHedge-Protocol/ac5227bc9fc898145963333ecf4a54339789a6f1/images/background-p-1080.png -------------------------------------------------------------------------------- /images/background-p-500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JTraversa/DefiHedge-Protocol/ac5227bc9fc898145963333ecf4a54339789a6f1/images/background-p-500.png -------------------------------------------------------------------------------- /images/background-p-800.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JTraversa/DefiHedge-Protocol/ac5227bc9fc898145963333ecf4a54339789a6f1/images/background-p-800.png -------------------------------------------------------------------------------- /images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JTraversa/DefiHedge-Protocol/ac5227bc9fc898145963333ecf4a54339789a6f1/images/background.png -------------------------------------------------------------------------------- /images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JTraversa/DefiHedge-Protocol/ac5227bc9fc898145963333ecf4a54339789a6f1/images/favicon.ico -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JTraversa/DefiHedge-Protocol/ac5227bc9fc898145963333ecf4a54339789a6f1/images/logo.png -------------------------------------------------------------------------------- /images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 14 | 20 | 24 | 27 | 29 | 33 | 37 | 40 | 43 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /images/resized-p-500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JTraversa/DefiHedge-Protocol/ac5227bc9fc898145963333ecf4a54339789a6f1/images/resized-p-500.png -------------------------------------------------------------------------------- /images/resized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JTraversa/DefiHedge-Protocol/ac5227bc9fc898145963333ecf4a54339789a6f1/images/resized.png -------------------------------------------------------------------------------- /images/webclip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JTraversa/DefiHedge-Protocol/ac5227bc9fc898145963333ecf4a54339789a6f1/images/webclip.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DefiHedge 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |
22 |
0x-------------------------
23 |
Tx:
24 |
User Address:
25 |
26 |
27 | 28 |
30 |
ETHDAI 31 |
Rate:
32 |
Duration:
33 |
Token:
34 |
Supplied:
35 |
36 |
37 | 38 | 39 | 40 | 41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
Create Offer 49 | Authorize Token
50 |
51 |
52 |
53 |
Active Offers:
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
0x-------------------------
69 |
70 |
Rate:
71 |
Duration:
72 |
Token:
73 |
Supplied:
74 |
Taker Stake:
75 |
76 |

77 |
78 |
79 |

80 |
81 |
82 |

83 |
84 |
85 |

86 |
87 |
88 |

89 |
Authorize Token 90 | Take Offer
91 |
92 |
93 |
Active Contracts:
94 |
0x-------------------------
95 |
0.00 ETH
96 |
Rate: 0%
97 | Release 98 | Release 99 | Release 100 |
0x-------------------------
101 |
0.00 ETH
102 |
Rate: 0%
103 |
0x-------------------------
104 |
0.00 ETH
105 |
Rate: 0%
106 |
01/01/2001 7:00:01 PM
107 |
01/01/2001 7:00:01 PM
108 |
01/01/2001 7:00:01 PM
109 |
110 |
111 | Local On-Chain PoC, Deployed on Ropsten 112 |
113 |
114 | 1. Chose Eth or Dai and approve Dai if necessary (Acquire Dai from Maker if necessary) 115 |
116 |
117 | 2. Place a fixed-side order at a chosen rate and maturity. 118 |
119 |
120 | 3. After confirmation, (or if an order already exists) select the order from the order list. 121 |
122 |
123 | 4. After inspecting the order's parameters, approve the new contract, "take" the order, and in the process back the fixed-rate with 100% like-kind collateral. 124 |
125 |
126 | 5. Once the agreement reaches maturity release the timelock, returning the fixed-yield to one party and remaining interest to another. 127 |
128 |
129 | 130 | 131 | 132 | 133 | 1740 | 1741 | 1742 | -------------------------------------------------------------------------------- /js/test.js: -------------------------------------------------------------------------------- 1 | 2 | function toggleText() { 3 | var x = document.getElementById("Rate").value; 4 | var y = document.getElementById("Duration").value; 5 | var z = document.getElementById("Token").value; 6 | var w = document.getElementById("Supplied").value; 7 | document.getElementById("outputRate").innerHTML = x; 8 | document.getElementById("outputDuration").innerHTML = y; 9 | document.getElementById("outputToken").innerHTML = z; 10 | document.getElementById("outputSupply").innerHTML = w; 11 | } 12 | --------------------------------------------------------------------------------