Skip to content
This repository has been archived by the owner on Sep 5, 2023. It is now read-only.

Murcake/check calldata #147

Merged
merged 3 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
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
3 changes: 1 addition & 2 deletions .github/workflows/develop-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,8 @@ jobs:
- name: Create benchmarks
run: |
mkdir -p benchmark/stats benchmark/tmp
python -m pytest tests/yul/ -v --tb=short --workers=auto
python -m pytest tests/behaviour/ -v --tb=short --workers=auto
make benchmark
python -m pytest tests/yul/ -v --tb=short --workers=auto $(ARGS)
mv ./benchmark/stats/stats.md "./benchmark/stats/${{ env.source_hash }}.md"

- name: Push benchmarks to another repository
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ test_yul: warp
python -m pytest tests/ast/ -v --tb=short --workers=auto $(ARGS)
python -m pytest scripts/yul/transpile_test.py -v --tb=short --workers=auto $(ARGS)
python -m pytest scripts/yul/compilation_test.py -v --tb=short --workers=auto $(ARGS)
python -m pytest tests/yul/ -v --tb=short --workers=auto $(ARGS)
python -m pytest tests/behaviour/ -v --tb=short --workers=auto $(ARGS)
.PHONY: test_yul

benchmark: warp
Expand Down
2 changes: 1 addition & 1 deletion scripts/yul/compilation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from starkware.starknet.compiler.compile import compile_starknet_files

