implement EXTCODESIZE

Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
xermicus
2024-05-22 22:56:03 +02:00
parent 06aa289d9b
commit 5138fe3d06
8 changed files with 100 additions and 8 deletions
+19 -1
View File
@@ -1,4 +1,4 @@
use alloy_primitives::{I256, U256};
use alloy_primitives::{Address, I256, U256};
use alloy_sol_types::{sol, SolCall, SolConstructor};
use crate::mock_runtime::{CallOutput, State};
@@ -123,6 +123,12 @@ sol!(
}
);
sol!(
contract ExtCode {
function ExtCodeSize(address who) public view returns (uint ret);
}
);
impl Contract {
/// Execute the contract.
///
@@ -405,6 +411,18 @@ impl Contract {
calldata: vec![0; 4],
}
}
pub fn ext_code_size(address: Address) -> Self {
let code = include_str!("../contracts/ExtCode.sol");
let name = "ExtCode";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: ExtCode::ExtCodeSizeCall::new((address,)).abi_encode(),
}
}
}
#[cfg(test)]
+24
View File
@@ -730,6 +730,30 @@ fn link_host_functions(engine: &Engine) -> Linker<Transaction> {
)
.unwrap();
linker
.func_wrap(
runtime_api::CODE_SIZE,
|caller: Caller<Transaction>, address_ptr: u32| {
let (caller, transaction) = caller.split();
let bytes = caller.read_memory_into_vec(address_ptr, 32)?;
let word = U256::from_le_slice(&bytes);
let address = Address::from_word(word.into());
log::info!("{}", address);
Ok(transaction
.state
.accounts
.get(&address)
.and_then(|account| account.contract)
.and_then(|blob_hash| transaction.state.blobs.get(&blob_hash))
.map(|code| code.len())
.unwrap_or_default() as u32)
},
)
.unwrap();
linker
}
+15
View File
@@ -507,3 +507,18 @@ fn create_with_value() {
}
}
}
#[test]
fn ext_code_size() {
let contract = Contract::ext_code_size(Transaction::default_address());
let (_, output) = assert_success(&contract, false);
let received = U256::from_be_slice(&output.data);
let expected = U256::from(contract.pvm_runtime.len());
assert_eq!(received, expected);
let contract = Contract::ext_code_size(Default::default());
let (_, output) = assert_success(&contract, false);
let received = U256::from_be_slice(&output.data);
let expected = U256::ZERO;
assert_eq!(received, expected);
}