Skip to content

Commit

Permalink
feat: public cairo_call precompile
Browse files Browse the repository at this point in the history
  • Loading branch information
enitrat committed Oct 15, 2024
1 parent a053c59 commit 8242b3a
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 13 deletions.
5 changes: 3 additions & 2 deletions cairo_zero/kakarot/constants.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ namespace Constants {
const P256VERIFY_PRECOMPILE = 0x100;

// Kakarot precompiles
const CAIRO_CALL_PRECOMPILE = 0x75001;
const CAIRO_WHITELISTED_CALL_PRECOMPILE = 0x75001;
const CAIRO_MESSAGING_PRECOMPILE = 0x75002;
const CAIRO_BATCH_CALL_PRECOMPILE = 0x75003;
const CAIRO_MULTICALL_PRECOMPILE = 0x75003;
const CAIRO_CALL_PRECOMPILE = 0x75004;

// FIELD PRIME
const FELT252_PRIME_HIGH = 0x8000000000000110000000000000000;
Expand Down
9 changes: 5 additions & 4 deletions cairo_zero/kakarot/precompiles/kakarot_precompiles.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ const CAIRO_MESSAGE_GAS = 5000;

namespace KakarotPrecompiles {
// @notice Executes a cairo contract/class.
// @dev Requires a whitelisted caller, as this could be called by CALLCODE / DELEGATECALL
// @dev If called with 0x75001, the caller _must_ be whitelisted, as this could be called by CALLCODE / DELEGATECALL.
// @dev It called with 0x75004, the caller can be anyone, as DELEGATECALL / CALLCODE are not allowed.
// @dev The input is formatted as:
// @dev [selector: bytes4][starknet_address: bytes32][starknet_selector:bytes32][data_offset: bytes32][data_len: bytes32][data: bytes[]]
// @dev [starknet_address: bytes32][starknet_selector:bytes32][data_offset: bytes32][data_len: bytes32][data: bytes[]]
// @param input_len The length of the input in bytes.
// @param input The input data.
// @param caller_address The address of the caller of the precompile. Delegatecall rules apply.
func cairo_precompile{
func cairo_call_precompile{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr,
Expand Down Expand Up @@ -76,7 +77,7 @@ namespace KakarotPrecompiles {
// @notice Executes a batch of calls to cairo contracts.
// @dev Cannot be called with CALLCODE / DELEGATECALL - _must_ be checked upstream.
// @dev The input is formatted as:
// @dev [selector: bytes4][number_of_calls: bytes4]
// @dev [number_of_calls: bytes32]
// @dev [to_1: bytes32][selector_1:bytes32][calldata_offset_1: bytes32][calldata_len_1: bytes32][calldata_1: bytes[]]...[to_n:bytes32]...
// @param input_len The length of the input in bytes.
// @param input The input data.
Expand Down
4 changes: 3 additions & 1 deletion cairo_zero/kakarot/precompiles/precompiles.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,14 @@ namespace Precompiles {
// Kakarot precompiles. Offset must have been computed appropriately,
// based on the total number of kakarot precompiles
jmp rel offset;
call KakarotPrecompiles.cairo_precompile; // offset 0x0c: precompile 0x75001
call KakarotPrecompiles.cairo_call_precompile; // offset 0x0c: precompile 0x75001
ret;
call KakarotPrecompiles.cairo_message; // offset 0x0d: precompile 0x75002
ret;
call KakarotPrecompiles.multicall_cairo_precompile; // offset 0x0e: precompile 0x75003
ret;
call KakarotPrecompiles.cairo_call_precompile; // offset 0x0f: precompile 0x75004
ret;
}

// @notice A placeholder for attempts to call a precompile without permissions
Expand Down
21 changes: 15 additions & 6 deletions cairo_zero/kakarot/precompiles/precompiles_helpers.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ from kakarot.storages import Kakarot_authorized_cairo_precompiles_callers
const LAST_ETHEREUM_PRECOMPILE_ADDRESS = 0x0a;
const FIRST_ROLLUP_PRECOMPILE_ADDRESS = Constants.P256VERIFY_PRECOMPILE;
const LAST_ROLLUP_PRECOMPILE_ADDRESS = Constants.P256VERIFY_PRECOMPILE;
const FIRST_KAKAROT_PRECOMPILE_ADDRESS = Constants.CAIRO_CALL_PRECOMPILE;
const LAST_KAKAROT_PRECOMPILE_ADDRESS = Constants.CAIRO_BATCH_CALL_PRECOMPILE;
const FIRST_KAKAROT_PRECOMPILE_ADDRESS = Constants.CAIRO_WHITELISTED_CALL_PRECOMPILE;
const LAST_KAKAROT_PRECOMPILE_ADDRESS = Constants.CAIRO_CALL_PRECOMPILE;

namespace PrecompilesHelpers {
func is_rollup_precompile{range_check_ptr}(address: felt) -> felt {
Expand Down Expand Up @@ -46,7 +46,7 @@ namespace PrecompilesHelpers {
// @param precompile_address The address of the precompile.
// @return Whether the precompile address requires a whitelist.
func requires_whitelist(precompile_address: felt) -> felt {
if (precompile_address == Constants.CAIRO_CALL_PRECOMPILE) {
if (precompile_address == Constants.CAIRO_WHITELISTED_CALL_PRECOMPILE) {
return TRUE;
}
if (precompile_address == Constants.CAIRO_MESSAGING_PRECOMPILE) {
Expand All @@ -65,10 +65,18 @@ namespace PrecompilesHelpers {
return res;
}

func is_delegatecall_protected(precompile_address: felt) -> felt {
let is_cairo_multicall = Helpers.is_zero(
precompile_address - Constants.CAIRO_MULTICALL_PRECOMPILE
);
let is_cairo_call = Helpers.is_zero(precompile_address - Constants.CAIRO_CALL_PRECOMPILE);
return is_cairo_multicall + is_cairo_call;
}

// @notice Returns whether the call to the precompile is authorized.
// @dev A call is authorized if:
// a. The precompile requires a whitelist AND the CODE_ADDRESS of the caller is whitelisted
// b. The precompile is CAIRO_BATCH_CALL_PRECOMPILE and the precompile address is the same as the message address (NOT a DELEGATECALL / CALLCODE).
// b. The precompile is CAIRO_MULTICALL_PRECOMPILE and the precompile address is the same as the message address (NOT a DELEGATECALL / CALLCODE).
// @param precompile_address The address of the precompile.
// @param caller_code_address The code_address of the precompile caller.
// @param caller_address The address of the caller.
Expand Down Expand Up @@ -101,8 +109,9 @@ namespace PrecompilesHelpers {
let range_check_ptr = [ap - 2];
let authorized = [ap - 1];

// Ensure that calls to CAIRO_BATCH_CALL_PRECOMPILE are not made through a delegatecall / callcode.
if (precompile_address == Constants.CAIRO_BATCH_CALL_PRECOMPILE) {
// Ensure that calls to CAIRO_CALL_PRECOMPILE are not made through a delegatecall / callcode.
let is_delegatecall_protected_ = is_delegatecall_protected(precompile_address);
if (is_delegatecall_protected_ != FALSE) {
let is_not_delegatecall = Helpers.is_zero(message_address - precompile_address);
tempvar authorized = authorized * is_not_delegatecall;
} else {
Expand Down

0 comments on commit 8242b3a

Please sign in to comment.