From ddc9b838ad62250945d3bb4c35f398e09833862c Mon Sep 17 00:00:00 2001 From: Matthew Black Date: Tue, 19 Mar 2019 11:27:59 -0400 Subject: [PATCH 1/9] ERC 1850 --- EIPS/eip-1850.md | 548 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 548 insertions(+) create mode 100644 EIPS/eip-1850.md diff --git a/EIPS/eip-1850.md b/EIPS/eip-1850.md new file mode 100644 index 00000000000000..4e7a2e94ebb9ed --- /dev/null +++ b/EIPS/eip-1850.md @@ -0,0 +1,548 @@ +--- +eip: ??? +title: Hashed Time-Locked Atomic Loan Contract transactions +author: Matthew Black , Tony Cai , Atomic Loans team +status: Draft +discussions-to: https://github.com/ethereum/EIPs/issues/??? +type: Standards Track +category: ERC +created: 2019-02-03 +--- + +## Simple Summary + +This EIP describes a script for a generalized debt agreement contract based on Hashed Time-Lock Contract (ERC 1630) transactions according to the Atomic Loans specification (https://arxiv.org/pdf/1901.05117.pdf). + + +## Abstract + +A Hashed Time-Locked Atomic Loan Contract is a script that permits a designated party (the "lender") to provide funds for a debt agreement for a specified amount of time, with collateral locked on another blockchain (denoted as the collateral blockchain for the purposes of this EIP). It also permits a second party (the "borrower") to withdraw the lent funds once their request to borrow has been approved by the lender, repay the loan after the loan period has passed and in the case of default, liquidate the collateral. + +## Motivation + +Hashed Time-Locked Atomic Loan Contract transactions are a safe method for exchanging multiple secrets for the purposes of executing a cross-chain debt agreement, due to the ability to recover a percentage of funds from an uncooperative counterparty. + +Hashed Time-Locked Atomic Loan Contract's enable cross-chain [atomic loans](https://arxiv.org/pdf/1901.05117.pdf) + +## Definitions + +`msg.sender`: is always the address where the current (external) function call came from + +`borrower`: entity that locks collateral on another blockchain and receives loan amount from `lender` following the approval of the `borrower’s` borrow request + +`lender`: entity that contributes funds to the Hashed Time-Lock Atomic Loan contract, to be borrowed by the `borrower` upon the locking of collateral and the `lender’s` approval + +`bidder`: entity that bids on the collateral to enable liquidation of the collateral + +`secret`: random number chosen by the `borrower` or `lender`, revealed to allow the parties to change the state of the debt agreement + +`secretHash`: hash of the `secret`, used in the construction of Hashed Time-Locked Atomic Loan Contract + +`expiration`: timestamp that determines which part of the debt agreement the two parties are in + +`now`: current block timestamp + +`principal`: the amount borrowed within the loan, upon which interest is calculated + +`interest`: a percentage amount of the loan principal paid by the `borrower` to the `lender`, in addition to the repayment of principal + +`approved`: `bool` state where if true, the collateral (and request to borrow from the `borrower`) has been accepted by the `lender` + +`bidding`: `bool` state where if true, third party `bidders` are able to bid on the collateral in order to liquidate it + +`currentBid`: highest bid on the collateral so far + +`liquidatedCollateralWidthdrawn`: `bool` state where the `borrower` and `lender` have withdrawn their share of the liquidated collateral + +`SecretA1`: secret generated by the `borrower`, used to prove that the `borrower` has withdrawn the loan + +`SecretA2`: secret generated by the `borrower`, used to allow the `bidder` to withdraw the liquidated collateral funds + +`SecretB1`: secret generated by the `lender`, used to accept the locking of collateral by `borrower`, enabling `borrower` to withdraw the loan amount + +`SecretB2`: secret generated by the `lender`, used to refund themselves in the event they aren't satisfied with `borrower’s`locking of collateral. Also used to accept `borrower’s` repayment of principal plus interest + +`SecretB3`: secret generated by the `lender`, used to allow the `bidder` to withdraw the liquidated collateral funds + + +`SecretC`: secret generated by the `bidder`,used to accept the signatures of the `borrower` and `lender` for authorizing the liquidation of collateral + +`ApproveExpiration`: timestamp after which the `lender` can no longer `approve` the loan by accepting requests to borrow from the `borrower` + +`LoanExpiration`: timestamp before which the `borrower` must repay the loan; or otherwise risk the liquidation or seizure of their collateral + +`AcceptExpiration`: timestamp before which the `lender` must accept the repayment of the loan + +`BiddingExpiration`: timestamp that determines the amount of time allocated to bidding before seizure period occurs + + +**Approve Period:** +During this time, the `lender` deploys the Hashed Time-Locked Atomic Loan Contract. Following this, the borrower locks their collateral on the collateral blockchain in a Hashed Time-Locked Atomic Loan Collateral Contract https://github.com/mattBlackDesign/BIP. The `lender` then either reveals `secretB1` to signify that they are satisfied with the collateral, and the borrower can withdraw the loan by revealing `secretA1`. If the `lender` is not satisfied with the collateral locked by the `borrower`, the `lender` can refunds their loan amount by revealing `secretB2`, which will subsequently allow the borrower to refund the collateral amount they deposited. + +**Loan Period:** +Once the `borrower` has withdrawn the loan amount, the Loan Period begins. Once the Loan Period is finished, the `borrower` is expected to repay the loan. If they do, the `lender` can then accept the repayment by revealing `secretB2`, enabling the borrower to refund their collateral amount. In the case that the `borrower` defaults or does not repay the full principal plus interest amount, the `lender` can choose to not accept the loan repayment, and the parties can opt for liquidation of the collateral in the Bidding Period. + +**Bidding Period:** +In the case of a default or the `lender` not accepting the `borrower` repayment, the `lender` and `borrower` can opt for liquidation of the collateral through the process of third party bidders bidding on the collateral. The Bidding Period can be initiated by either the `lender` or the `borrower`. Once the bidding timeout occurs, the `lender` and `borrower` must each provide a signature to allow the collateral to be withdrawn by the winning `bidder`. + +**Seizure Period:** +In the case that bidding is unsuccessful, the `lender` can seize a percentage of the collateral. The amount is dependent on the amount of collateral locked in the seizable script and refundable script as described in the BIP (https://github.com/mattBlackDesign/BIP). During this period the `borrower` can also refund the funds locked in the refundable script. + +**Refund Period:** +In the case of a default where the `lender` does not seize the collateral locked in the seizable script, then the borrower can refund the funds locked in the seizablescript. + +## Specification + +### Constructor + +The `msg.sender` transfers funds to the smart contract during its deployment. + +```js +constructor ( + bytes32 _secretHashA1, + bytes32 _secretHashA2, + bytes32 _secretHashB1, + bytes32 _secretHashB2, + bytes32 _secretHashB3, + uint256 _approveExpiration, + uint256 _loanExpiration, + uint256 _acceptExpiration, + uint256 _biddingExpiration, + address _borrower, + uint256 _principal, + uint256 _interest, + uint256 _liquidationFee, + uint256 _biddingTimeout, + uint256 _biddingRefund, + address _tokenAddress + ) public { + secretHashA1 = _secretHashA1; + secretHashA2 = _secretHashA2; + secretHashB1 = _secretHashB1; + secretHashB2 = _secretHashB2; + secretHashB3 = _secretHashB3; + approveExpiration = _approveExpiration; + loanExpiration = _loanExpiration; + acceptExpiration = _acceptExpiration; + biddingExpiration = _biddingExpiration; + borrower = _borrower; + lender = msg.sender; + principal = _principal; + interest = _interest; + liquidationFee = _liquidationFee; + biddingTimeout = _biddingTimeout; + biddingRefund = _biddingRefund; + token = StandardToken(_tokenAddress); + } +``` + +## Methods + +### fund + +The `msg.sender` or `lender` transfers tokens for the loan amount to the contract + +SHOULD throw if `funded` is true + +```js +function fund () public { +``` + +### approve + +The `msg.sender` or `lender` approves the locking of collateral done by the Borrower on the collateral blockchain. + +SHOULD throw if `msg.sender` does not equal `lender` address + +SHOULD throw if hash of `_secretB1` does not equal `secretHashB1` + +SHOULD throw if `now` is greater than `approveExpiration` + +Note `secret` can be any bytesize, but that should be specified by the two parties before the HTLC is initiated. The recommended size is 32 bytes. + +```js +function approve (bytes32 _secretB1) public { +``` + +### withdraw + +The `msg.sender` or `borrower` withdraws the loan amount + +SHOULD throw if hash of `_secretA1` does not equal `secretHashA1` + +SHOULD throw if hash of `_secretB1` does not equal `secretHashB1` + +SHOULD throw if `approved` does not equal true + +```js +function withdraw (bytes32 _secretA1, bytes32 _secretB1) public { +``` + +### acceptOrCancel + +The `msg.sender` or `lender` accepts the `borrower` repayment of the `principal` plus `interest` + +SHOULD throw if hash of `_secretB2` does not equal `secretHashB2` + +SHOULD throw if `now` is less than or equal to `withdrawExpiration` + +SHOULD throw if `now` is greater than `acceptExpiration` + +SHOULD throw if `bidding` is true + +```js +function acceptOrCancel (bytes32 _secretB2) public { +``` + +### payback + +The `msg.sender` or `borrower` repays the loan amount + +SHOULD throw if `msg.value` does not equal `principal` plus `interest` + +Note that in this version, it is expected that the borrower make just one repayment, which covers the entirety of `principal` plus `interest` + +```js +function payback () public payable returns (bool success) { +``` + +### refundPayback + +The `msg.sender` or `borrower` refunds the repayment amount they put forth in the event their repayment is not accepted by the `lender` + +SHOULD throw if `now` less than or equal to `acceptExpiration` + +SHOULD throw if `repaid` is false + +SHOULD throw if `msg.sender` is not the borrower + +```js +function refundPayback () public { +``` + +### startBidding + +The `msg.sender` (either the `lender` or `borrower`) initiates the bidding process + +SHOULD throw if `repaid` is true + +SHOULD throw if `withdrawn` is false + +SHOULD throw if `now` is less than or equal to `loanExpiration` + +SHOULD throw if `msg.sender` is neither a `borrower` address nor a `lender` address + +```js +function startBidding () public { +``` + +### bid + +The `msg.sender` (anyone who is interested in bidding on the collateral) bids on the collateral + +SHOULD throw if `bidding` is not `true` + +SHOULD throw if `now` is less than or equal to `loanExpiration` + +SHOULD throw if `now` is greater than biddingTimeoutExpiration + +SHOULD throw if `_bidValue` is less than or equal to `currentBid` + +SHOULD throw if token balance of `msg.sender` is less than `_bidValue` + +```js +function bid (bytes32 _secretHashC, uint256 bidValue) public { +``` + +### provideSignature + +The `msg.sender` provides a `signature` for the collateral blockchain enabling the `bidder` to spend the `collateral` in the liquidation process + +SHOULD throw if `now` is less than or equal to `loanExpiration` + +```js +function provideSignature (string _signature) public { +``` + +### provideSecret + +The `msg.sender` provides a `secret` to enable the `bidder` to spend the `collateral` in the liquidation process + +SHOULD throw if `now` is less than or equal to `loanExpiration` + +if `msg.sender` is the `borrower`, then SHOULD throw if the hash of `_secret` does not equal `secretHashA2` + +if `msg.sender` is the `lender`, then SHOULD throw if the hash of `_secret` does not equal `secretHashB3` + +if `msg.sender` is neither the `lender` or `borrower`, it SHOULD throw + +```js +function provideSecret (bytes32 _secret) public { +``` + +### withdrawLiquidatedCollateral + +The `msg.sender` (either `borrower` or `lender`) withdraws the liquidated collateral + +SHOULD throw if `now` is less than or equal to `biddingTimeoutExpiration` + +if `msg.sender` is the borrower, then SHOULD throw if `borrowerLiquidatedCollateralWithdrawn` is true + +if `msg.sender` is the lender, then SHOULD throw if `lenderLiquidatedCollateralWithdraw` is true + +if `msg.sender` is neither the lender or borrower, it SHOULD throw + +```js +function withdrawLiquidatedCollateral (bytes32 _secretA2, bytes32 _secretB2, bytes32 _secretC) public { +``` + +### refundBid + +The `msg.sender` or `bidder` refunds their bid in the case that the `borrower` and `lender` do not opt into liquidating the collateral + +SHOULD throw if `repaid` is true + +SHOULD throw if `now` less than or equal to `biddingRefundExpiration` + +SHOULD throw if the hash of `secretC` equals `secretHashC` and the hash of `secretA2` equals `secretHashA2` and the hash of `secretB2` equals `secretHashB2` + +SHOULD throw if `borrowerLiquidatedCollateralWithdrawn` is true + +SHOULD throw if `lenderLiquidatedCollateralWithdrawn` is true + +SHOULD throw if `currentBid` is less than or equal to 0 + +```js +function refundBid () public { +``` + +## Compatibility + +ERC ??? is compatible with [BIP ???](https://github.com/atomicloans/bip) for [atomic loans](https://arxiv.org/pdf/1901.05117.pdf) with Bitcoin and other HTLC compatible chains. + +## Implementation + +This implementation is a simple example of a Hashed Time-Locked Atomic Loan Contract using Solidity + +https://github.com/AtomicLoans/ethereum-contracts/blob/master/contracts/AtomicLoan.sol + +```js +pragma solidity ^0.4.25; + +contract AtomicLoan { + using SafeMath for uint256; + + address borrower; + address lender; + address bidder; + + bytes32 secretHashA1; + bytes32 secretHashA2; + bytes32 secretHashB1; + bytes32 secretHashB2; + bytes32 secretHashB3; + bytes32 secretHashC; + + bytes32 public secretA2; + bytes32 public secretB2; + bytes32 public secretB3; + bytes32 public secretC; + + uint256 approveExpiration; + uint256 loanExpiration; + uint256 acceptExpiration; + uint256 biddingExpiration; + + uint256 biddingTimeout; + uint256 biddingRefund; + + uint256 public principal; + uint256 public interest; + uint256 public liquidationFee; + + bool public funded = false; + bool public approved = false; + bool public withdrawn = false; + bool public bidding = false; + bool public repaid = false; + + uint256 currentBid = 0; + uint256 biddingTimeoutExpiration; + uint256 biddingRefundExpiration; + + string public borrowerSignature; + string public lenderSignature; + + bool liquidatedCollateralWidthdrawn = false; + + string aCoinAddress; + + StandardToken public token; + + constructor ( + bytes32 _secretHashA1, + bytes32 _secretHashA2, + bytes32 _secretHashB1, + bytes32 _secretHashB2, + bytes32 _secretHashB3, + uint256 _approveExpiration, + uint256 _loanExpiration, + uint256 _acceptExpiration, + uint256 _biddingExpiration, + address _borrower, + uint256 _principal, + uint256 _interest, + uint256 _liquidationFee, + uint256 _biddingTimeout, + uint256 _biddingRefund, + address _tokenAddress + ) public { + secretHashA1 = _secretHashA1; + secretHashA2 = _secretHashA2; + secretHashB1 = _secretHashB1; + secretHashB2 = _secretHashB2; + secretHashB3 = _secretHashB3; + approveExpiration = _approveExpiration; + loanExpiration = _loanExpiration; + acceptExpiration = _acceptExpiration; + biddingExpiration = _biddingExpiration; + borrower = _borrower; + lender = msg.sender; + principal = _principal; + interest = _interest; + liquidationFee = _liquidationFee; + biddingTimeout = _biddingTimeout; + biddingRefund = _biddingRefund; + token = StandardToken(_tokenAddress); + } + + function fund () public { + require(funded == false); + token.transferFrom(msg.sender, address(this), principal); + funded = true; + } + + function approve (bytes32 _secretB1) public { + require(funded == true); + require(sha256(abi.encodePacked(_secretB1)) == secretHashB1); + require(now <= approveExpiration); + approved = true; + } + + function withdraw (bytes32 _secretA1, bytes32 _secretB1) public { + require(funded == true); + require(approved == true); + require(sha256(abi.encodePacked(_secretA1)) == secretHashA1); + require(sha256(abi.encodePacked(_secretB1)) == secretHashB1); + token.transfer(borrower, token.balanceOf(address(this))); + withdrawn = true; + } + + function accept_or_cancel (bytes32 _secretB2) public { + require(sha256(abi.encodePacked(_secretB2)) == secretHashB2); + require(now > approveExpiration); + require(now <= acceptExpiration); + require(bidding == false); + token.transfer(lender, token.balanceOf(address(this))); + selfdestruct(lender); + } + + function payback () public { + require(withdrawn == true); + require(now <= loanExpiration); + require(msg.sender == borrower); + token.transferFrom(borrower, address(this), principal.add(interest)); + repaid = true; + } + + function refundPayback () public { + require(now > acceptExpiration); + require(repaid == true); + require(msg.sender == borrower); + token.transfer(borrower, token.balanceOf(address(this))); + selfdestruct(borrower); + } + + function startBidding () public { + require(repaid == false); + require(withdrawn == true); + require(now > loanExpiration); + require(msg.sender == borrower || msg.sender == lender); + biddingTimeoutExpiration = now.add(biddingTimeout); + biddingRefundExpiration = biddingTimeoutExpiration.add(biddingRefund); + bidding = true; + } + + function bid (bytes32 _secretHashC, uint256 _bidValue, string _aCoinAddress) public { + require(bidding == true); + require(now > loanExpiration); + require(now <= biddingTimeoutExpiration); + require(_bidValue > currentBid); + require(token.balanceOf(msg.sender) >= _bidValue); + token.transferFrom(msg.sender, address(this), _bidValue); + if (currentBid > 0) { + token.transfer(bidder, currentBid); + } + bidder = msg.sender; + currentBid = _bidValue; + secretHashC = _secretHashC; + aCoinAddress = _aCoinAddress; + } + + function provideSignature (string memory _signature) public { + require(now > loanExpiration); // Is this needed? + if (msg.sender == borrower) { + borrowerSignature = _signature; + } else if (msg.sender == lender) { + lenderSignature = _signature; + } else { + revert(); + } + } + + function provideSecret (bytes32 _secret) public { + require(now > loanExpiration); + if (msg.sender == borrower) { + require(sha256(abi.encodePacked(_secret)) == secretHashA2); + secretA2 = _secret; + } else if (msg.sender == lender) { + require(sha256(abi.encodePacked(_secret)) == secretHashB3); + secretB3 = _secret; + } else if (msg.sender == bidder) { + require(sha256(abi.encodePacked(_secret)) == secretHashC); + secretC = _secret; + } else { + revert(); + } + } + + function withdrawLiquidatedCollateral (bytes32 _secretA2, bytes32 _secretB3, bytes32 _secretC) public { + require(now > biddingTimeoutExpiration); + require(sha256(abi.encodePacked(_secretA2)) == secretHashA2); + require(sha256(abi.encodePacked(_secretB3)) == secretHashB3); + require(sha256(abi.encodePacked(_secretC)) == secretHashC); + require(msg.sender == borrower || msg.sender == lender); + if (currentBid > (principal.add(interest).add(liquidationFee))) { + token.transfer(lender, (principal.add(interest).add(liquidationFee))); + token.transfer(borrower, token.balanceOf(address(this))); + } else { + token.transfer(lender, currentBid); + } + selfdestruct(lender); + } + + function refundBid () public { + require(now > biddingRefundExpiration); + require(sha256(abi.encodePacked(secretC)) != secretHashC || sha256(abi.encodePacked(secretA2)) != secretHashA2 || sha256(abi.encodePacked(secretB3)) != secretHashB3); + require(currentBid > 0); + token.transfer(bidder, currentBid); + selfdestruct(lender); + } +} +``` + +Note other hash functions can also be used, such as `keccak256`, `ripemd160`. However both parties should specify the hash function to be used before the Hashed Time-Locked Atomic Loan Contract is initialized. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From d5ec889cbeae77b7e102a17456d6f0f1a40a764d Mon Sep 17 00:00:00 2001 From: Matthew Black Date: Tue, 19 Mar 2019 11:42:21 -0400 Subject: [PATCH 2/9] Small fixes --- EIPS/eip-1850.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EIPS/eip-1850.md b/EIPS/eip-1850.md index 4e7a2e94ebb9ed..d38f6fefbdca5e 100644 --- a/EIPS/eip-1850.md +++ b/EIPS/eip-1850.md @@ -1,17 +1,17 @@ --- -eip: ??? +eip: 1850 title: Hashed Time-Locked Atomic Loan Contract transactions author: Matthew Black , Tony Cai , Atomic Loans team status: Draft -discussions-to: https://github.com/ethereum/EIPs/issues/??? +discussions-to: https://github.com/ethereum/EIPs/issues/1851 type: Standards Track category: ERC -created: 2019-02-03 +created: 2019-03-19 --- ## Simple Summary -This EIP describes a script for a generalized debt agreement contract based on Hashed Time-Lock Contract (ERC 1630) transactions according to the Atomic Loans specification (https://arxiv.org/pdf/1901.05117.pdf). +This EIP describes a script for a generalized debt agreement contract based on Hashed Time-Lock Contract (ERC 1850) transactions according to the Atomic Loans specification (https://arxiv.org/pdf/1901.05117.pdf). ## Abstract From a0b76c89d6e780c49c14ef6b501395ddfb22dbce Mon Sep 17 00:00:00 2001 From: Matthew Black Date: Tue, 19 Mar 2019 11:52:04 -0400 Subject: [PATCH 3/9] Replace ??? with ERC 1850 --- EIPS/eip-1850.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-1850.md b/EIPS/eip-1850.md index d38f6fefbdca5e..3d03c01854207f 100644 --- a/EIPS/eip-1850.md +++ b/EIPS/eip-1850.md @@ -318,7 +318,7 @@ function refundBid () public { ## Compatibility -ERC ??? is compatible with [BIP ???](https://github.com/atomicloans/bip) for [atomic loans](https://arxiv.org/pdf/1901.05117.pdf) with Bitcoin and other HTLC compatible chains. +ERC 1850 is compatible with [BIP ???](https://github.com/atomicloans/bip) for [atomic loans](https://arxiv.org/pdf/1901.05117.pdf) with Bitcoin and other HTLC compatible chains. ## Implementation From 984267897867d9c7141a4576a465985a5cd02055 Mon Sep 17 00:00:00 2001 From: Matthew Black Date: Tue, 19 Mar 2019 11:53:28 -0400 Subject: [PATCH 4/9] Change contract transactions to Contracts --- EIPS/eip-1850.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-1850.md b/EIPS/eip-1850.md index 3d03c01854207f..b4aa157a4bdb11 100644 --- a/EIPS/eip-1850.md +++ b/EIPS/eip-1850.md @@ -1,6 +1,6 @@ --- eip: 1850 -title: Hashed Time-Locked Atomic Loan Contract transactions +title: Hashed Time-Locked Atomic Loan Contracts author: Matthew Black , Tony Cai , Atomic Loans team status: Draft discussions-to: https://github.com/ethereum/EIPs/issues/1851 From 77bf6720c7f282ef0bb55d967c6bef195c1cd880 Mon Sep 17 00:00:00 2001 From: Matthew Black Date: Fri, 22 Mar 2019 02:47:54 -0400 Subject: [PATCH 5/9] Improve wording in EIP-1850 --- EIPS/eip-1850.md | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/EIPS/eip-1850.md b/EIPS/eip-1850.md index b4aa157a4bdb11..88336f05a455fe 100644 --- a/EIPS/eip-1850.md +++ b/EIPS/eip-1850.md @@ -1,6 +1,6 @@ --- eip: 1850 -title: Hashed Time-Locked Atomic Loan Contracts +title: Hashed Time-Locked Principal Contract transactions author: Matthew Black , Tony Cai , Atomic Loans team status: Draft discussions-to: https://github.com/ethereum/EIPs/issues/1851 @@ -11,34 +11,36 @@ created: 2019-03-19 ## Simple Summary -This EIP describes a script for a generalized debt agreement contract based on Hashed Time-Lock Contract (ERC 1850) transactions according to the Atomic Loans specification (https://arxiv.org/pdf/1901.05117.pdf). +This EIP describes a script for a generalized debt agreement contract based on Hashed Time-Lock Contract (ERC 1630) transactions according to the Atomic Loans specification (https://arxiv.org/pdf/1901.05117.pdf). ## Abstract -A Hashed Time-Locked Atomic Loan Contract is a script that permits a designated party (the "lender") to provide funds for a debt agreement for a specified amount of time, with collateral locked on another blockchain (denoted as the collateral blockchain for the purposes of this EIP). It also permits a second party (the "borrower") to withdraw the lent funds once their request to borrow has been approved by the lender, repay the loan after the loan period has passed and in the case of default, liquidate the collateral. +A Hashed Time-Locked Principal Contract (HTLPC) is a script that permits a designated party (the "lender") to provide ERC20 denominated funds for a debt agreement for a specified amount of time, with collateral locked on another blockchain (denoted as the collateral blockchain for the purposes of this EIP). It also permits a second party (the "borrower") to withdraw the lent funds once their request to borrow has been approved by the lender, repay the loan after the loan period has passed and in the case of default, liquidate the collateral. ## Motivation -Hashed Time-Locked Atomic Loan Contract transactions are a safe method for exchanging multiple secrets for the purposes of executing a cross-chain debt agreement, due to the ability to recover a percentage of funds from an uncooperative counterparty. +HTLPC transactions are a safe method for exchanging multiple secrets for the purposes of executing a cross-chain debt agreement, due to the ability to recover a percentage of funds from an uncooperative counterparty. -Hashed Time-Locked Atomic Loan Contract's enable cross-chain [atomic loans](https://arxiv.org/pdf/1901.05117.pdf) +HLTPC's enable cross-chain [atomic loans](https://arxiv.org/pdf/1901.05117.pdf) ## Definitions -`msg.sender`: is always the address where the current (external) function call came from +`msg.sender`: is always the address where the current function call came from `borrower`: entity that locks collateral on another blockchain and receives loan amount from `lender` following the approval of the `borrower’s` borrow request -`lender`: entity that contributes funds to the Hashed Time-Lock Atomic Loan contract, to be borrowed by the `borrower` upon the locking of collateral and the `lender’s` approval +`lender`: entity that contributes funds to the HTLPC, to be borrowed by the `borrower` upon the locking of collateral on the collateral chain and the `lender’s` approval `bidder`: entity that bids on the collateral to enable liquidation of the collateral -`secret`: random number chosen by the `borrower` or `lender`, revealed to allow the parties to change the state of the debt agreement +`repay`: when the `borrower` pays back the `principal` + `interest` before `loanExpiration` + +`default`: when the `borrower` fails to pay back the `principal` + `interest` before the `loanExpiration` -`secretHash`: hash of the `secret`, used in the construction of Hashed Time-Locked Atomic Loan Contract +`secret`: random number chosen by the `borrower` or `lender`, revealed to allow the parties to change the state of the debt agreement -`expiration`: timestamp that determines which part of the debt agreement the two parties are in +`secretHash`: hash of the `secret`, used in the construction of HTLPC `now`: current block timestamp @@ -46,7 +48,7 @@ Hashed Time-Locked Atomic Loan Contract's enable cross-chain [atomic loans](http `interest`: a percentage amount of the loan principal paid by the `borrower` to the `lender`, in addition to the repayment of principal -`approved`: `bool` state where if true, the collateral (and request to borrow from the `borrower`) has been accepted by the `lender` +`approved`: `bool` state where if true, the request to borrow, as well as the collateral from the `borrower` has been accepted by the `lender` `bidding`: `bool` state where if true, third party `bidders` are able to bid on the collateral in order to liquidate it @@ -65,7 +67,7 @@ Hashed Time-Locked Atomic Loan Contract's enable cross-chain [atomic loans](http `SecretB3`: secret generated by the `lender`, used to allow the `bidder` to withdraw the liquidated collateral funds -`SecretC`: secret generated by the `bidder`,used to accept the signatures of the `borrower` and `lender` for authorizing the liquidation of collateral +`SecretC`: secret generated by the `bidder`, used to accept the signatures of the `borrower` and `lender` for authorizing the liquidation of collateral `ApproveExpiration`: timestamp after which the `lender` can no longer `approve` the loan by accepting requests to borrow from the `borrower` @@ -77,19 +79,19 @@ Hashed Time-Locked Atomic Loan Contract's enable cross-chain [atomic loans](http **Approve Period:** -During this time, the `lender` deploys the Hashed Time-Locked Atomic Loan Contract. Following this, the borrower locks their collateral on the collateral blockchain in a Hashed Time-Locked Atomic Loan Collateral Contract https://github.com/mattBlackDesign/BIP. The `lender` then either reveals `secretB1` to signify that they are satisfied with the collateral, and the borrower can withdraw the loan by revealing `secretA1`. If the `lender` is not satisfied with the collateral locked by the `borrower`, the `lender` can refunds their loan amount by revealing `secretB2`, which will subsequently allow the borrower to refund the collateral amount they deposited. +During this time, the `lender` deploys the HTLPC. Following this, the borrower locks their collateral on the collateral blockchain in a Hashed Time-Locked Collateral Contract (HTLCC) (Bitcoin version specified here: https://github.com/atomicloans/BIP). The `lender` then either reveals `secretB1` to signify that they are satisfied with the collateral, and the borrower can withdraw the loan by revealing `secretA1`. If the `lender` is not satisfied with the collateral locked by the `borrower`, the `lender` can refunds their loan amount by revealing `secretB2`, which will subsequently allow the borrower to refund the collateral amount they deposited. **Loan Period:** -Once the `borrower` has withdrawn the loan amount, the Loan Period begins. Once the Loan Period is finished, the `borrower` is expected to repay the loan. If they do, the `lender` can then accept the repayment by revealing `secretB2`, enabling the borrower to refund their collateral amount. In the case that the `borrower` defaults or does not repay the full principal plus interest amount, the `lender` can choose to not accept the loan repayment, and the parties can opt for liquidation of the collateral in the Bidding Period. +Once the `borrower` has withdrawn the loan amount, the Loan Period begins. Once the Loan Period is finished, the `borrower` is expected to repay the loan. If they do, the `lender` can then accept the repayment by revealing `secretB2`, enabling the borrower to refund their collateral amount. In the case that the `borrower` defaults or does not repay the full principal plus interest amount, the `lender` can choose to not accept the loan repayment, and the parties can opt for liquidation of the collateral in the Bidding Period. **Bidding Period:** -In the case of a default or the `lender` not accepting the `borrower` repayment, the `lender` and `borrower` can opt for liquidation of the collateral through the process of third party bidders bidding on the collateral. The Bidding Period can be initiated by either the `lender` or the `borrower`. Once the bidding timeout occurs, the `lender` and `borrower` must each provide a signature to allow the collateral to be withdrawn by the winning `bidder`. +In the case of a default or the `lender` not accepting the `borrower` repayment, the `lender` and `borrower` can opt for liquidation of the collateral through the process of third party bidders bidding on the collateral. The Bidding Period can be initiated by either the `lender` or the `borrower`. Once the bidding timeout occurs, the `lender` and `borrower` must each provide a signature, followed by `secretC` revealed by the winning `bidder` once they have checked that the signature is proper. Finally, the `lender` and `borrower` must each reveal `secretA2` and `secretB3` to allow the collateral to be withdrawn by the winning `bidder`. **Seizure Period:** -In the case that bidding is unsuccessful, the `lender` can seize a percentage of the collateral. The amount is dependent on the amount of collateral locked in the seizable script and refundable script as described in the BIP (https://github.com/mattBlackDesign/BIP). During this period the `borrower` can also refund the funds locked in the refundable script. +In the case that either the `lender` or `borrower` don’t accept the bid, the `lender` can seize a percentage of the collateral. The amount is dependent on the amount of collateral locked in the Seizable Collateral script and Refundable Collateral script as described in the BIP (https://github.com/atomicloans/bip). During this period the `borrower` can also refund the funds locked in the Refundable Collateral script. **Refund Period:** -In the case of a default where the `lender` does not seize the collateral locked in the seizable script, then the borrower can refund the funds locked in the seizablescript. +In the case of a default where the `lender` does not seize the collateral locked in the Seizable Collateral script, then the borrower can refund the funds locked in the Seizable Collateral script described in the BIP (https://github.com/atomicloans/bip). ## Specification @@ -322,7 +324,7 @@ ERC 1850 is compatible with [BIP ???](https://github.com/atomicloans/bip) for [a ## Implementation -This implementation is a simple example of a Hashed Time-Locked Atomic Loan Contract using Solidity +This implementation is a simple example of a HTLPC using Solidity https://github.com/AtomicLoans/ethereum-contracts/blob/master/contracts/AtomicLoan.sol @@ -541,7 +543,7 @@ contract AtomicLoan { } ``` -Note other hash functions can also be used, such as `keccak256`, `ripemd160`. However both parties should specify the hash function to be used before the Hashed Time-Locked Atomic Loan Contract is initialized. +Note other hash functions can also be used, such as `keccak256`, `ripemd160`. However both parties should specify the hash function to be used before the HTLPC is initialized. ## Copyright From e1996c02735fa0ab61c38ff9209ef3f46cc5e47f Mon Sep 17 00:00:00 2001 From: Matthew Black Date: Thu, 28 Mar 2019 04:15:45 -0400 Subject: [PATCH 6/9] Add references and remove solidity implementation --- EIPS/eip-1850.md | 228 ++++------------------------------------------- 1 file changed, 15 insertions(+), 213 deletions(-) diff --git a/EIPS/eip-1850.md b/EIPS/eip-1850.md index 88336f05a455fe..58ea7b023e78ab 100644 --- a/EIPS/eip-1850.md +++ b/EIPS/eip-1850.md @@ -22,7 +22,7 @@ A Hashed Time-Locked Principal Contract (HTLPC) is a script that permits a desig HTLPC transactions are a safe method for exchanging multiple secrets for the purposes of executing a cross-chain debt agreement, due to the ability to recover a percentage of funds from an uncooperative counterparty. -HLTPC's enable cross-chain [atomic loans](https://arxiv.org/pdf/1901.05117.pdf) +HLTPC's enable cross-chain atomic loans ## Definitions @@ -328,222 +328,24 @@ This implementation is a simple example of a HTLPC using Solidity https://github.com/AtomicLoans/ethereum-contracts/blob/master/contracts/AtomicLoan.sol -```js -pragma solidity ^0.4.25; - -contract AtomicLoan { - using SafeMath for uint256; - - address borrower; - address lender; - address bidder; - - bytes32 secretHashA1; - bytes32 secretHashA2; - bytes32 secretHashB1; - bytes32 secretHashB2; - bytes32 secretHashB3; - bytes32 secretHashC; - - bytes32 public secretA2; - bytes32 public secretB2; - bytes32 public secretB3; - bytes32 public secretC; - - uint256 approveExpiration; - uint256 loanExpiration; - uint256 acceptExpiration; - uint256 biddingExpiration; - - uint256 biddingTimeout; - uint256 biddingRefund; - - uint256 public principal; - uint256 public interest; - uint256 public liquidationFee; - - bool public funded = false; - bool public approved = false; - bool public withdrawn = false; - bool public bidding = false; - bool public repaid = false; - - uint256 currentBid = 0; - uint256 biddingTimeoutExpiration; - uint256 biddingRefundExpiration; - - string public borrowerSignature; - string public lenderSignature; - - bool liquidatedCollateralWidthdrawn = false; - - string aCoinAddress; - - StandardToken public token; - - constructor ( - bytes32 _secretHashA1, - bytes32 _secretHashA2, - bytes32 _secretHashB1, - bytes32 _secretHashB2, - bytes32 _secretHashB3, - uint256 _approveExpiration, - uint256 _loanExpiration, - uint256 _acceptExpiration, - uint256 _biddingExpiration, - address _borrower, - uint256 _principal, - uint256 _interest, - uint256 _liquidationFee, - uint256 _biddingTimeout, - uint256 _biddingRefund, - address _tokenAddress - ) public { - secretHashA1 = _secretHashA1; - secretHashA2 = _secretHashA2; - secretHashB1 = _secretHashB1; - secretHashB2 = _secretHashB2; - secretHashB3 = _secretHashB3; - approveExpiration = _approveExpiration; - loanExpiration = _loanExpiration; - acceptExpiration = _acceptExpiration; - biddingExpiration = _biddingExpiration; - borrower = _borrower; - lender = msg.sender; - principal = _principal; - interest = _interest; - liquidationFee = _liquidationFee; - biddingTimeout = _biddingTimeout; - biddingRefund = _biddingRefund; - token = StandardToken(_tokenAddress); - } +Note other hash functions can also be used, such as `keccak256`, `ripemd160`. However both parties should specify the hash function to be used before the HTLPC is initialized. - function fund () public { - require(funded == false); - token.transferFrom(msg.sender, address(this), principal); - funded = true; - } - - function approve (bytes32 _secretB1) public { - require(funded == true); - require(sha256(abi.encodePacked(_secretB1)) == secretHashB1); - require(now <= approveExpiration); - approved = true; - } - - function withdraw (bytes32 _secretA1, bytes32 _secretB1) public { - require(funded == true); - require(approved == true); - require(sha256(abi.encodePacked(_secretA1)) == secretHashA1); - require(sha256(abi.encodePacked(_secretB1)) == secretHashB1); - token.transfer(borrower, token.balanceOf(address(this))); - withdrawn = true; - } +## References - function accept_or_cancel (bytes32 _secretB2) public { - require(sha256(abi.encodePacked(_secretB2)) == secretHashB2); - require(now > approveExpiration); - require(now <= acceptExpiration); - require(bidding == false); - token.transfer(lender, token.balanceOf(address(this))); - selfdestruct(lender); - } - - function payback () public { - require(withdrawn == true); - require(now <= loanExpiration); - require(msg.sender == borrower); - token.transferFrom(borrower, address(this), principal.add(interest)); - repaid = true; - } +**Papers** - function refundPayback () public { - require(now > acceptExpiration); - require(repaid == true); - require(msg.sender == borrower); - token.transfer(borrower, token.balanceOf(address(this))); - selfdestruct(borrower); - } - - function startBidding () public { - require(repaid == false); - require(withdrawn == true); - require(now > loanExpiration); - require(msg.sender == borrower || msg.sender == lender); - biddingTimeoutExpiration = now.add(biddingTimeout); - biddingRefundExpiration = biddingTimeoutExpiration.add(biddingRefund); - bidding = true; - } - - function bid (bytes32 _secretHashC, uint256 _bidValue, string _aCoinAddress) public { - require(bidding == true); - require(now > loanExpiration); - require(now <= biddingTimeoutExpiration); - require(_bidValue > currentBid); - require(token.balanceOf(msg.sender) >= _bidValue); - token.transferFrom(msg.sender, address(this), _bidValue); - if (currentBid > 0) { - token.transfer(bidder, currentBid); - } - bidder = msg.sender; - currentBid = _bidValue; - secretHashC = _secretHashC; - aCoinAddress = _aCoinAddress; - } - - function provideSignature (string memory _signature) public { - require(now > loanExpiration); // Is this needed? - if (msg.sender == borrower) { - borrowerSignature = _signature; - } else if (msg.sender == lender) { - lenderSignature = _signature; - } else { - revert(); - } - } - - function provideSecret (bytes32 _secret) public { - require(now > loanExpiration); - if (msg.sender == borrower) { - require(sha256(abi.encodePacked(_secret)) == secretHashA2); - secretA2 = _secret; - } else if (msg.sender == lender) { - require(sha256(abi.encodePacked(_secret)) == secretHashB3); - secretB3 = _secret; - } else if (msg.sender == bidder) { - require(sha256(abi.encodePacked(_secret)) == secretHashC); - secretC = _secret; - } else { - revert(); - } - } - - function withdrawLiquidatedCollateral (bytes32 _secretA2, bytes32 _secretB3, bytes32 _secretC) public { - require(now > biddingTimeoutExpiration); - require(sha256(abi.encodePacked(_secretA2)) == secretHashA2); - require(sha256(abi.encodePacked(_secretB3)) == secretHashB3); - require(sha256(abi.encodePacked(_secretC)) == secretHashC); - require(msg.sender == borrower || msg.sender == lender); - if (currentBid > (principal.add(interest).add(liquidationFee))) { - token.transfer(lender, (principal.add(interest).add(liquidationFee))); - token.transfer(borrower, token.balanceOf(address(this))); - } else { - token.transfer(lender, currentBid); - } - selfdestruct(lender); - } - - function refundBid () public { - require(now > biddingRefundExpiration); - require(sha256(abi.encodePacked(secretC)) != secretHashC || sha256(abi.encodePacked(secretA2)) != secretHashA2 || sha256(abi.encodePacked(secretB3)) != secretHashB3); - require(currentBid > 0); - token.transfer(bidder, currentBid); - selfdestruct(lender); - } -} -``` +1. Atomic Loans: Cryptocurrency Debt Instruments Paper. https://arxiv.org/pdf/1901.05117.pdf +1. Atomic Cross-Chain Swaps. https://arxiv.org/pdf/1801.09515.pdf +1. Atomic Swaptions: Cryptocurrency Derivatives. https://www.ics.uci.edu/~jamesal1/Swaptions.pdf -Note other hash functions can also be used, such as `keccak256`, `ripemd160`. However both parties should specify the hash function to be used before the HTLPC is initialized. +**Standards** + +1. ERC-1630 Hashed Time-Locked Contract Standard (HTLC). https://github.com/ethereum/EIPs/pull/1630 +1. BIP ??? Hashed Time-Locked Collateral Contract Standard (HTLCC) https://github.com/bitcoin/bips/pull/773 + +**Discussions** + +1. Jimmy Song Off Chain HTLCC Q&A: https://youtu.be/ezRDcvkiff0?t=162 ## Copyright From 66511fffc6351aef538fc8da8642a296369fe2d7 Mon Sep 17 00:00:00 2001 From: Matthew Black Date: Thu, 28 Mar 2019 04:23:14 -0400 Subject: [PATCH 7/9] Add interface for atomicloans contract --- EIPS/eip-1850.md | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/EIPS/eip-1850.md b/EIPS/eip-1850.md index 58ea7b023e78ab..4e67176728e479 100644 --- a/EIPS/eip-1850.md +++ b/EIPS/eip-1850.md @@ -13,7 +13,6 @@ created: 2019-03-19 This EIP describes a script for a generalized debt agreement contract based on Hashed Time-Lock Contract (ERC 1630) transactions according to the Atomic Loans specification (https://arxiv.org/pdf/1901.05117.pdf). - ## Abstract A Hashed Time-Locked Principal Contract (HTLPC) is a script that permits a designated party (the "lender") to provide ERC20 denominated funds for a debt agreement for a specified amount of time, with collateral locked on another blockchain (denoted as the collateral blockchain for the purposes of this EIP). It also permits a second party (the "borrower") to withdraw the lent funds once their request to borrow has been approved by the lender, repay the loan after the loan period has passed and in the case of default, liquidate the collateral. @@ -320,7 +319,7 @@ function refundBid () public { ## Compatibility -ERC 1850 is compatible with [BIP ???](https://github.com/atomicloans/bip) for [atomic loans](https://arxiv.org/pdf/1901.05117.pdf) with Bitcoin and other HTLC compatible chains. +ERC 1850 is compatible with [BIP ???](https://github.com/bitcoin/bips/pull/773) for atomicloans with Bitcoin and other HTLC compatible chains. ## Implementation @@ -328,6 +327,43 @@ This implementation is a simple example of a HTLPC using Solidity https://github.com/AtomicLoans/ethereum-contracts/blob/master/contracts/AtomicLoan.sol +```js +pragma solidity ^0.5.0; + +contract AtomicLoan { + constructor ( + bytes32 _secretHashA1, + bytes32 _secretHashA2, + bytes32 _secretHashB1, + bytes32 _secretHashB2, + bytes32 _secretHashB3, + uint256 _approveExpiration, + uint256 _loanExpiration, + uint256 _acceptExpiration, + uint256 _biddingExpiration, + address _borrower, + uint256 _principal, + uint256 _interest, + uint256 _liquidationFee, + uint256 _biddingTimeout, + uint256 _biddingRefund, + address _tokenAddress + ); + function fund () public; + function approve (bytes32 _secretB1) public; + function withdraw (bytes32 _secretA1, bytes32 _secretB1); + function accept_or_cancel (bytes32 _secretB2) public; + function payback () public; + function refundPayback () public; + function startBidding () public; + function bid (bytes32 _secretHashC, uint256 _bidValue, string _aCoinAddress) public; + function provideSignature (string memory _signature) public; + function provideSecret (bytes32 _secret) public; + function withdrawLiquidatedCollateral (bytes32 _secretA2, bytes32 _secretB3, bytes32 _secretC) public; + function refundBid () public; +} +``` + Note other hash functions can also be used, such as `keccak256`, `ripemd160`. However both parties should specify the hash function to be used before the HTLPC is initialized. ## References From c85561b0661d64de981b5c37bd2b03a39edb928c Mon Sep 17 00:00:00 2001 From: Matthew Black Date: Thu, 28 Mar 2019 04:25:46 -0400 Subject: [PATCH 8/9] Add ERC20 standard to references --- EIPS/eip-1850.md | 1 + 1 file changed, 1 insertion(+) diff --git a/EIPS/eip-1850.md b/EIPS/eip-1850.md index 4e67176728e479..b9f0bc202faa43 100644 --- a/EIPS/eip-1850.md +++ b/EIPS/eip-1850.md @@ -376,6 +376,7 @@ Note other hash functions can also be used, such as `keccak256`, `ripemd160`. Ho **Standards** +1. ERC-20 Token Standard. https://eips.ethereum.org/EIPS/eip-20 1. ERC-1630 Hashed Time-Locked Contract Standard (HTLC). https://github.com/ethereum/EIPs/pull/1630 1. BIP ??? Hashed Time-Locked Collateral Contract Standard (HTLCC) https://github.com/bitcoin/bips/pull/773 From e55f3a327783e3ff2166a4b90a3228293b086799 Mon Sep 17 00:00:00 2001 From: Matthew Black Date: Sat, 30 Mar 2019 11:01:35 -0400 Subject: [PATCH 9/9] Update BIP info to reflect BIP 197 --- EIPS/eip-1850.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/EIPS/eip-1850.md b/EIPS/eip-1850.md index b9f0bc202faa43..7cb4fa93c69c07 100644 --- a/EIPS/eip-1850.md +++ b/EIPS/eip-1850.md @@ -78,7 +78,7 @@ HLTPC's enable cross-chain atomic loans **Approve Period:** -During this time, the `lender` deploys the HTLPC. Following this, the borrower locks their collateral on the collateral blockchain in a Hashed Time-Locked Collateral Contract (HTLCC) (Bitcoin version specified here: https://github.com/atomicloans/BIP). The `lender` then either reveals `secretB1` to signify that they are satisfied with the collateral, and the borrower can withdraw the loan by revealing `secretA1`. If the `lender` is not satisfied with the collateral locked by the `borrower`, the `lender` can refunds their loan amount by revealing `secretB2`, which will subsequently allow the borrower to refund the collateral amount they deposited. +During this time, the `lender` deploys the HTLPC. Following this, the borrower locks their collateral on the collateral blockchain in a Hashed Time-Locked Collateral Contract (HTLCC) (Bitcoin version specified here: https://github.com/bitcoin/bips/blob/master/bip-0197.mediawiki). The `lender` then either reveals `secretB1` to signify that they are satisfied with the collateral, and the borrower can withdraw the loan by revealing `secretA1`. If the `lender` is not satisfied with the collateral locked by the `borrower`, the `lender` can refunds their loan amount by revealing `secretB2`, which will subsequently allow the borrower to refund the collateral amount they deposited. **Loan Period:** Once the `borrower` has withdrawn the loan amount, the Loan Period begins. Once the Loan Period is finished, the `borrower` is expected to repay the loan. If they do, the `lender` can then accept the repayment by revealing `secretB2`, enabling the borrower to refund their collateral amount. In the case that the `borrower` defaults or does not repay the full principal plus interest amount, the `lender` can choose to not accept the loan repayment, and the parties can opt for liquidation of the collateral in the Bidding Period. @@ -87,10 +87,10 @@ Once the `borrower` has withdrawn the loan amount, the Loan Period begins. Once In the case of a default or the `lender` not accepting the `borrower` repayment, the `lender` and `borrower` can opt for liquidation of the collateral through the process of third party bidders bidding on the collateral. The Bidding Period can be initiated by either the `lender` or the `borrower`. Once the bidding timeout occurs, the `lender` and `borrower` must each provide a signature, followed by `secretC` revealed by the winning `bidder` once they have checked that the signature is proper. Finally, the `lender` and `borrower` must each reveal `secretA2` and `secretB3` to allow the collateral to be withdrawn by the winning `bidder`. **Seizure Period:** -In the case that either the `lender` or `borrower` don’t accept the bid, the `lender` can seize a percentage of the collateral. The amount is dependent on the amount of collateral locked in the Seizable Collateral script and Refundable Collateral script as described in the BIP (https://github.com/atomicloans/bip). During this period the `borrower` can also refund the funds locked in the Refundable Collateral script. +In the case that either the `lender` or `borrower` don’t accept the bid, the `lender` can seize a percentage of the collateral. The amount is dependent on the amount of collateral locked in the Seizable Collateral script and Refundable Collateral script as described in the BIP (https://github.com/bitcoin/bips/blob/master/bip-0197.mediawiki). During this period the `borrower` can also refund the funds locked in the Refundable Collateral script. **Refund Period:** -In the case of a default where the `lender` does not seize the collateral locked in the Seizable Collateral script, then the borrower can refund the funds locked in the Seizable Collateral script described in the BIP (https://github.com/atomicloans/bip). +In the case of a default where the `lender` does not seize the collateral locked in the Seizable Collateral script, then the borrower can refund the funds locked in the Seizable Collateral script described in the BIP (https://github.com/bitcoin/bips/blob/master/bip-0197.mediawiki). ## Specification @@ -319,7 +319,7 @@ function refundBid () public { ## Compatibility -ERC 1850 is compatible with [BIP ???](https://github.com/bitcoin/bips/pull/773) for atomicloans with Bitcoin and other HTLC compatible chains. +ERC 1850 is compatible with [BIP 197](https://github.com/bitcoin/bips/blob/master/bip-0197.mediawiki) for atomicloans with Bitcoin and other HTLC compatible chains. ## Implementation @@ -378,7 +378,7 @@ Note other hash functions can also be used, such as `keccak256`, `ripemd160`. Ho 1. ERC-20 Token Standard. https://eips.ethereum.org/EIPS/eip-20 1. ERC-1630 Hashed Time-Locked Contract Standard (HTLC). https://github.com/ethereum/EIPs/pull/1630 -1. BIP ??? Hashed Time-Locked Collateral Contract Standard (HTLCC) https://github.com/bitcoin/bips/pull/773 +1. BIP 197 Hashed Time-Locked Collateral Contract Standard (HTLCC) https://github.com/bitcoin/bips/blob/master/bip-0197.mediawiki **Discussions**