Skip to content

Commit

Permalink
refactor: Test msg sender, value for all msg calls
Browse files Browse the repository at this point in the history
This restructures the tests to confirm the expected msg.value and
msg.sender with various different message call types, e.g. call,
delegatecall, callcode, staticcall.

The storage tests are also split up so that they are independent set of
tests to keep different types of tests separate and reduce clutter with
the slight increase in redundancy in the test logic.
  • Loading branch information
drklee3 committed Oct 24, 2024
1 parent c437a06 commit 38f7cc5
Show file tree
Hide file tree
Showing 6 changed files with 496 additions and 188 deletions.
42 changes: 38 additions & 4 deletions tests/e2e-evm/contracts/ABI_BasicTests.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,19 @@ pragma solidity ^0.8.24;
// Low level caller
//
contract Caller {
/**
* @dev Call a function via CALL with the current msg.value
*/
function functionCall(address payable to, bytes calldata data) external payable {
(bool success, bytes memory result) = to.call{value: msg.value}(data);
this.functionCallWithValue(to, msg.value, data);
}

/**
* @dev Call a function via CALL with a specific value that may be different
* from the current msg.value
*/
function functionCallWithValue(address payable to, uint256 value, bytes calldata data) public payable {
(bool success, bytes memory result) = to.call{value: value}(data);

if (!success) {
// solhint-disable-next-line gas-custom-errors
Expand All @@ -30,7 +41,18 @@ contract Caller {
}
}

/**
* @dev Call a contract function via CALLCODE with the current msg.value
*/
function functionCallCode(address to, bytes calldata data) external payable {
this.functionCallCodeWithValue(to, msg.value, data);
}

/**
* @dev Call a contract function via CALLCODE with a specific value that may
* be different from the current msg.value
*/
function functionCallCodeWithValue(address to, uint256 value, bytes calldata data) external payable {
// solhint-disable-next-line no-inline-assembly
assembly {
// Copy the calldata to memory, as callcode uses memory pointers.
Expand All @@ -49,7 +71,7 @@ contract Caller {
let result := callcode(
gas(), // gas
to, // to address
callvalue(), // value
value, // value to send
0, // in - pointer to start of input, 0 since we copied the data to 0
data.length, // insize - size of the input
0, // out
Expand Down Expand Up @@ -80,7 +102,12 @@ contract Caller {
}
}

function functionDelegateCall(address to, bytes calldata data) external {
/**
* @dev Call a contract function via DELEGATECALL with the current msg.value
* and current msg.sender. DELEGATECALL cannot specify a different
* value.
*/
function functionDelegateCall(address to, bytes calldata data) external payable {
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory result) = to.delegatecall(data);

Expand All @@ -95,7 +122,12 @@ contract Caller {
}
}

function functionStaticCall(address to, bytes calldata data) external view {
/**
* @dev Call a contract function via STATICCALL with the current msg.value
* and current msg.sender.
* @return The result of the static call in bytes.
*/
function functionStaticCall(address to, bytes calldata data) external view returns (bytes memory) {
(bool success, bytes memory result) = to.staticcall(data);

if (!success) {
Expand All @@ -107,6 +139,8 @@ contract Caller {
revert(add(32, result), mload(result))
}
}

return result;
}
}

Expand Down
14 changes: 0 additions & 14 deletions tests/e2e-evm/contracts/ABI_CallCodeTest.sol

This file was deleted.

4 changes: 4 additions & 0 deletions tests/e2e-evm/contracts/ABI_DisabledTests.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ contract NoopDisabledMock is ABI_BasicTests.NoopReceivePayableFallback {
function noopPayable() external payable {
mockRevert();
}
/**
* @dev This function is intentionally not marked as pure to test the
* behavior of view functions in disabled contracts.
*/
// solc-ignore-next-line func-mutability
function noopView() external view {
mockRevert();
Expand Down
37 changes: 37 additions & 0 deletions tests/e2e-evm/contracts/ContextInspector.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/**
* @title A contract to inspect the msg context.
* @notice This contract is used to test the expected msg.sender and msg.value
* of a contract call in various scenarios.
*/
contract ContextInspector {
/**
* @dev Emitted when the emitMsgSender() function is called.
*/
event MsgSender(address sender);

/**
* @dev Emitted when the emitMsgValue() function is called.
*
* Note that `value` may be zero.
*/
event MsgValue(uint256 value);

function emitMsgSender() external {
emit MsgSender(msg.sender);
}

function emitMsgValue() external payable {
emit MsgValue(msg.value);
}

/**
* @dev Returns the current msg.sender. This is primarily used for testing
* staticcall as events are not emitted.
*/
function getMsgSender() external view returns (address) {
return msg.sender;
}
}
15 changes: 15 additions & 0 deletions tests/e2e-evm/contracts/StorageTests.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/**
* @title A basic contract with a storage value.
* @notice This contract is used to test storage reads and writes, primarily
* for testing storage behavior in delegateCall.
*/
contract StorageBasic {
uint256 public storageValue;

function setStorageValue(uint256 value) external {
storageValue = value;
}
}
Loading

0 comments on commit 38f7cc5

Please sign in to comment.