---
tags: Projects
---
# Swap
:::info
**Released:** April 27th, 11:59pm EST
**Due:** May 6th, 11:59pm EST
:::
## Introduction
You've now worked across several different aspects of blockchains. First, you implemented a blockchain storage solution in Chain. Then, you added a consensus mechanism in Coin, allowing us to run a fully (mostly?) functioning cryptocurrency. Lastly, you implemented a scaling solution in Lightning.
Now, it's time to dip your toes into smart contracts and cross-chain commerce. If you haven't already completed the [**Solidity lab**](https://hackmd.io/@cs1951l-2023/solidity), do that first. It covers Hardhat installation, which is required for this project.
#### Important Concepts
Before we begin, it's worth reviewing some of the foundations for this project.
* **Escrowing:** In standard finance, escrow accounts are owned by third parties to hold assets until some condition is fulfilled. In blockchain finance, those third parties are smart contracts. Putting those together, escrowing an asset on a blockchain means transferring custody to a smart contract until some condition is fulfilled.
* **Cross-Chain Commerce:** Cross-chain commerce allows us to make financial exchanges across multiple blockchains that cannot communicate with each other. For example, we could have cross-chain commerce by using the incompatible Bitcoin and Ethereum chains (although any such implementation wouldn't be feature-rich, as Bitcoin lacks smart contracts)
* **Hashlocks:** hashlocks are the backbone of many smart contracts. I'm free to publish $H(S)$ as far and wide as I like, since nobody will be able to reverse-engineer $S$. The fulfillment condition for releasing an escrowed asset is providing $S$, which the contract can quickly verify hashes to $H(S)$.
### Hedging Against Sore Lose Attacks
Here's the [**original paper**](https://arxiv.org/pdf/2105.06322.pdf) describing the protocol we'll cover below. You should read up until the start of Section 6, which is a total of just under 4 pages. If you do not, you likely will not understand the purpose of this protocol: limiting the impact of sore loser attacks.
:::info
**Sore loser attack:**
When one party decides to halt participation in cross-chain commerce partway through a protocol, leaving the other parties’ assets locked up for a long duration (Xue, 2021).
:::
### The Protocol
In this example, Alice sets up a cross-chain swap with Bob. She owns Apricots and he owns Bananas. She wants to trade some of her Apricots for some of his Bananas.
Some of the communication between Alice and Bob must happen off chain, such as Alice telling Bob the hashLock for the swaps. For simplicity's sake, the protocol only depicts on-chain communication, which is the part that you will be implementing.
#### Notation
**P_a:** Alice's premium amount
**P_b:** Bob's premium amount
**A_a:** Alice's asset amount
**A_b:** Bob's asset amount
**s:** the secret used to create the hash lock
**H(s):** the hash lock
```sequence
Title: If everything goes as expected...
participant Alice as A
participant Apricot Chain as AC
participant Banana Chain as BC
participant Bob as B
A -> BC: (1) setup BananaSwap with H(s)
A -> AC: (2) setup ApricotSwap with H(s)
Note over A, B: Entering premium escrowing phase
A -> BC: (3) escrow P_a + P_b
B -> AC: (4) escrow P_b
Note over A, B: Entering asset escrowing phase
A -> AC: (5) escrow A_a
B -> BC: (6) escrow A_b
Note over A, B: Entering redemption phase
A -> BC: (7) redeem A_b with s & refund P_a + P_b
B -> AC: (8) redeem A_a with s & refund P_b
```
#### Steps Explained
**(1 & 2)** Alice must first set up the swap contracts. She will create a `BananaSwap` on the BananaChain and an `ApricotSwap` on the ApricotChain. Both will have the same hashLock $H(S)$, but only Alice knows the secret $S$.
**Note:** A participant in this protocol escrows their premium on the chain of the asset they'd like to receive. That means that Alice and Bob must each own both assets. In this case, that means they both must own some `Apricot` and some `Banana`.
**(3)** As the initiator, Alice has to escrow an amount equal to her premium + Bob's premium on the `BananaChain`. This might surprise you, as we'd expect her to only have to pay the amount totalling her premium. The reason for this is covered in Section 5.2 of the [**original paper**](https://arxiv.org/pdf/2105.06322.pdf).
**(4)** Having seen Alice successfully escrow her premium on the `BananaChain`, Bob now escrows his premium on the `ApricotChain`.
**(5)** Now that both parties have escrowed their premiums, we enter the asset escrowing phase. If either party disappears at this point, they'll lose their premium! Alice escrows her Apricots on the `ApricotChain`.
**(6)** Having seen Alice correctly escrow her Apricots, Bob follows suit by escrowing his Bananas on the `BananaChain`.
**(7)** Alice sees that Bob's bananas are correctly escrowed, so now she gets to redeem them! Doing so requires her to reveal the secret $S$. She should also get her premium refunded, since she followed the specifications of the protocol.
**(8)** Since Alice had to reveal $S$ to collect her Bananas, Bob now knows the secret! Using $S$, he can collect his Apricots and have his premium P_b refunded.
**FIN.**
```sequence
Title: If Bob disappers...
participant Alice as A
participant Apricot Chain as AC
participant Banana Chain as BC
participant Bob as B
A -> BC: (1) setup BananaSwap with H(s)
A -> AC: (2) setup ApricotSwap with H(s)
Note over A, B: Entering premium escrowing phase
A -> BC: (3) escrow P_a + P_b
B -> AC: (4) escrow P_b
Note over A, B: Entering asset escrowing phase
A -> AC: (5) escrow A_a
B --> BC: (6) ZZZ ZZZ ZZZ
Note over A, B: Entering redemption phase
A -> AC: (7) redeem P_b & refund A_a
A -> BC: (8) refund P_b + P_a
```
#### Steps Explained
**(1-5)** Ommited. See explanations above.
**(6)** Bob is nowhere to be found. He must be sleeping...
**(7)** Since Bob missed his deadline to escrow his asset, Alice collects his premium deposited on the `ApricotChain`. She will also get her asset refunded.
**(8)** Alice must also get her own premium refunded, which was escrowed on the `BananaChain`
**FIN.**
```sequence
Title: Bob never escrows his premium...
participant Alice as A
participant Apricot Chain as AC
participant Banana Chain as BC
participant Bob as B
A -> BC: (1) setup BananaSwap with H(s)
A -> AC: (2) setup ApricotSwap with H(s)
Note over A, B: Entering premium escrowing phase
A -> BC: (3) escrow P_a + P_b
B -> AC: (4) ZZZ ZZZ
Note over A, B: Entering redemption phase
A -> BC: (5) refund P_b + P_a
```
**(1-3)** Ommited. See explanations above.
**(4)** Bob is nowhere to be found. He must be sleeping...
**(5)** Shoot! Alice doesn't get anything from this interaction. All she can do is get her initial premium refunded. She won't be doing any business with Bob again...
**FIN.**
## Assignment
:::info
**Important caveat:**
The protocol above uses two distinct chains, but we're only using Solidity and the Ethereum chain for this project. Ethereum has the best testing support, and it prevents you from having to learn multiple languages for this project.
We'll be implementing all of the various calls above, since a person could be either the initiator or follower on either chain.
While **in theory** you're implementing a **cross-chain swap**, **in reality** you're implementing an **ERC20 swap** with a protocol that would work across distinct chains.
:::
For this assignment, you will implement the functions listed below. We recommend that you tackle them in the following order:
1. `setup`
2. `escrowPremium`
3. `escrowAsset`
4. `redeemAsset`
5. `refundAsset`
6. `redeemPremium`
7. `refundPremium`
All functions are worth (roughly) the same amount. Check out our [grading breakdown](##Grading) for more info.
Some general hints:
* We recommend that you put all of your require statements in a modifier, which is currently blank.
* Remember that an event should be emitted after a function executes.
#### Implement:
```solidity=
/**
setup is called to initialize an instance of a swap in this contract.
Due to storage constraints, the various parts of the swap are spread
out between the three different mappings above: swaps, assets,
and premiums.
*/
function setup(
uint expectedAssetEscrow,
uint expectedPremiumEscrow,
address payable assetEscrower,
address payable premiumEscrower,
address assetName,
bytes32 hashLock,
uint startTime,
bool firstAssetEscrow,
uint delta
)
public
payable
canSetup(hashLock)
{}
```
#### Overview
* This function instantiates an instance of a swap (for one side of the protocol).
* You should prevent initiating duplicate swap by setting certain requirements. (hint: you can use zero address as "null")
* You'll want to instantiate the appropriate structs based on the arguments and then add those structs to their mappings.
* So what are the deadlines/timeouts that we have to set? That depends on whether that chain has the first asset escrow. The `delta` argument is an agreed-upon safe time interval for both parties, such that each interval is some `n * delta`, beginning from the `startTime`.
* In the first protocol sequence above, `firstAssetEscrow` is true on the `ApricotChain` and false on the `BananaChain` (since in the asset escrowing round the Apricots are escrowed prior to the Bananas). Thus, the deadline for the premium on the `BananaChain` (where `firstAssetEscrow` is false) is `startTime + 1 * delta`.
* The timeout for the swap is a time after which all possible events have occurred on a chain. Hint: look at the ApricotChain.
#### (Somewhat Hidden) Helpful Fields:
* `msg.sender`: the function's caller.
#### Implement:
```solidity=
/**
The premium escrower has to escrow their premium for
the protocol to succeed.
*/
function escrowPremium(bytes32 hashLock)
public
payable
canEscrowPremium(hashLock)
{}
```
#### Hint
* Before you begin, you should require a few things to be true.
* Set relevant field(s) in this swap's premium struct demonstrating you've taken this step.
#### Helpful Functions
* ERC20's `transfer` or `transferFrom`? Go back to HW 3 for a refresher.
* ERC20's `balanceOf`
#### Implement:
```solidity=
/**
The asset escrower has to escrow their premium for
the protocol to succeed.
*/
function escrowAsset(bytes32 hashLock)
public
payable
canEscrowAsset(hashLock)
{}
```
#### Hint
* Don't forget requirements!
#### Implement:
```solidity=
/**
redeemAsset redeems the asset for the new owner.
*/
function redeemAsset(bytes32 preimage, bytes32 hashLock)
public
canRedeemAsset(preimage, hashLock)
{}
```
#### Hint
* How do we make sure if a token is being moved properly and reflected in structs?
#### Helpful Functions
* `sha256(abi.encode(message))`: how to get the SHA-256 hash of `message`
#### Implement:
```solidity=
/**
refundPremium refunds the premiumEscrower's premium
should the counterparty break from the protocol
*/
function refundPremium(bytes32 hashLock)
public
canRefundPremium(hashLock)
{}
```
#### Overview
* Ensure the order of the protocols.
#### Implement:
```solidity=
/**
refundAsset refunds the asset to its original owner
should the swap fail
*/
function refundAsset(bytes32 hashLock)
public
canRefundAsset(hashLock)
{}
```
#### Implement:
```solidity=
/**
redeemPremium allows a party to redeem the
counterparty's premium should the swap fail
*/
function redeemPremium(bytes32 hashLock)
public
canRedeemPremium(hashLock)
{}
```
## Testing
This assignment is autograded, and you are able to run our test suite as many time as you like. While you can run all of your tests on Gradescope, we strongly recommend that you test locally. That way, you can fail quickly and try again!
Hardhat allows us to log solidity variables, something that you cannot do normally. This means that you can use `console.log(message)` in your `.sol` files to log a message to standard output. This will save you a lot of frustration!
#### Testing Resources:
* [Solidity Documentation](https://docs.soliditylang.org/en/v0.8.12/)
* [Solidity By Example](https://solidity-by-example.org/)
* [Hardhat Documentation](https://hardhat.org/getting-started/)
* [Testing with Hardhat](https://hardhat.org/tutorial/testing-contracts.html)
* [Remix Documentation](https://remix-ide.readthedocs.io/en/latest/)
## Install
:::warning
This assignment requires a few steps prior to cloning the stencil. Please make sure you do those first!
:::
1. Clone the [stencil repo](https://classroom.github.com/a/LePg4npg).
2. To install the package dependencies, run `npm i`
3. Get after it! Good luck :smiley:
## HandIn
- Log into [Gradescope](https://www.gradescope.com/) and Submit your code using **GitHub**.
## Grading
:::warning
**Note:** This assignment's feedback form is a **REQUIRED** part of the assignment, worth 5 points.
The form can be found [here](https://forms.gle/B61GsjJ3h7AfojRq6).
:::
This assignment is out of **100 points**.
On Gradescope, each individual test is worth 1 point, for 38 total points. It was much easier to set up that way, so we'll adjust the scores later to match the rubric below.
### Rubric
| Test Suite | Points |
|:---------------- |:-------:|
| `Setup` | 14 |
| `Escrow Premium` | 13 |
| `Escrow Asset` | 14 |
| `Redeem Asset` | 14 |
| `Refund Asset` | 14 |
| `Redeem Premium` | 13 |
| `Refund Premium` | 13 |
| Feedback Form | 5 |
| **Total** | **100** |