Handle a request

The handleRequest function is used to simulate a law's execution without actually performing state changes. This is crucial for validating actions before they are executed.

Simulation Process

1. Function Signature

function handleRequest(
    address caller,
    address powers,
    uint16 lawId,
    bytes memory lawCalldata,
    uint256 nonce
) public view virtual returns (
    uint256 actionId,
    address[] memory targets,
    uint256[] memory values,
    bytes[] memory calldatas,
    bytes memory stateChange
)

2. Simulation Steps

Action ID Generation

actionId = LawUtilities.hashActionId(lawId, lawCalldata, nonce);

Parameter Processing

  • Decode and validate input parameters

  • Check parameter constraints

  • Verify parameter relationships

Target Preparation

  • Determine target contracts

  • Prepare call data

  • Calculate required values

State Change Simulation

  • Simulate state changes

  • Validate state transitions

  • Prepare state change data

Implementation Requirements

1. View Function

  • Must be a view function

  • Cannot modify state

  • Must return all necessary data

2. Return Values

  • actionId: Unique identifier for the action

  • targets: Array of target contract addresses

  • values: Array of ETH values to send

  • calldatas: Array of encoded function calls

  • stateChange: Encoded state changes

3. Validation

  • Validate all input parameters

  • Check execution conditions

  • Verify state consistency

  • Ensure proper data formatting

Best Practices

  1. Simulation Accuracy

    • Accurately simulate all state changes

    • Consider all edge cases

    • Validate all conditions

    • Check all constraints

  2. Gas Optimization

    • Minimize memory usage

    • Use efficient data structures

    • Cache frequently accessed values

    • Optimize array operations

  3. Error Handling

    • Validate all inputs

    • Check all conditions

    • Provide clear error messages

    • Handle edge cases

  4. Security

    • Validate all parameters

    • Check for potential exploits

    • Verify data integrity

    • Protect against manipulation

Example Implementation

function handleRequest(
    address caller,
    address powers,
    uint16 lawId,
    bytes memory lawCalldata,
    uint256 nonce
) public view virtual override returns (
    uint256 actionId,
    address[] memory targets,
    uint256[] memory values,
    bytes[] memory calldatas,
    bytes memory stateChange
) {
    // Generate action ID
    actionId = LawUtilities.hashActionId(lawId, lawCalldata, nonce);
    
    // Decode parameters
    (address target, uint256 value, bytes memory data) = abi.decode(
        lawCalldata,
        (address, uint256, bytes)
    );
    
    // Validate parameters
    require(target != address(0), "Invalid target");
    require(value <= maxValue, "Value too high");
    
    // Prepare targets
    targets = new address[](1);
    targets[0] = target;
    
    // Prepare values
    values = new uint256[](1);
    values[0] = value;
    
    // Prepare calldatas
    calldatas = new bytes[](1);
    calldatas[0] = data;
    
    // Simulate state changes
    stateChange = abi.encode(
        simulateStateChange(target, value, data)
    );
    
    return (actionId, targets, values, calldatas, stateChange);
}

Common Pitfalls

  1. State Modification

    • Attempting to modify state in a view function

    • Using non-view functions in simulation

    • Modifying storage variables

  2. Gas Estimation

    • Not considering gas costs

    • Creating unnecessarily large arrays

    • Using inefficient data structures

  3. Validation

    • Missing parameter validation

    • Incomplete condition checks

    • Insufficient error handling

  4. Data Formatting

    • Incorrect data encoding

    • Mismatched array lengths

    • Invalid parameter types

Last updated