mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-09 20:01:05 +00:00
@@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
contract ExtCode {
|
||||
function ExtCodeSize(address who) public view returns (uint ret) {
|
||||
assembly {
|
||||
ret := extcodesize(who)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ pub static BLOCK_NUMBER: &str = "block_number";
|
||||
|
||||
pub static CALLER: &str = "caller";
|
||||
|
||||
pub static CODE_SIZE: &str = "code_size";
|
||||
|
||||
pub static DEPOSIT_EVENT: &str = "deposit_event";
|
||||
|
||||
pub static GET_STORAGE: &str = "get_storage";
|
||||
@@ -36,7 +38,7 @@ pub static VALUE_TRANSFERRED: &str = "value_transferred";
|
||||
|
||||
/// All imported runtime API symbols..
|
||||
/// Useful for configuring common attributes and linkage.
|
||||
pub static IMPORTS: [&str; 11] = [
|
||||
pub static IMPORTS: [&str; 12] = [
|
||||
ADDRESS,
|
||||
BLOCK_NUMBER,
|
||||
CALLER,
|
||||
@@ -44,6 +46,7 @@ pub static IMPORTS: [&str; 11] = [
|
||||
GET_STORAGE,
|
||||
HASH_KECCAK_256,
|
||||
INPUT,
|
||||
INSTANTIATE,
|
||||
NOW,
|
||||
RETURN,
|
||||
SET_STORAGE,
|
||||
|
||||
@@ -1,17 +1,36 @@
|
||||
//! Translates the external code operations.
|
||||
|
||||
use inkwell::values::BasicValue;
|
||||
|
||||
use crate::polkavm::context::Context;
|
||||
use crate::polkavm::Dependency;
|
||||
use crate::polkavm_const::runtime_api;
|
||||
|
||||
/// Translates the `extcodesize` instruction.
|
||||
pub fn size<'ctx, D>(
|
||||
_context: &mut Context<'ctx, D>,
|
||||
_address: inkwell::values::IntValue<'ctx>,
|
||||
context: &mut Context<'ctx, D>,
|
||||
address: inkwell::values::IntValue<'ctx>,
|
||||
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
todo!()
|
||||
let address_pointer = context.build_alloca(context.word_type(), "value");
|
||||
context.build_store(address_pointer, address)?;
|
||||
|
||||
let address_pointer_casted = context.builder().build_ptr_to_int(
|
||||
address_pointer.value,
|
||||
context.xlen_type(),
|
||||
"address_pointer",
|
||||
)?;
|
||||
let value = context
|
||||
.build_runtime_call(runtime_api::CODE_SIZE, &[address_pointer_casted.into()])
|
||||
.unwrap_or_else(|| panic!("{} should return a value", runtime_api::CODE_SIZE))
|
||||
.into_int_value();
|
||||
|
||||
Ok(context
|
||||
.builder()
|
||||
.build_int_z_extend(value, context.word_type(), "extcodesize")?
|
||||
.as_basic_value_enum())
|
||||
}
|
||||
|
||||
/// Translates the `extcodehash` instruction.
|
||||
|
||||
@@ -73,6 +73,8 @@ POLKAVM_IMPORT(uint32_t, is_contract, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, code_hash, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, code_size, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, own_code_hash, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, caller_is_origin)
|
||||
|
||||
@@ -87,9 +87,9 @@ impl Error {
|
||||
│ usually needed in the following cases: │
|
||||
│ 1. To detect whether an address belongs to a smart contract. │
|
||||
│ 2. To detect whether the deploy code execution has finished. │
|
||||
│ zkSync Era comes with native account abstraction support (so accounts are smart contracts, │
|
||||
│ including private-key controlled EOAs), and you should avoid differentiating between contracts │
|
||||
│ and non-contract addresses. │
|
||||
│ Polkadot comes with native account abstraction support (so smart contracts are just accounts │
|
||||
│ coverned by code), and you should avoid differentiating between contracts and non-contract |
|
||||
| addresses. │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────┘"#
|
||||
.to_owned();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user