Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
rkdud007 committed May 22, 2024
1 parent 456f686 commit 86899c4
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 0 deletions.
1 change: 1 addition & 0 deletions cairo-lang
Submodule cairo-lang added at 57560f
1 change: 1 addition & 0 deletions cairo-vm
Submodule cairo-vm added at b72f5a
46 changes: 46 additions & 0 deletions cairo0-bootloader/common/syscalls.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from starkware.cairo.common.dict_access import DictAccess

const CALL_CONTRACT_SELECTOR = 'CallContract';

// Describes the CallContract system call format.
struct CallContractRequest {
// The system call selector
// (= CALL_CONTRACT_SELECTOR, DELEGATE_CALL_SELECTOR or DELEGATE_L1_HANDLER_SELECTOR).
selector: felt,
// The address of the L2 contract to call.
contract_address: felt,
// The selector of the function to call.
function_selector: felt,
// The size of the calldata.
calldata_size: felt,
// The calldata.
calldata: felt*,
}

struct CallContractResponse {
retdata_size: felt,
retdata: felt*,
}

struct CallContract {
request: CallContractRequest,
response: CallContractResponse,
}

func call_contract{syscall_ptr: felt*}(
contract_address: felt, function_selector: felt, calldata_size: felt, calldata: felt*
) -> (retdata_size: felt, retdata: felt*) {
let syscall = [cast(syscall_ptr, CallContract*)];
assert syscall.request = CallContractRequest(
selector=CALL_CONTRACT_SELECTOR,
contract_address=contract_address,
function_selector=function_selector,
calldata_size=calldata_size,
calldata=calldata,
);
%{ syscall_handler.call_contract(segments=segments, syscall_ptr=ids.syscall_ptr) %}
let response = syscall.response;

let syscall_ptr = syscall_ptr + CallContract.SIZE;
return (retdata_size=response.retdata_size, retdata=response.retdata);
}
103 changes: 103 additions & 0 deletions cairo0-bootloader/os/syscall_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import dataclasses
from enum import Enum, auto
from typing import List, Optional, cast
from starkware.starknet.core.os.syscall_handler import SyscallHandlerBase
from starkware.starknet.core.os.syscall_utils import cast_to_int
from starkware.cairo.common.structs import CairoStructProxy
from starkware.starknet.definitions.error_codes import StarknetErrorCode
from starkware.cairo.lang.vm.relocatable import MaybeRelocatable
from starkware.starkware_utils.error_handling import stark_assert
from starkware.starkware_utils.validated_dataclass import ValidatedDataclass


class CallType(Enum):
Call = 0
Delegate = auto()

class EntryPointType(Enum):
EXTERNAL = 0
L1_HANDLER = auto()
CONSTRUCTOR = auto()

@dataclasses.dataclass(frozen=True)
class CallResult(ValidatedDataclass):
"""
Contains the return values of a contract call.
"""

gas_consumed: int
# The result selector corresponds to the Rust panic result:
# 0 if the syscall succeeded; a non-zero otherwise.
failure_flag: int
retdata: List[int]

@classmethod
def create(
cls,
initial_gas: int,
updated_gas: MaybeRelocatable,
failure_flag: MaybeRelocatable,
retdata: List[MaybeRelocatable],
) -> "CallResult":
stark_assert(
all(isinstance(value, int) for value in retdata),
code=StarknetErrorCode.INVALID_RETURN_DATA,
message="Return data expected to be non-relocatable.",
)
stark_assert(
failure_flag in (0, 1),
code=StarknetErrorCode.INVALID_RETURN_DATA,
message="failure_flag field expected to be either 0 or 1.",
)
updated_gas = cast(int, updated_gas)
stark_assert(
isinstance(updated_gas, int) and 0 <= updated_gas <= initial_gas,
code=StarknetErrorCode.INVALID_RETURN_DATA,
message=f"Unexpected remaining gas: {updated_gas}.",
)

return cls(
gas_consumed=initial_gas - updated_gas,
failure_flag=cast(int, failure_flag),
retdata=cast(List[int], retdata),
)

@property
def succeeded(self) -> bool:
return self.failure_flag == 0

class Cairo0SyscallHandler(SyscallHandlerBase):
def _call_contract_helper(
self, remaining_gas: int, request: CairoStructProxy, syscall_name: str
) -> CallResult:
calldata = self._get_felt_range(
start_addr=request.calldata_start, end_addr=request.calldata_end
)
class_hash: Optional[int] = None
if syscall_name == "call_contract":
contract_address = cast_to_int(request.contract_address)
caller_address = self.entry_point.contract_address
call_type = CallType.Call
# if self._is_validate_execution_mode():
# stark_assert(
# self.entry_point.contract_address == contract_address,
# code=StarknetErrorCode.UNAUTHORIZED_ACTION_ON_VALIDATE,
# message=(
# f"Unauthorized syscall {syscall_name} "
# f"in execution mode {self.tx_execution_context.execution_mode.name}."
# ),
# )

call = self.execute_entry_point_cls(
call_type=call_type,
contract_address=contract_address,
entry_point_selector=cast_to_int(request.selector),
entry_point_type=EntryPointType.EXTERNAL,
calldata=calldata,
caller_address=caller_address,
initial_gas=remaining_gas,
class_hash=class_hash,
code_address=None,
)

return self.execute_entry_point(call=call)

0 comments on commit 86899c4

Please sign in to comment.