From d856d2a3c9d176c446eb447e7f3c208ada87d807 Mon Sep 17 00:00:00 2001 From: Daniel Perez Date: Thu, 21 Nov 2024 12:19:33 +0000 Subject: [PATCH] Add transfer method to address --- CHANGELOG.md | 2 ++ src/interpreter/builtins/address.rs | 35 +++++++++++++++++++++++++---- src/interpreter/builtins/mod.rs | 1 + src/interpreter/builtins/repl.rs | 14 +++++++----- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a561ec..cfc776a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,12 @@ * Add `repl.startPrank` / `repl.stopPrank` to start/stop impersonating an address * Add `FUNC.traceCall` method to contract functions * Add `abi.decodeData` to decode function calldata and errors from any known ABI +* Add `address.transfer` to send ETH to an address ### Other changes * Encode `FixedBytes` as with zero padding on the left instead of the right +* Allow to load a private key from `bytes32` ## v0.1.3 (2024-08-15) diff --git a/src/interpreter/builtins/address.rs b/src/interpreter/builtins/address.rs index c58e806..2f88faa 100644 --- a/src/interpreter/builtins/address.rs +++ b/src/interpreter/builtins/address.rs @@ -1,13 +1,16 @@ use std::sync::Arc; -use alloy::{providers::Provider, transports::BoxFuture}; -use anyhow::Result; +use alloy::{ + network::TransactionBuilder, providers::Provider, rpc::types::TransactionRequest, + transports::BoxFuture, +}; +use anyhow::{anyhow, Result}; use futures::FutureExt; use lazy_static::lazy_static; use crate::interpreter::{ - functions::{AsyncProperty, FunctionDef}, - Env, Value, + functions::{AsyncMethod, AsyncProperty, FunctionDef, FunctionParam}, + Env, Type, Value, }; fn get_balance<'a>(env: &'a Env, receiver: &'a Value) -> BoxFuture<'a, Result> { @@ -22,7 +25,31 @@ fn get_balance<'a>(env: &'a Env, receiver: &'a Value) -> BoxFuture<'a, Result( + env: &'a mut Env, + receiver: &'a Value, + args: &'a [Value], +) -> BoxFuture<'a, Result> { + async move { + let provider = env.get_provider(); + let value = args + .first() + .ok_or(anyhow!("Missing value")) + .and_then(|v| v.as_u256())?; + let addr = receiver.as_address()?; + let tx_req = TransactionRequest::default().with_to(addr).value(value); + let tx = provider.send_transaction(tx_req).await?; + Ok(Value::Transaction(*tx.tx_hash())) + } + .boxed() +} + lazy_static! { pub static ref ADDRESS_BALANCE: Arc = AsyncProperty::arc("balance", get_balance); + pub static ref ADDRESS_TRANSFER: Arc = AsyncMethod::arc( + "transfer", + transfer, + vec![vec![FunctionParam::new("amount", Type::Uint(256))]] + ); } diff --git a/src/interpreter/builtins/mod.rs b/src/interpreter/builtins/mod.rs index 36d7222..92d9d6c 100644 --- a/src/interpreter/builtins/mod.rs +++ b/src/interpreter/builtins/mod.rs @@ -98,6 +98,7 @@ lazy_static! { let mut addr_methods = HashMap::new(); addr_methods.insert("format".to_string(), format::NON_NUM_FORMAT.clone()); addr_methods.insert("balance".to_string(), address::ADDRESS_BALANCE.clone()); + addr_methods.insert("transfer".to_string(), address::ADDRESS_TRANSFER.clone()); m.insert(NonParametricType::Address, addr_methods); let mut transaction_methods = HashMap::new(); diff --git a/src/interpreter/builtins/repl.rs b/src/interpreter/builtins/repl.rs index ec5fcf4..94ad069 100644 --- a/src/interpreter/builtins/repl.rs +++ b/src/interpreter/builtins/repl.rs @@ -146,12 +146,12 @@ fn get_default_sender(env: &Env) -> Value { } fn load_private_key(env: &mut Env, _receiver: &Value, args: &[Value]) -> Result { - let key = match args { - [Value::Str(key)] => key.clone(), - [] => rpassword::prompt_password("Enter private key: ")?, + let signer: PrivateKeySigner = match args { + [Value::Str(key)] => key.parse()?, + [Value::FixBytes(bytes, 32)] => PrivateKeySigner::from_bytes(bytes)?, + [] => rpassword::prompt_password("Enter private key: ")?.parse()?, _ => bail!("loadPrivateKey: invalid arguments"), }; - let signer: PrivateKeySigner = key.parse()?; env.set_signer(signer)?; Ok(get_default_sender(env)) } @@ -318,7 +318,11 @@ lazy_static! { pub static ref REPL_LOAD_PRIVATE_KEY: Arc = SyncMethod::arc( "loadPrivateKey", load_private_key, - vec![vec![], vec![FunctionParam::new("privateKey", Type::String)]] + vec![ + vec![], + vec![FunctionParam::new("privateKey", Type::String)], + vec![FunctionParam::new("privateKey", Type::FixBytes(32))] + ] ); pub static ref REPL_LOAD_KEYSTORE: Arc = SyncMethod::arc( "loadKeystore",