From bc9ea729b4a3051a7244752fd12d2b92bd38ed8a Mon Sep 17 00:00:00 2001 From: enitrat Date: Tue, 19 Nov 2024 22:31:12 +0800 Subject: [PATCH] feat: add new_call_contract_syscall to Cairo1Helpers class --- crates/contracts/src/cairo1_helpers.cairo | 45 +++++++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/contracts/src/cairo1_helpers.cairo b/crates/contracts/src/cairo1_helpers.cairo index 4bd3b89d2..6fde0474b 100644 --- a/crates/contracts/src/cairo1_helpers.cairo +++ b/crates/contracts/src/cairo1_helpers.cairo @@ -1,4 +1,4 @@ -use core::starknet::{EthAddress, secp256_trait::Signature}; +use core::starknet::{EthAddress, secp256_trait::Signature, ContractAddress}; #[starknet::interface] pub trait IPrecompiles { @@ -88,7 +88,7 @@ pub trait IHelpers { /// * The recovered Ethereum address. fn recover_eth_address(self: @T, msg_hash: u256, signature: Signature) -> (bool, EthAddress); - /// Performs signature verification in the secp256r1 ellipitic curve. + /// Performs signature verification in the secp256r1 elliptic curve. /// /// # Arguments /// @@ -103,13 +103,33 @@ pub trait IHelpers { fn verify_signature_secp256r1( self: @T, msg_hash: u256, r: u256, s: u256, x: u256, y: u256 ) -> bool; + + + /// Calls a contract using the new Cairo call_contract_syscall. + /// + /// Meant to be used from Cairo Zero classes that want to be able to manage the return value of + /// the call. + /// Only applicable from Starknet v0.13.4 and onwwards. + /// + /// # Arguments + /// + /// * `to` - The address of the contract to call. + /// * `selector` - The selector of the function to call. + /// * `calldata` - The calldata to pass to the function. + /// + /// # Returns + /// A tuple containing: + /// * A boolean indicating whether the call was successful. + /// * The output of the call. + fn new_call_contract_syscall( + ref self: T, to: ContractAddress, selector: felt252, calldata: Span + ) -> (bool, Span); } pub mod embeddable_impls { use core::keccak::{cairo_keccak, keccak_u256s_be_inputs}; use core::num::traits::Zero; - use core::starknet::EthAddress; use core::starknet::eth_signature::{verify_eth_signature}; use core::starknet::secp256_trait::{ Signature, recover_public_key, Secp256PointTrait, is_valid_signature @@ -117,6 +137,7 @@ pub mod embeddable_impls { use core::starknet::secp256_trait::{Secp256Trait}; use core::starknet::secp256k1::Secp256k1Point; use core::starknet::secp256r1::{Secp256r1Point}; + use core::starknet::{ContractAddress, EthAddress}; use core::traits::Into; use core::{starknet, starknet::SyscallResultTrait}; use evm::errors::EVMError; @@ -149,7 +170,7 @@ pub mod embeddable_impls { } #[starknet::embeddable] - pub impl Helpers of super::IHelpers { + pub impl Helpers> of super::IHelpers { fn get_block_hash(self: @TContractState, block_number: u64) -> felt252 { starknet::syscalls::get_block_hash_syscall(block_number).unwrap_syscall() } @@ -217,6 +238,22 @@ pub mod embeddable_impls { return is_valid_signature(msg_hash, r, s, public_key); } + + fn new_call_contract_syscall( + ref self: TContractState, + to: ContractAddress, + selector: felt252, + calldata: Span + ) -> (bool, Span) { + // Note: until Starknet v0.13.4, the transaction will fail if the call reverted. + let result = starknet::syscalls::call_contract_syscall(to, selector, calldata); + match result { + Result::Ok(output) => { return (true, output); }, + // This will need to be manually tested and enabled once contract calls can be + // handled. + Result::Err(error) => { return panic(error); } + } + } } }