I am attempting to build a smart contract for an imaginary burger shop. But I keep getting this error when I run the build command.
The test compiles, and cargo check
compiles successfully too.
Here is the source code.
#![cfg_attr(not(feature = "std"), no_std)]
#[ink::contract]
mod burger_shop {
use ink::prelude::*;
use ink::storage::Mapping;
use scale::{Decode, Encode};
#[ink(storage)]
pub struct BurgerShop {
orders: Vec<(u32, Order)>,
orders_mapping: Mapping<u32, Order>,
shop_owner: AccountId,
}
// TODO: add logic to calculate gas fees for user
#[derive(Encode, Decode, Debug, Clone)]
#[cfg_attr(
feature = "std",
derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout)
)]
pub struct Order {
burger_menu: String,
customer: AccountId,
price: u32,
amount: u32,
paid: bool,
delivered: bool,
status: Status,
completed: bool,
}
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum Error {
/// Provide a detailed comment on the error
PaymentError,
OrderNotCompleted,
}
// result type
pub type Result<T> = core::result::Result<T, Error>;
#[cfg_attr(
feature = "std",
derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout)
)]
#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq)]
pub enum Status {
GettingIngredients,
Preparing,
SentForDelivery,
Delivered,
}
impl Default for Status {
fn default() -> Self {
Status::GettingIngredients
}
}
impl BurgerShop {
#[ink(constructor)]
pub fn new() -> Self {
let list_of_orders = Mapping::new();
Self {
orders: vec![],
orders_mapping: list_of_orders,
shop_owner: Self::env().caller(),
}
}
#[ink(message)]
pub fn get_orders(&self) -> Vec<(u32, Order)> {
// ensure the call is from the shop owner
let caller = self.env().caller();
assert!(caller == self.shop_owner, "You are not the shop owner!");
self.orders.clone()
}
#[ink(message)]
pub fn new_order(&mut self, order: Order) {
let count = self.orders.len() as u32;
// ensure order is from the customer
let caller = self.env().caller();
assert!(caller == order.customer, "You are not the customer!");
// ensure that the order is not completed
assert!(
order.completed == false,
"Cant add an already completed order!"
);
self.orders_mapping.insert(count, &order);
self.orders.push((count, order));
}
#[ink(message)]
pub fn get_single_order(&self, id: u32) -> (u32, Order) {
let tuple_order = (id, self.orders_mapping.get(id).expect("Order not found!"));
tuple_order
}
#[ink(message)]
pub fn mark_completed(&mut self, id: u32) -> Result<()> {
let mut order = self.orders_mapping.get(id).expect("order not found!");
assert!(order.completed == false, "Order already completed!");
assert!(order.paid == true, "Order not paid!");
assert!(order.delivered == true, "Order not delivered!");
assert!(order.status == Status::Delivered, "Order not delivered!");
if order.paid && order.delivered && order.status == Status::Delivered {
order.completed = true;
Ok(())
} else {
Err(Error::OrderNotCompleted)
}
}
#[ink(message)]
pub fn make_payment(&mut self, id: u32) -> Result<()> {
let mut order = self.orders_mapping.get(id).expect("order not found!");
assert!(order.paid == false, "Order already paid!");
// ensure that sender is the caller
let caller = self.env().caller();
assert!(caller == order.customer, "You are not the customer!");
// ensure that the order is not completed
assert!(order.completed == false, "Order already completed!");
// ensure that the order is not delivered
assert!(order.delivered == false, "Order already delivered!");
// make payment
match self.env().transfer(self.shop_owner, order.price.into()) {
Ok(_) => {
order.paid = true;
order.status = Status::Preparing;
Ok(())
}
Err(_) => Err(Error::PaymentError),
}
}
#[ink(message)]
pub fn change_status(&mut self, id: u32, status: Status) {
let mut order = self.orders_mapping.get(id).expect("order not found!");
// ensure caller is the shop owner
let caller = self.env().caller();
assert!(caller == self.shop_owner, "You are not the shop owner!");
// ensure that the order is not completed
assert!(order.completed == false, "Order already completed!");
order.status = status;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[ink::test]
fn it_works() {
let mut burger_shop = BurgerShop::new();
let order = Order {
burger_menu: "Cheese Burger".to_string(),
customer: AccountId::from([0x01; 32]),
price: 100,
amount: 1,
paid: false,
delivered: false,
status: Status::GettingIngredients,
completed: false,
};
burger_shop.new_order(order.clone());
let orders = burger_shop.get_orders();
assert_eq!(orders.len(), 1);
}
}
}
What could I be doing wrong?
Here is the Cargo.toml file
[package]
name = "burger_shop"
version = "0.1.0"
authors = ["Ayomide Bajo <[email protected]>"]
edition = "2021"
[dependencies]
ink = { version = "4.0.1", default-features = false }
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true }
sp-io = "22.0.0"
[dev-dependencies]
ink_e2e = "4.0.1"
[lib]
path = "lib.rs"
[features]
default = ["std"]
std = [
"ink/std",
"scale/std",
"scale-info/std",
]
ink-as-dependency = []
e2e-tests = []
The rustup update && rustup default nightly && cargo build --release
run successfully but cargo contract build
still results in the same error
This is weird. cargo build
compiles but cargo contract build
doesn't.
If cargo contract build
command doesn't work for my smart contract I can't deploy it.
After removing sp-io from the .toml file.
rustup update && rustup default nightly && cargo build --release
cargo contract build
still gives the same error