starknet-devnet-core 0.4.2

Starknet core logic for devnet
use blockifier::state::state_api::StateReader;
use starknet_rs_core::types::Felt;
use starknet_types::contract_address::ContractAddress;
use starknet_types::contract_class::ContractClass;
use starknet_types::contract_class::deprecated::json_contract_class::Cairo0Json;
use starknet_types::felt::ClassHash;
use starknet_types::rpc::state::Balance;

use crate::error::DevnetResult;
use crate::state::state_readers::DictState;
use crate::state::{CustomState, StarknetState};
use crate::traits::{Accounted, Deployed};

pub(crate) struct SystemContract {
    class_hash: ClassHash,
    address: ContractAddress,
    contract_class: ContractClass,
}

impl SystemContract {
    pub(crate) fn new_cairo0(
        class_hash: Felt,
        address: Felt,
        contract_class_json_str: &str,
    ) -> DevnetResult<Self> {
        Ok(Self {
            class_hash,
            address: ContractAddress::new(address)?,
            contract_class: Cairo0Json::raw_json_from_json_str(contract_class_json_str)?.into(),
        })
    }

    pub(crate) fn new_cairo1(
        class_hash: ClassHash,
        address: Felt,
        contract_class_json_str: &str,
    ) -> DevnetResult<Self> {
        Ok(Self {
            class_hash,
            address: ContractAddress::new(address)?,
            contract_class: ContractClass::cairo_1_from_sierra_json_str(contract_class_json_str)?
                .into(),
        })
    }
}

impl Deployed for SystemContract {
    fn deploy(&self, state: &mut StarknetState) -> DevnetResult<()> {
        self.declare_if_undeclared(state, self.class_hash, &self.contract_class)?;
        state.predeploy_contract(self.address, self.class_hash)?;
        Ok(())
    }

    fn get_address(&self) -> ContractAddress {
        self.address
    }
}

impl Accounted for SystemContract {
    fn set_initial_balance(&self, _state: &mut DictState) -> DevnetResult<()> {
        Ok(())
    }

    fn get_balance(
        &self,
        _state: &mut impl StateReader,
        _token: crate::account::FeeToken,
    ) -> DevnetResult<Balance> {
        Ok(Balance::default())
    }
}

#[cfg(test)]
mod tests {
    use starknet_types::contract_class::ContractClass;

    use super::SystemContract;
    use crate::constants::{
        CAIRO_1_ERC20_CONTRACT, CAIRO_1_ERC20_CONTRACT_CLASS_HASH, ETH_ERC20_CONTRACT_ADDRESS,
    };
    use crate::state::StarknetState;
    use crate::traits::Deployed;

    #[test]
    fn load_erc20_contract() {
        assert!(ContractClass::cairo_1_from_sierra_json_str(CAIRO_1_ERC20_CONTRACT).is_ok());
    }

    #[test]
    fn system_account_deployed_successfully() {
        let mut state = StarknetState::default();
        let sys_contract = SystemContract::new_cairo1(
            CAIRO_1_ERC20_CONTRACT_CLASS_HASH,
            ETH_ERC20_CONTRACT_ADDRESS,
            CAIRO_1_ERC20_CONTRACT,
        )
        .unwrap();

        assert!(sys_contract.deploy(&mut state).is_ok());
    }
}