Skip to content

Commit

Permalink
dev: rename and adapt solidity test files
Browse files Browse the repository at this point in the history
  • Loading branch information
enitrat committed Oct 15, 2024
1 parent 8242b3a commit ab11db2
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 79 deletions.
156 changes: 156 additions & 0 deletions solidity_contracts/src/CairoPrecompiles/CallCairoPrecompileTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

contract CallCairoPrecompileTest {
using CallCairoLib for uint256;

/// @dev The cairo contract to call
uint256 immutable cairoCounter;

constructor(uint256 cairoContractAddress) {
cairoCounter = cairoContractAddress;
}

function getCairoCounter() public view returns (uint256 counterValue) {
uint256[] memory data = new uint256[](0);
bytes memory returnData = cairoCounter.staticcallCairo("get", data);

// The return data is a 256-bit integer, so we can directly cast it to uint256
return abi.decode(returnData, (uint256));
}

/// @notice Calls the Cairo contract to increment its internal counter
/// @dev The delegatecall preserves the caller's context, so the caller's address will
/// be the caller of this function.
function delegateCallIncrementCairoCounter() external {
uint256[] memory data = new uint256[](0);
cairoCounter.delegatecallCairo("inc", data);
}

/// @notice Calls the Cairo contract to increment its internal counter
function incrementCairoCounter() external {
uint256[] memory data = new uint256[](0);
cairoCounter.callCairo("inc", data);
}

/// @notice Calls the Cairo contract to set its internal counter to an arbitrary value
/// @dev Called with a regular call, the caller's address will be this contract's address
/// @dev The counter value is split into two 128-bit values to match the Cairo contract's expected inputs (u256 is composed of two u128s)
/// @param newCounter The new counter value to set
function setCairoCounter(uint256 newCounter) external {
// The u256 input must be split into two u128 values to match the expected cairo input
uint128 newCounterLow = uint128(newCounter);
uint128 newCounterHigh = uint128(newCounter >> 128);

uint256[] memory data = new uint256[](2);
data[0] = uint256(newCounterLow);
data[1] = uint256(newCounterHigh);
cairoCounter.callCairo("set_counter", data);
}

/// @notice Calls the Cairo contract to get the (starknet) address of the last caller
/// @return lastCaller The starknet address of the last caller
function getLastCaller() external view returns (uint256 lastCaller) {
uint256[] memory data = new uint256[](0);
bytes memory returnData = cairoCounter.staticcallCairo("get_last_caller", data);

return abi.decode(returnData, (uint256));
}

/// @notice Calls the Cairo contract to increment its internal counter
/// @dev The delegatecall preserves the caller's context, so the caller's address will
/// be the caller of this function.
/// @dev Should always fail, as MulticallCairo does not support delegatecalls.
function incrementCairoCounterDelegatecall() external {
uint256[] memory data = new uint256[](0);
cairoCounter.delegatecallCairo("inc", data);
}

/// @notice Calls the Cairo contract to increment its internal counter
/// @dev Called with a regular call, the caller's address will be this contract's address
/// @dev Should always fail, as MulticallCairo does not support callcode.
function incrementCairoCounterCallcode() external {
uint256[] memory data = new uint256[](0);
cairoCounter.callcodeCairo("inc", data);
}
}

