⌘K

Icon SunFilledIcon MoonStars

Icon LinkPayback

To beat this level, you'll need to trick the contract into sending you all its funds.

contract;
 
use std::{
    asset::transfer,
    auth::msg_sender,
    constants::BASE_ASSET_ID,
    context::{
        msg_amount,
        this_balance,
    },
    logging::log,
};
 
abi MyContract {
    #[payable, storage(write)]
    fn send_funds();
 
    #[payable, storage(read)]
    fn pay_back();
 
    #[storage(read)]
    fn attack_success() -> bool;
}
 
storage {
    has_initial_funds: bool = false,
}
 
impl MyContract for Contract {
    #[payable, storage(write)]
    fn send_funds() {
       let contract_balance = this_balance(BASE_ASSET_ID);
        if contract_balance > 0 {
            storage.has_initial_funds.write(true);
        }
    }
 
    #[payable, storage(read)]
    fn pay_back() {
        let sender = msg_sender().unwrap();
        let amount = msg_amount();
        let contract_balance = this_balance(BASE_ASSET_ID);
        let previous_balance = contract_balance - amount;
        let intial_funds = storage.has_initial_funds.try_read().unwrap();
        if intial_funds == true {
            if amount > previous_balance {
                transfer(sender, BASE_ASSET_ID, contract_balance);
            }
        }
    }
 
    #[storage(read)]
    fn attack_success() -> bool{
        let intial_funds = storage.has_initial_funds.try_read().unwrap();
        require(intial_funds == true, 333);
        let contract_balance = this_balance(BASE_ASSET_ID);
        require(contract_balance == 0, 555);
        true
    }
}