Skip to main content

Challenge 6: Go Recycle!

The City of Venice is tired of all the trash ending up in the canals, especially pizza boxes still filled with a certain type of pizza which are just dumped everywhere are ruining the experience. They decided to start a recycling program rewarding people who do their part with a Venetian Flag; Go grab one!

For this challenge you might want to investigate the Transfer to object functionality; Pizzaboxes from previous challenges can not be used in this one.

Deployed Contract Addresses:

PizzaBoxRecycler: 0x8c23295c9844f10a7f3809d0a31bca68094bd867e4da35b8ab4d1166a017b383
Package: 0x5b3571ccaf942310691ca034fbfa381ccd724029396e329910a789b1d25ece3d

Contracts

recycle.move

module ctf::recycle {
use iota::transfer::{Receiving};
use iota::dynamic_field as df;
use ctf::pizza::{Self, PizzaBox};

const ENoPizzaBoxProvidedEver: u64 = 1;
const ENotEnoughRecycledYet: u64 = 2;
const ENoRecyclingNeededJustEatIt: u64 = 3;

public struct PizzaBoxRecycler has key {
id: object::UID
}

public struct PizzaPointBalance has store {
amount: u64
}

public struct Flag has key, store {
id: UID,
user: address
}

fun init (ctx: &mut TxContext) {
transfer::share_object(
PizzaBoxRecycler {
id: object::new(ctx)
}
);
}

public fun accept_box(recycler: &mut PizzaBoxRecycler, disposed: Receiving<PizzaBox>, ctx: &mut TxContext) {
let sender = tx_context::sender(ctx);
let box = transfer::public_receive(&mut recycler.id, disposed);

assert!(pizza::has_pineapple_traces(&box), ENoRecyclingNeededJustEatIt);

if (df::exists_(&recycler.id, sender)) {
let balance: &mut PizzaPointBalance = df::borrow_mut(&mut recycler.id, sender);
balance.amount = balance.amount + 1
} else {
df::add(&mut recycler.id, sender, PizzaPointBalance { amount: 1 });
};

pizza::recycle_box(box);
}

#[allow(lint(self_transfer))]
public fun get_flag(recycler: &mut PizzaBoxRecycler, ctx: &mut TxContext) {
let sender = tx_context::sender(ctx);
// Make sure what we are withdrawing exists
assert!(df::exists_(&recycler.id, sender), ENoPizzaBoxProvidedEver);
let balance: &mut PizzaPointBalance = df::borrow_mut(&mut recycler.id, sender);
assert!(balance.amount > 2, ENotEnoughRecycledYet);
transfer::public_transfer(Flag {
id: object::new(ctx),
user: tx_context::sender(ctx)
}, tx_context::sender(ctx));
}
}

pizza.move

module ctf::pizza {

public struct Pizza has key, store {
id: UID,
olive_oils: u16,
yeast: u16,
flour: u16,
water: u16,
salt: u16,
tomato_sauce: u16,
cheese: u16,
pineapple: u16,
}

public struct PizzaBox has key, store {
id: UID,
pizza: Pizza,
}

#[allow(lint(self_transfer))]
public fun cook(olive_oils: u16, yeast: u16, flour: u16, water: u16, salt: u16, tomato_sauce: u16, cheese: u16, pineapple: u16, ctx: &mut tx_context::TxContext) {
let sender = tx_context::sender(ctx);

let p = Pizza {
id: object::new(ctx),
olive_oils,
yeast,
flour,
water,
salt,
tomato_sauce,
cheese,
pineapple,
};

transfer::public_transfer(PizzaBox { id: object::new(ctx), pizza: p }, sender);
}

public fun has_pineapple_traces(box: &PizzaBox):bool {
box.pizza.pineapple > 0
}

public fun recycle_box(box: PizzaBox) {
let PizzaBox {id, pizza} = box;
let Pizza {id: pid, olive_oils: _, yeast: _, flour: _, water: _, salt: _, tomato_sauce: _, cheese: _, pineapple: _} = pizza;

object::delete(pid);
object::delete(id);
}
}

The previous challenges covered the basics of the Object Model and how to interact with the blockchain. This challenge's main theme is object transfers, which will be crucial to capturing the flag. We recommend you to check the following articles:

Good luck in capturing your sixth flag!

tip

Make sure you recycle enough pizza boxes!