Skip to content
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
8 changes: 4 additions & 4 deletions crates/integration/contracts/MLoad.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pragma solidity ^0.8.28;
"dest": {
"Instantiated": 0
},
"data": "e2179b8e"
"data": "0be0e4a60000000000000000000000000000000000000000000000000000000000000000"
}
}
]
Expand All @@ -29,12 +29,12 @@ pragma solidity ^0.8.28;

contract MLoad {
constructor() payable {
assert(g() == 0);
assert(loadAt(0) == 0);
}

function g() public payable returns (uint m) {
function loadAt(uint _offset) public payable returns (uint m) {
assembly {
m := mload(0)
m := mload(_offset)
}
}
}
9 changes: 9 additions & 0 deletions crates/integration/src/cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ sol!(
);
case!("MCopy.sol", MCopy, memcpyCall, memcpy, payload: Bytes);

sol!(
contract MLoad {
constructor() payable;

function loadAt(uint _offset) public payable returns (uint m);
}
);
case!("MLoad.sol", MLoad, loadAtCall, load_at, _offset: U256);

sol!(
contract Call {
function value_transfer(address payable destination) public payable;
Expand Down
38 changes: 38 additions & 0 deletions crates/integration/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,3 +714,41 @@ fn invalid_opcode_works() {

assert_eq!(result.weight_consumed, GAS_LIMIT);
}

/// Load from heap memory using an out of bounds offset and expect the
/// contract to hit the `invalid` syscall to use all gas (like on EVM).
///
/// The offset is picked such that a regular truncate would be in bounds.
#[test]
fn safe_truncate_int_to_xlen_works() {
let offset = 0x10000000_00000000u64;
let data = Contract::load_at(Uint::from(offset)).calldata;
let mut actions = instantiate("contracts/MLoad.sol", "MLoad");
actions.append(&mut vec![
Call {
origin: TestAddress::Alice,
dest: TestAddress::Instantiated(0),
value: 0,
gas_limit: None,
storage_deposit_limit: None,
data,
},
VerifyCall(VerifyCallExpectation {
success: false,
..Default::default()
}),
]);

let results = Specs {
actions,
differential: true,
..Default::default()
}
.run();

let CallResult::Exec { result, .. } = results.last().unwrap() else {
unreachable!()
};

assert_eq!(result.weight_consumed, GAS_LIMIT);
}
Loading