warp_root = os.path.abspath(os.path.join(__file__, "../../.."))
test_dir = os.path.join(warp_root, "tests", "yul")
test_dir = os.path.join(warp_root, "tests", "golden")
cairo_files = [
os.path.join(test_dir, item)
for item in os.listdir(test_dir)
Expand Down
2 changes: 1 addition & 1 deletion scripts/yul/compile_sol_files_in_tests_yul.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env sh
for f in tests/yul/*.sol do
for f in tests/golden/*.sol do
warp transpile $f WARP --cairo-output &
done
wait
2 changes: 1 addition & 1 deletion scripts/yul/transpile_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from yul.main import transpile_from_solidity

warp_root = os.path.abspath(os.path.join(__file__, "../../.."))
test_dir = os.path.join(warp_root, "tests", "yul")
test_dir = os.path.join(warp_root, "tests", "golden")
tests = [
os.path.join(test_dir, item)
for item in os.listdir(test_dir)
Expand Down
1 change: 1 addition & 0 deletions tests/behaviour/ERC20.sol
1 change: 1 addition & 0 deletions tests/behaviour/ERC20_storage.cairo
1 change: 1 addition & 0 deletions tests/behaviour/ERC20_storage.sol
1 change: 1 addition & 0 deletions tests/behaviour/address.cairo
1 change: 1 addition & 0 deletions tests/behaviour/address.sol
1 change: 1 addition & 0 deletions tests/behaviour/c2c.cairo
1 change: 1 addition & 0 deletions tests/behaviour/c2c.sol
File renamed without changes.
1 change: 1 addition & 0 deletions tests/behaviour/calldatacopy.cairo
1 change: 1 addition & 0 deletions tests/behaviour/calldatacopy.sol
1 change: 1 addition & 0 deletions tests/behaviour/constructors_dyn.cairo
1 change: 1 addition & 0 deletions tests/behaviour/constructors_dyn.sol
1 change: 1 addition & 0 deletions tests/behaviour/constructors_nonDyn.cairo
1 change: 1 addition & 0 deletions tests/behaviour/constructors_nonDyn.sol
24 changes: 24 additions & 0 deletions tests/behaviour/friendly.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pragma solidity ^0.8.6;

interface IFriend {
function call_friend(IFriend friend) external view returns (uint);

function tell_number(IFriend friend) external view returns (uint);
}

contract Friend is IFriend {
uint _number;

constructor(uint number) {
_number = number;
}

function call_friend(IFriend friend) external view returns (uint) {
return friend.tell_number(this);
}

function tell_number(IFriend friend) external view returns (uint) {
require(msg.sender == address(friend));
return _number;
}
}
12 changes: 12 additions & 0 deletions tests/behaviour/hacker.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
%lang starknet
%builtins range_check

from starkware.cairo.common.alloc import alloc

@external
func __main(calldata_size : felt, calldata_len : felt, calldata : felt*) -> (
returndata_size : felt, returndata_len : felt, returndata : felt*):
let (returndata) = alloc()
assert returndata[0] = 2 ** 128
return (16, 1, returndata)
end
94 changes: 94 additions & 0 deletions tests/behaviour/malicious-calldata_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import asyncio
import tempfile
from pathlib import Path

import pytest
from cli.encoding import get_cairo_calldata, get_ctor_evm_calldata, get_evm_calldata
from starkware.starknet.compiler.compile import (
compile_starknet_codes,
compile_starknet_files,
)
from starkware.starknet.testing.state import StarknetState
from starkware.starkware_utils.error_handling import StarkException
from yul.main import transpile_from_solidity
from yul.starknet_utils import deploy_contract, invoke_method

WARP_ROOT = Path(__file__).parents[2]
CAIRO_PATH = WARP_ROOT / "warp" / "cairo-src"
TEST_DIR = Path(__file__).parent


@pytest.fixture
async def starknet():
return await StarknetState.empty()


@pytest.fixture
def friendly_info():
friendly_file = TEST_DIR / "friendly.sol"
return transpile_from_solidity(friendly_file, "Friend")


@pytest.fixture
def friendly_def(friendly_info):
with tempfile.NamedTemporaryFile(mode="w", suffix=".cairo") as tmp:
tmp.write(friendly_info["cairo_code"])
yield compile_starknet_codes(
[(friendly_info["cairo_code"], tmp.name)],
debug_info=True,
cairo_path=[CAIRO_PATH],
)


@pytest.fixture
async def friendly_address(starknet, friendly_info, friendly_def):
return await deploy_contract(starknet, friendly_info, friendly_def, 8)


@pytest.mark.asyncio
async def test_normal_contract_call(
starknet, friendly_info, friendly_def, friendly_address
):
friendly_address2 = await deploy_contract(starknet, friendly_info, friendly_def, 13)
result = await invoke_method(
starknet, friendly_info, friendly_address, "call_friend", friendly_address2
)
assert result.retdata == [32, 2, 0, 13]


@pytest.mark.asyncio
async def test_malicious_deploy(starknet, friendly_info, friendly_def):
evm_calldata = get_ctor_evm_calldata(friendly_info["sol_abi"], [0])
cairo_calldata = get_cairo_calldata(evm_calldata)
cairo_calldata[-1] = 2 ** 128 # tamper with calldata to make it invalid
exc_msg = rf"Value {2**128}, in range check builtin \d*, is out of range \[0, {2**128}\)\."
with pytest.raises(StarkException, match=exc_msg):
await starknet.deploy(friendly_def, cairo_calldata)


@pytest.mark.asyncio
async def test_malicious_direct_call(starknet, friendly_info, friendly_address):
evm_calldata = get_evm_calldata(friendly_info["sol_abi"], "call_friend", [0])
cairo_calldata = get_cairo_calldata(evm_calldata)
cairo_calldata[-1] = 2 ** 128 # tamper with calldata to make it invalid
exc_msg = rf"Value {2**128}, in range check builtin \d*, is out of range \[0, {2**128}\)\."
with pytest.raises(StarkException, match=exc_msg):
await starknet.invoke_raw(
contract_address=friendly_address,
selector="__main",
calldata=cairo_calldata,
caller_address=0,
)


@pytest.mark.asyncio
async def test_malicious_contract_call(starknet, friendly_info, friendly_address):
hacker_file = TEST_DIR / "hacker.cairo"
hacker_def = compile_starknet_files([str(hacker_file)], debug_info=True)
hacker_address = await starknet.deploy(hacker_def, [])

exc_msg = rf"Value {2**128}, in range check builtin \d*, is out of range \[0, {2**128}\)\."
with pytest.raises(StarkException, match=exc_msg):
await invoke_method(
starknet, friendly_info, friendly_address, "call_friend", hacker_address
)
1 change: 1 addition & 0 deletions tests/behaviour/payable-function.cairo
1 change: 1 addition & 0 deletions tests/behaviour/payable-function.sol
1 change: 1 addition & 0 deletions tests/behaviour/pure-function.cairo
1 change: 1 addition & 0 deletions tests/behaviour/pure-function.sol
1 change: 1 addition & 0 deletions tests/behaviour/short_string.cairo
1 change: 1 addition & 0 deletions tests/behaviour/short_string.sol
1 change: 1 addition & 0 deletions tests/behaviour/view-function.cairo
1 change: 1 addition & 0 deletions tests/behaviour/view-function.sol
12 changes: 6 additions & 6 deletions tests/cli/tests.bats
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
}

@test "check constructor_dyn.sol" {
warp transpile ./tests/yul/constructors_dyn.sol WARP
warp deploy ./tests/yul/constructors_dyn.json --constructor_args "[0x123, (12, 15), 17]"
rm ./tests/yul/constructors_dyn.json
warp transpile ./tests/golden/constructors_dyn.sol WARP
warp deploy ./tests/golden/constructors_dyn.json --constructor_args "[0x123, (12, 15), 17]"
rm ./tests/golden/constructors_dyn.json
}

@test "check constructor_nonDyn.sol" {
warp transpile ./tests/yul/constructors_nonDyn.sol WARP
warp deploy ./tests/yul/constructors_nonDyn.json --constructor_args "[0x123, 15, 17]"
rm ./tests/yul/constructors_nonDyn.json
warp transpile ./tests/golden/constructors_nonDyn.sol WARP
warp deploy ./tests/golden/constructors_nonDyn.json --constructor_args "[0x123, 15, 17]"
rm ./tests/golden/constructors_nonDyn.json
}
3 changes: 3 additions & 0 deletions tests/yul/ERC20.cairo → tests/golden/ERC20.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
%lang starknet
%builtins pedersen range_check bitwise

from evm.array import validate_array
from evm.calls import calldataload, calldatasize, caller
from evm.exec_env import ExecutionEnvironment
from evm.hashing import uint256_pedersen
Expand Down Expand Up @@ -41,6 +42,7 @@ end
func constructor{pedersen_ptr : HashBuiltin*, range_check_ptr, syscall_ptr : felt*}(
calldata_size, calldata_len, calldata : felt*):
alloc_locals
validate_array(calldata_len, calldata)
let (memory_dict) = default_dict_new(0)
let memory_dict_start = memory_dict
let msize = 0
Expand All @@ -56,6 +58,7 @@ func __main{pedersen_ptr : HashBuiltin*, range_check_ptr, syscall_ptr : felt*}(
calldata_size, calldata_len, calldata : felt*) -> (
returndata_size, returndata_len, returndata : felt*):
alloc_locals
validate_array(calldata_len, calldata)
let (__fp__, _) = get_fp_and_pc()
local exec_env_ : ExecutionEnvironment = ExecutionEnvironment(calldata_size=calldata_size, calldata_len=calldata_len, calldata=calldata, returndata_size=0, returndata_len=0, returndata=cast(0, felt*), to_returndata_size=0, to_returndata_len=0, to_returndata=cast(0, felt*))
let exec_env : ExecutionEnvironment* = &exec_env_
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
%lang starknet
%builtins pedersen range_check bitwise

from evm.array import validate_array
from evm.calls import calldataload, calldatasize
from evm.exec_env import ExecutionEnvironment
from evm.hashing import uint256_pedersen
Expand Down Expand Up @@ -41,6 +42,7 @@ end
func constructor{pedersen_ptr : HashBuiltin*, range_check_ptr, syscall_ptr : felt*}(
calldata_size, calldata_len, calldata : felt*):
alloc_locals
validate_array(calldata_len, calldata)
let (memory_dict) = default_dict_new(0)
let memory_dict_start = memory_dict
let msize = 0
Expand All @@ -56,6 +58,7 @@ func __main{pedersen_ptr : HashBuiltin*, range_check_ptr, syscall_ptr : felt*}(
calldata_size, calldata_len, calldata : felt*) -> (
returndata_size, returndata_len, returndata : felt*):
alloc_locals
validate_array(calldata_len, calldata)
let (__fp__, _) = get_fp_and_pc()
local exec_env_ : ExecutionEnvironment = ExecutionEnvironment(calldata_size=calldata_size, calldata_len=calldata_len, calldata=calldata, returndata_size=0, returndata_len=0, returndata=cast(0, felt*), to_returndata_size=0, to_returndata_len=0, to_returndata=cast(0, felt*))
let exec_env : ExecutionEnvironment* = &exec_env_
Expand Down
3 changes: 3 additions & 0 deletions tests/yul/address.cairo → tests/golden/address.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
%lang starknet
%builtins pedersen range_check bitwise

from evm.array import validate_array
from evm.calls import calldataload, calldatasize
from evm.exec_env import ExecutionEnvironment
from evm.memory import uint256_mstore
Expand All @@ -19,6 +20,7 @@ end
@constructor
func constructor{range_check_ptr}(calldata_size, calldata_len, calldata : felt*):
alloc_locals
validate_array(calldata_len, calldata)
let (memory_dict) = default_dict_new(0)
let memory_dict_start = memory_dict
let msize = 0
Expand All @@ -34,6 +36,7 @@ func __main{range_check_ptr, syscall_ptr : felt*}(
calldata_size, calldata_len, calldata : felt*) -> (
returndata_size, returndata_len, returndata : felt*):
alloc_locals
validate_array(calldata_len, calldata)
let (__fp__, _) = get_fp_and_pc()
local exec_env_ : ExecutionEnvironment = ExecutionEnvironment(calldata_size=calldata_size, calldata_len=calldata_len, calldata=calldata, returndata_size=0, returndata_len=0, returndata=cast(0, felt*), to_returndata_size=0, to_returndata_len=0, to_returndata=cast(0, felt*))
let exec_env : ExecutionEnvironment* = &exec_env_
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions tests/yul/arrays.cairo → tests/golden/arrays.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
%lang starknet
%builtins pedersen range_check bitwise

from evm.array import validate_array
from evm.calls import calldataload, calldatasize
from evm.exec_env import ExecutionEnvironment
from evm.hashing import uint256_pedersen
Expand Down Expand Up @@ -36,6 +37,7 @@ end
@constructor
func constructor{range_check_ptr}(calldata_size, calldata_len, calldata : felt*):
alloc_locals
validate_array(calldata_len, calldata)
let (memory_dict) = default_dict_new(0)
let memory_dict_start = memory_dict
let msize = 0
Expand All @@ -51,6 +53,7 @@ func __main{pedersen_ptr : HashBuiltin*, range_check_ptr, syscall_ptr : felt*}(
calldata_size, calldata_len, calldata : felt*) -> (
returndata_size, returndata_len, returndata : felt*):
alloc_locals
validate_array(calldata_len, calldata)
let (__fp__, _) = get_fp_and_pc()
local exec_env_ : ExecutionEnvironment = ExecutionEnvironment(calldata_size=calldata_size, calldata_len=calldata_len, calldata=calldata, returndata_size=0, returndata_len=0, returndata=cast(0, felt*), to_returndata_size=0, to_returndata_len=0, to_returndata=cast(0, felt*))
let exec_env : ExecutionEnvironment* = &exec_env_
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions tests/yul/c2c.cairo → tests/golden/c2c.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
%lang starknet
%builtins pedersen range_check bitwise

from evm.array import validate_array
from evm.calls import calldataload, calldatasize, warp_call, warp_static_call
from evm.exec_env import ExecutionEnvironment
from evm.memory import uint256_mload, uint256_mstore
Expand All @@ -27,6 +28,7 @@ end
@constructor
func constructor{range_check_ptr}(calldata_size, calldata_len, calldata : felt*):
alloc_locals
validate_array(calldata_len, calldata)
let (memory_dict) = default_dict_new(0)
let memory_dict_start = memory_dict
let msize = 0
Expand All @@ -42,6 +44,7 @@ func __main{range_check_ptr, syscall_ptr : felt*}(
calldata_size, calldata_len, calldata : felt*) -> (
returndata_size, returndata_len, returndata : felt*):
alloc_locals
validate_array(calldata_len, calldata)
let (__fp__, _) = get_fp_and_pc()
local exec_env_ : ExecutionEnvironment = ExecutionEnvironment(calldata_size=calldata_size, calldata_len=calldata_len, calldata=calldata, returndata_size=0, returndata_len=0, returndata=cast(0, felt*), to_returndata_size=0, to_returndata_len=0, to_returndata=cast(0, felt*))
let exec_env : ExecutionEnvironment* = &exec_env_
Expand Down
File renamed without changes.
Loading