# Sapio for Fun (and Profit)

In this section, we're going to build a simple option contract. This sort of contract could be used, for example, to make an on-chain asynchronous offer to someone to enter a bet with you.

Then, you'll have some challenges to modify the contract to extend it's functionality meaningfully.

The logic for the basic contract is as follows:

1. If $$\tau_{now} > \tau_{timeout}$$:
• send funds to return address
2. If strike_price btc are added:
• send funds + strike_price to strike_into contract

#![allow(unused)]
fn main() {
/// The Data Fields required to create a on-chain bet
pub struct UnderFundedExpiringOption {
/// How much money has to be paid to strike the contract
strike_price: Amount,
/// if the contract expires, where to return the money
return_address: bitcoin::Address,
/// if the contract strikes, where to send the money
strike_into: Box<dyn Compilable>,
/// the timeout (as an absolute time) when the contract should end.
timeout: AnyAbsTimeLock,
}

impl UnderFundedExpiringOption {
#[then]
/// return the funds on expiry
fn expires(self, ctx: Context) {
ctx.template()
// set the timeout for this path -- because it is using
// then! we do not require a guard.
.set_lock_time(self.timeout)?
.add_output(
// ctx.funds() knows how much money has been sent to this contract
ctx.funds(),
// this bootstraps an address into a contract object
&Compiled::from_address(self.return_address.clone(), None),
None,
)?
.into()
}
/// continue the contract
#[then]
fn strikes(self, ctx: Context) {
let tmpl = ctx.template().add_amount(self.strike_price);
let amt = (tmpl.ctx().funds() + self.strike_price).into();
tmpl.add_sequence()
.add_output(
// use the inner context of tmpl because it has added funds
amt,
self.strike_into.as_ref(),
None,
)?
.into()
}
}

impl Contract for UnderFundedExpiringOption {
declare!(then, Self::expires, Self::strikes);
declare!(non updatable);
}
}


# Challenges

There's no right answer to the following challenges, and the resulting contract may not be too useful, but it should be a good exercise to learn more about writing Sapio contracts.

1. Clear out your helloworld plugin and put this code in.
2. Write a contract designed to be put into the strike_into field which sends funds to one party or the other based on a third-party revealing a hash preimage A or B.
3. Modify the contract so that there is a expire_A and a expire_B path that go to different addresses, and expire_A requires a signature or hash reveal to be taken.
4. Modify the contract so that if expire_A is taken, a small payout early_exit_fee: bitcoin::Address is made to a early_exit : bitcoin::Address.
5. Modify the contract so that expire_A is only present the fields required by it are Option::is_some (hint: use compile_if!).
6. Add logic to deduct fees.
7. Add a cooperative_close guard! clause that allows both parties to exit gracefully