Skip to content

feat(forge): implement vm.signTypedData cheatcode #10330

New issue

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

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

Already on GitHub? # to your account

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions crates/cheatcodes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ tracing.workspace = true
walkdir.workspace = true
proptest.workspace = true
serde.workspace = true

20 changes: 20 additions & 0 deletions crates/cheatcodes/assets/cheatcodes.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions crates/cheatcodes/spec/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2651,6 +2651,10 @@ interface Vm {
#[cheatcode(group = Crypto)]
function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);

/// Signs Human-Readable Typed Data with `privateKey` using the secp256k1 curve.
#[cheatcode(group = Crypto)]
function signTypedData(string calldata jsonData, uint256 privateKey) external pure returns (uint8 v, bytes32 r,bytes32 s);

/// Signs `digest` with `privateKey` using the secp256k1 curve.
///
/// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
Expand Down
11 changes: 11 additions & 0 deletions crates/cheatcodes/src/crypto.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Implementations of [`Crypto`](spec::Group::Crypto) Cheatcodes.

use crate::{Cheatcode, Cheatcodes, Result, Vm::*};
use alloy_dyn_abi::eip712::TypedData;
use alloy_primitives::{keccak256, Address, B256, U256};
use alloy_signer::{Signer, SignerSync};
use alloy_signer_local::{
Expand Down Expand Up @@ -51,6 +52,16 @@ impl Cheatcode for sign_0Call {
}
}

impl Cheatcode for signTypedDataCall {
fn apply(&self, _state: &mut Cheatcodes) -> Result {
let Self { jsonData, privateKey } = self;
let typed_data: TypedData = serde_json::from_str(jsonData)?;
let digest = typed_data.eip712_signing_hash()?;
let sig = sign(privateKey, &digest)?;
Ok(encode_full_sig(sig))
}
}

impl Cheatcode for signCompact_0Call {
fn apply(&self, _state: &mut Cheatcodes) -> Result {
let Self { wallet, digest } = self;
Expand Down
3 changes: 2 additions & 1 deletion crates/evm/traces/src/decoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,11 +457,12 @@ impl CallTraceDecoder {

Some(decoded.iter().map(format_token).collect())
}
"signDelegation" | "signAndAttachDelegation" => {
"signDelegation" | "signAndAttachDelegation" | "signTypedData" => {
let mut decoded = func.abi_decode_input(&data[SELECTOR_LEN..], false).ok()?;
// Redact private key and replace in trace for
// signAndAttachDelegation(address implementation, uint256 privateKey)
// signDelegation(address implementation, uint256 privateKey)
// signTypedData(string jsonData, uint256 privateKey)
decoded[1] = DynSolValue::String("<pk>".to_string());
Some(decoded.iter().map(format_token).collect())
}
Expand Down
1 change: 1 addition & 0 deletions testdata/cheats/Vm.sol

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading