Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update cairo lib addresses #10

Merged
merged 3 commits into from
Oct 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 62 additions & 115 deletions src/CairoLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,155 +3,79 @@ pragma solidity >=0.8.0 <0.9.0;

obatirou marked this conversation as resolved.
Show resolved Hide resolved
library CairoLib {
/// @dev The Cairo precompile contract's address.
address constant CAIRO_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000075001;
address constant CAIRO_MESSAGING_ADDRESS = 0x0000000000000000000000000000000000075002;
address constant CAIRO_MESSAGE_PRECOMPILE = 0x0000000000000000000000000000000000075002;
address constant CAIRO_MULTICALL_PRECOMPILE= 0x0000000000000000000000000000000000075003;
address constant CAIRO_CALL_PRECOMPILE= 0x0000000000000000000000000000000000075004;

struct CairoCall {
uint256 contractAddress;
uint256 functionSelector;
uint256[] data;
}

/// @notice Performs a low-level call to a Cairo contract deployed on the Starknet appchain.
/// @notice Performs a low-level call to a Cairo contract deployed on Starknet.
/// @dev Used with intent to modify the state of the Cairo contract.
/// @param contractAddress The address of the Cairo contract.
/// @param functionSelector The function selector of the Cairo contract function to be called.
/// @param data The input data for the Cairo contract function.
/// @return The return data from the Cairo contract function.
function callCairo(uint256 contractAddress, uint256 functionSelector, uint256[] memory data)
internal
returns (bytes memory)
{
function callCairo(uint256 contractAddress, uint256 functionSelector, uint256[] memory data) internal returns (bytes memory) {
bytes memory callData = abi.encode(contractAddress, functionSelector, data);

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

return result;
}

/// @notice Performs a low-level call to a Cairo contract deployed on the Starknet appchain.
/// @dev Used with intent to modify the state of the Cairo contract.
/// @param contractAddress The address of the Cairo contract.
/// @param functionSelector The function selector of the Cairo contract function to be called.
/// @return The return data from the Cairo contract function.
function callCairo(uint256 contractAddress, uint256 functionSelector) internal returns (bytes memory) {
uint256[] memory data = new uint256[](0);
return callCairo(contractAddress, functionSelector, data);
}

/// @notice Performs a low-level call to a Cairo contract deployed on the Starknet appchain.
/// @dev Used with intent to modify the state of the Cairo contract.
/// @param functionName The name of the Cairo contract function to be called.
/// @return The return data from the Cairo contract function.
function callCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
function callCairo(CairoCall memory call)
internal
returns (bytes memory)
{
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
return callCairo(contractAddress, functionSelector, data);
return callCairo(call.contractAddress, call.functionSelector, call.data);
}

/// @notice Performs a low-level call to a Cairo contract deployed on the Starknet appchain.
/// @dev Used with intent to modify the state of the Cairo contract.
/// @param functionName The name of the Cairo contract function to be called.
/// @return The return data from the Cairo contract function.
function callCairo(uint256 contractAddress, string memory functionName) internal returns (bytes memory) {
function callCairo(uint256 contractAddress, uint256 functionSelector) internal returns (bytes memory) {
uint256[] memory data = new uint256[](0);
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
return callCairo(contractAddress, functionSelector, data);
}

/// @notice Performs a low-level delegatecall to a Cairo contract deployed on the Starknet appchain.
/// @dev Used with intent to modify the state of the Cairo contract.
/// @dev Using delegatecall preserves the context of the calling contract, and the execution of the
/// callee contract is performed using the `msg.sender` of the calling contract.
/// @param contractAddress The address of the Cairo contract.
/// @param functionSelector The function selector of the Cairo contract function to be called.
/// @param data The input data for the Cairo contract function.
/// @return The return data from the Cairo contract function.
function delegatecallCairo(uint256 contractAddress, uint256 functionSelector, uint256[] memory data)
internal
returns (bytes memory)
{
bytes memory callData = abi.encode(contractAddress, functionSelector, data);

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

return result;
}

/// @notice Performs a low-level delegatecall to a Cairo contract deployed on the Starknet appchain.
/// @dev Used with intent to modify the state of the Cairo contract.
/// @dev Using delegatecall preserves the context of the calling contract, and the execution of the
/// callee contract is performed using the `msg.sender` of the calling contract.
/// @param contractAddress The address of the Cairo contract.
/// @param functionSelector The function selector of the Cairo contract function to be called.
/// @return The return data from the Cairo contract function.
function delegatecallCairo(uint256 contractAddress, uint256 functionSelector) internal returns (bytes memory) {
function callCairo(uint256 contractAddress, string memory functionName) internal returns (bytes memory) {
uint256[] memory data = new uint256[](0);
return delegatecallCairo(contractAddress, functionSelector, data);
}

/// @notice Performs a low-level delegatecall to a Cairo contract deployed on the Starknet appchain.
/// @dev Used with intent to modify the state of the Cairo contract.
/// @dev Using delegatecall preserves the context of the calling contract, and the execution of the
/// callee contract is performed using the `msg.sender` of the calling contract.
/// @param contractAddress The address of the Cairo contract.
/// @param functionName The name of the Cairo contract function to be called.
/// @param data The input data for the Cairo contract function.
/// @return The return data from the Cairo contract function.
function delegatecallCairo(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);
return callCairo(contractAddress, functionSelector, data);
}

/// @notice Performs a low-level delegatecall to a Cairo contract deployed on the Starknet appchain.
/// @dev Used with intent to modify the state of the Cairo contract.
/// @dev Using delegatecall preserves the context of the calling contract, and the execution of the
/// callee contract is performed using the `msg.sender` of the calling contract.
/// @param contractAddress The address of the Cairo contract.
/// @param functionName The name of the Cairo contract function to be called.
/// @return The return data from the Cairo contract function.
function delegatecallCairo(uint256 contractAddress, string memory functionName) internal returns (bytes memory) {
uint256[] memory data = new uint256[](0);
function callCairo(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);
return callCairo(contractAddress, functionSelector, data);
}

/// @notice Performs a low-level call to a Cairo contract deployed on the Starknet appchain.
/// @notice Performs a low-level static call to a Cairo contract deployed on Starknet.
/// @dev Used with intent to read the state of the Cairo contract.
/// @param contractAddress The address of the Cairo contract.
/// @param functionSelector The function selector of the Cairo contract function to be called.
/// @param data The input data for the Cairo contract function.
/// @return The return data from the Cairo contract function.
function staticcallCairo(uint256 contractAddress, uint256 functionSelector, uint256[] memory data)
internal
view
returns (bytes memory)
{
function staticcallCairo(uint256 contractAddress, uint256 functionSelector, uint256[] memory data) internal view returns (bytes memory) {
bytes memory callData = abi.encode(contractAddress, functionSelector, data);

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

return result;
}

/// @notice Performs a low-level call to a Cairo contract deployed on the Starknet appchain.
/// @dev Used with intent to read the state of the Cairo contract.
/// @param contractAddress The address of the Cairo contract.
/// @param functionSelector The function selector of the Cairo contract function to be called.
/// @return The return data from the Cairo contract function.
function staticcallCairo(uint256 contractAddress, uint256 functionSelector) internal view returns (bytes memory) {
function staticcallCairo(uint256 contractAddress, string memory functionName)
internal
view
returns (bytes memory)
{
uint256[] memory data = new uint256[](0);
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
return staticcallCairo(contractAddress, functionSelector, data);
}

/// @notice Performs a low-level call to a Cairo contract deployed on the Starknet appchain.
/// @dev Used with intent to read the state of the Cairo contract.
/// @param contractAddress The address of the Cairo contract.
/// @param functionName The name of the Cairo contract function to be called.
/// @param data The input data for the Cairo contract function.
/// @return The return data from the Cairo contract function.
function staticcallCairo(uint256 contractAddress, string memory functionName, uint256[] memory data)
internal
view
Expand All @@ -161,26 +85,49 @@ library CairoLib {
return staticcallCairo(contractAddress, functionSelector, data);
}

/// @notice Performs a low-level call to a Cairo contract deployed on the Starknet appchain.
/// @dev Used with intent to read the state of the Cairo contract.
/// @param contractAddress The address of the Cairo contract.
/// @param functionName The name of the Cairo contract function to be called.
/// @return The return data from the Cairo contract function.
function staticcallCairo(uint256 contractAddress, string memory functionName)
function staticcallCairo(CairoCall memory call)
internal
view
returns (bytes memory)
{
uint256[] memory data = new uint256[](0);
uint256 functionSelector = uint256(keccak256(bytes(functionName))) % 2 ** 250;
return staticcallCairo(contractAddress, functionSelector, data);
return staticcallCairo(call.contractAddress, call.functionSelector, call.data);
}


/// @notice Performs a multicall to Cairo contracts deployed on Starknet.
/// @dev Used with intent to modify the state of the Cairo contract.
/// @param calls The array of CairoCall structs to be executed.
function multicallCairo(CairoCall[] memory calls) internal {
uint256 n_calls = calls.length;
bytes memory callData = abi.encode(n_calls);
for (uint32 i = 0; i < n_calls; i++) {
bytes memory encodedCall = abi.encode(calls[i].contractAddress, calls[i].functionSelector, calls[i].data);
callData = bytes.concat(callData, encodedCall);
}
(bool success,) = CAIRO_MULTICALL_PRECOMPILE.call(callData);
require(success, "CairoLib: multicallCairo failed");
}

/// @notice Performs a multicall to Cairo contracts deployed on Starknet.
/// @dev Used with intent to read the state of the Cairo contract.
/// @dev **This can still mutate the underlying Cairo contract state.**
/// @param calls The array of CairoCall structs to be executed.
function multicallCairoStatic(CairoCall[] memory calls) internal view {
obatirou marked this conversation as resolved.
Show resolved Hide resolved
uint256 n_calls = calls.length;
bytes memory callData = abi.encode(n_calls);
for (uint32 i = 0; i < n_calls; i++) {
bytes memory encodedCall = abi.encode(calls[i].contractAddress, calls[i].functionSelector, calls[i].data);
callData = bytes.concat(callData, encodedCall);
}
(bool success,) = CAIRO_MULTICALL_PRECOMPILE.staticcall(callData);
require(success, "CairoLib: multicallCairoStatic failed");
}

/// @notice Performs a low-level call to send a message from the Kakarot to the Ethereum network.
/// @param payload The payload of the message to send to the Ethereum contract. The same payload will need
/// to be provided on L1 to consume the message.
function sendMessageToL1(bytes memory payload) internal {
(bool success,) = CAIRO_MESSAGING_ADDRESS.call(payload);
(bool success,) = CAIRO_MESSAGE_PRECOMPILE.call(payload);
require(success, "CairoLib: sendMessageToL1 failed");
}

Expand Down