library CallCairoLib {
address constant CALL_CAIRO_PRECOMPILE = 0x0000000000000000000000000000000000075004;

function callCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
internal
returns (bytes memory)
{
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
bytes memory callData = abi.encode(contractAddress, functionSelector, data);

(bool success, bytes memory result) = CALL_CAIRO_PRECOMPILE.call(callData);
require(success, string(abi.encodePacked("CairoLib: cairo call failed with: ", result)));

return result;
}

function staticcallCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
internal
view
returns (bytes memory)
{
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
bytes memory callData = abi.encode(contractAddress, functionSelector, data);

(bool success, bytes memory result) = CALL_CAIRO_PRECOMPILE.staticcall(callData);
require(success, string(abi.encodePacked("CairoLib: cairo call failed with: ", result)));

return result;
}

function delegatecallCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
internal
returns (bytes memory)
{
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
bytes memory callData = abi.encode(contractAddress, functionSelector, data);

(bool success, bytes memory result) = CALL_CAIRO_PRECOMPILE.delegatecall(callData);
require(success, string(abi.encodePacked("CairoLib: cairo call failed with: ", result)));

return result;
}

function callcodeCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
internal
returns (bytes memory)
{
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
bytes memory callData = abi.encode(contractAddress, functionSelector, data);

bool success;
bytes memory result;

// Use inline assembly for callcode
assembly {
// Allocate memory for the return data
let ptr := mload(0x40)

// Perform the callcode
success := callcode(gas(), CALL_CAIRO_PRECOMPILE, 0, add(callData, 0x20), mload(callData), ptr, 0)

// Retrieve the size of the return data
let size := returndatasize()

// Store the size of the return data
mstore(result, size)

// Copy the return data
returndatacopy(add(result, 0x20), 0, size)

// Update the free memory pointer
mstore(0x40, add(result, add(0x20, size)))
}

require(success, string(abi.encodePacked("CairoLib: call_contract failed with: ", result)));

return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity >=0.8.0 <0.9.0;

/// @notice A contract that performs various call types to the Kakarot MulticallCairo precompile.
/// @dev Only meant to test the MulticallCairo precompile when called from a Solidity Contract.
contract MulticallCairoCounterCaller {
contract MulticallCairoPrecompileTest {
using MulticallCairoLib for uint256;

/// @dev The cairo contract to call
Expand All @@ -12,16 +12,14 @@ contract MulticallCairoCounterCaller {
/// @dev The cairo function selector to call - `inc`
uint256 constant FUNCTION_SELECTOR_INC = uint256(keccak256("inc")) % 2 ** 250;

/// @dev The cairo function selector to call - `set_counter`
uint256 constant FUNCTION_SELECTOR_SET_COUNTER = uint256(keccak256("set_counter")) % 2 ** 250;

constructor(uint256 cairoContractAddress) {
cairoCounter = cairoContractAddress;
}

/// @notice Calls the Cairo contract to increment its internal counter
function incrementCairoCounter() external {
cairoCounter.callCairo("inc");
uint256[] memory data = new uint256[](0);
cairoCounter.callCairo("inc", data);
}

/// @notice Calls the Cairo contract to increment its internal counter in a batch of multiple calls
Expand All @@ -42,14 +40,16 @@ contract MulticallCairoCounterCaller {
/// be the caller of this function.
/// @dev Should always fail, as MulticallCairo does not support delegatecalls.
function incrementCairoCounterDelegatecall() external {
cairoCounter.delegatecallCairo("inc");
uint256[] memory data = new uint256[](0);
cairoCounter.delegatecallCairo("inc", data);
}

/// @notice Calls the Cairo contract to increment its internal counter
/// @dev Called with a regular call, the caller's address will be this contract's address
/// @dev Should always fail, as MulticallCairo does not support callcode.
function incrementCairoCounterCallcode() external {
cairoCounter.callcodeCairo("inc");
uint256[] memory data = new uint256[](0);
cairoCounter.callcodeCairo("inc", data);
}
}

Expand Down Expand Up @@ -78,10 +78,11 @@ library MulticallCairoLib {
return result;
}

function callCairo(uint256 contractAddress, uint256 functionSelector, uint256[] memory data)
function callCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
internal
returns (bytes memory)
{
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
bytes memory callData =
bytes.concat(abi.encode(uint256(1)), abi.encode(contractAddress, functionSelector, data));

Expand All @@ -91,28 +92,11 @@ library MulticallCairoLib {
return result;
}

function callCairo(uint256 contractAddress, uint256 functionSelector) internal returns (bytes memory) {
uint256[] memory data = new uint256[](0);
return callCairo(contractAddress, functionSelector, data);
}

function callCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
function delegatecallCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
internal
returns (bytes memory)
{
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
return callCairo(contractAddress, functionSelector, data);
}

function callCairo(uint256 contractAddress, string memory functionName) internal returns (bytes memory) {
uint256[] memory data = new uint256[](0);
return callCairo(contractAddress, functionName, data);
}

function delegatecallCairo(uint256 contractAddress, uint256 functionSelector, uint256[] memory data)
internal
returns (bytes memory)
{
bytes memory callData =
bytes.concat(abi.encode(uint256(1)), abi.encode(contractAddress, functionSelector, data));

Expand All @@ -126,29 +110,11 @@ library MulticallCairoLib {
return result;
}

function delegatecallCairo(uint256 contractAddress, uint256 functionSelector) internal returns (bytes memory) {
uint256[] memory data = new uint256[](0);
return delegatecallCairo(contractAddress, functionSelector, data);
}

function delegatecallCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
function callcodeCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
internal
returns (bytes memory)
{
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
return delegatecallCairo(contractAddress, functionSelector, data);
}

function delegatecallCairo(uint256 contractAddress, string memory functionName) internal returns (bytes memory) {
uint256[] memory data = new uint256[](0);
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
return delegatecallCairo(contractAddress, functionSelector, data);
}

function callcodeCairo(uint256 contractAddress, uint256 functionSelector, uint256[] memory data)
internal
returns (bytes memory)
{
bytes memory callData =
bytes.concat(abi.encode(uint256(1)), abi.encode(contractAddress, functionSelector, data));

Expand Down Expand Up @@ -180,10 +146,4 @@ library MulticallCairoLib {

return result;
}

function callcodeCairo(uint256 contractAddress, string memory functionName) internal returns (bytes memory) {
uint256[] memory data = new uint256[](0);
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
return callcodeCairo(contractAddress, functionSelector, data);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;

import {CairoCounterCaller} from "./CairoCounterCaller.sol";
import {WhitelistedCallCairoPrecompileTest} from "./WhitelistedCallCairoPrecompileTest.sol";

contract SubContextPrecompile {
RevertingSubContext immutable revertingSubContext;
Expand All @@ -21,11 +21,11 @@ contract SubContextPrecompile {
}

contract RevertingSubContext {
CairoCounterCaller immutable cairo_counter_caller;
WhitelistedCallCairoPrecompileTest immutable cairo_counter_caller;
uint256 dummyCounter;

constructor(address _cairo_counter_caller) {
cairo_counter_caller = CairoCounterCaller(_cairo_counter_caller);
cairo_counter_caller = WhitelistedCallCairoPrecompileTest(_cairo_counter_caller);
}

function reverting() public {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,16 @@ import {CairoLib} from "kakarot-lib/CairoLib.sol";

using CairoLib for uint256;

contract CairoCounterCaller {
contract WhitelistedCallCairoPrecompileTest {
/// @dev The cairo contract to call
uint256 immutable cairoCounter;

/// @dev The cairo function selector to call - `inc`
uint256 constant FUNCTION_SELECTOR_INC = uint256(keccak256("inc")) % 2 ** 250;

/// @dev The cairo function selector to call - `set_counter`
uint256 constant FUNCTION_SELECTOR_SET_COUNTER = uint256(keccak256("set_counter")) % 2 ** 250;

/// @dev The cairo function selector to call - `get`
uint256 constant FUNCTION_SELECTOR_GET = uint256(keccak256("get")) % 2 ** 250;

uint256 constant FUNCTION_SELECTOR_GET_LAST_CALLER = uint256(keccak256("get_last_caller")) % 2 ** 250;

constructor(uint256 cairoContractAddress) {
cairoCounter = cairoContractAddress;
}

function getCairoCounter() public view returns (uint256 counterValue) {
bytes memory returnData = cairoCounter.staticcallCairo(FUNCTION_SELECTOR_GET);
bytes memory returnData = cairoCounter.staticcallCairo("get");

// The return data is a 256-bit integer, so we can directly cast it to uint256
return abi.decode(returnData, (uint256));
Expand All @@ -34,10 +23,15 @@ contract CairoCounterCaller {
/// @notice Calls the Cairo contract to increment its internal counter
/// @dev The delegatecall preserves the caller's context, so the caller's address will
/// be the caller of this function.
function incrementCairoCounter() external {
function delegateCallIncrementCairoCounter() external {
cairoCounter.delegatecallCairo("inc");
}

/// @notice Calls the Cairo contract to increment its internal counter
function incrementCairoCounter() external {
cairoCounter.callCairo("inc");
}

/// @notice Calls the Cairo contract to set its internal counter to an arbitrary value
/// @dev Called with a regular call, the caller's address will be this contract's address
/// @dev The counter value is split into two 128-bit values to match the Cairo contract's expected inputs (u256 is composed of two u128s)
Expand All @@ -50,13 +44,13 @@ contract CairoCounterCaller {
uint256[] memory data = new uint256[](2);
data[0] = uint256(newCounterLow);
data[1] = uint256(newCounterHigh);
cairoCounter.callCairo(FUNCTION_SELECTOR_SET_COUNTER, data);
cairoCounter.callCairo("set_counter", data);
}

/// @notice Calls the Cairo contract to get the (starknet) address of the last caller
/// @return lastCaller The starknet address of the last caller
function getLastCaller() external view returns (uint256 lastCaller) {
bytes memory returnData = cairoCounter.staticcallCairo(FUNCTION_SELECTOR_GET_LAST_CALLER);
bytes memory returnData = cairoCounter.staticcallCairo("get_last_caller");

return abi.decode(returnData, (uint256));
}
Expand Down
Loading

0 comments on commit ab11db2

Please sign in to comment.