Skip to content

Commit

Permalink
Implement balance (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
xermicus authored Jun 3, 2024
1 parent 1ba806b commit 5ff17da
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 4 deletions.
4 changes: 4 additions & 0 deletions crates/integration/contracts/Value.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ contract Value {
function value() public payable returns (uint ret) {
ret = msg.value;
}

function balance_of(address _address) public view returns (uint ret) {
ret = _address.balance;
}
}
18 changes: 18 additions & 0 deletions crates/integration/src/cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ sol!(
}
);

sol!(
contract Value {
function balance_of(address _address) public view returns (uint ret);
}
);

impl Contract {
/// Execute the contract.
///
Expand Down Expand Up @@ -490,6 +496,18 @@ impl Contract {
calldata: Default::default(),
}
}

pub fn value_balance_of(address: Address) -> Self {
let code = include_str!("../contracts/Value.sol");
let name = "Value";

Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Value::balance_ofCall::new((address,)).abi_encode(),
}
}
}

#[cfg(test)]
Expand Down
29 changes: 29 additions & 0 deletions crates/integration/src/mock_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,10 @@ impl State {
pub fn accounts(&self) -> &HashMap<Address, Account> {
&self.accounts
}

pub fn accounts_mut(&mut self) -> &mut HashMap<Address, Account> {
&mut self.accounts
}
}

fn link_host_functions(engine: &Engine) -> Linker<Transaction> {
Expand Down Expand Up @@ -902,6 +906,31 @@ fn link_host_functions(engine: &Engine) -> Linker<Transaction> {
)
.unwrap();

linker
.func_wrap(
runtime_api::imports::BALANCE,
|caller: Caller<Transaction>, address_ptr: u32, balance_ptr: u32| -> Result<(), Trap> {
let (mut 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());
let balance = transaction
.state
.accounts()
.get(&address)
.map(|account| account.value)
.unwrap_or(U256::default());

caller.write_memory(balance_ptr, &balance.to_le_bytes::<32>())?;

log::info!("account {address} balance {balance}");

Ok(())
},
)
.unwrap();

linker
}

Expand Down
25 changes: 25 additions & 0 deletions crates/integration/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,3 +565,28 @@ fn mcopy() {

assert_eq!(expected, received);
}

#[test]
fn balance() {
let (_, output) = assert_success(&Contract::value_balance_of(Default::default()), false);

let expected = U256::ZERO;
let received = U256::from_be_slice(&output.data);
assert_eq!(expected, received);

let expected = U256::from(54589);
let (mut state, address) = State::new_deployed(Contract::value_balance_of(Default::default()));
state.accounts_mut().get_mut(&address).unwrap().value = expected;

let contract = Contract::value_balance_of(address);
let (_, output) = state
.transaction()
.with_default_account(&contract.pvm_runtime)
.calldata(contract.calldata)
.call();

assert_eq!(ReturnFlags::Success, output.flags);

let received = U256::from_be_slice(&output.data);
assert_eq!(expected, received)
}
5 changes: 4 additions & 1 deletion crates/llvm-context/src/polkavm/const/runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ pub mod exports {
pub mod imports {
pub static ADDRESS: &str = "address";

pub static BALANCE: &str = "balance";

pub static BLOCK_NUMBER: &str = "block_number";

pub static CALL: &str = "seal_call";
Expand Down Expand Up @@ -45,8 +47,9 @@ pub mod imports {

/// All imported runtime API symbols.
/// Useful for configuring common attributes and linkage.
pub static IMPORTS: [&str; 15] = [
pub static IMPORTS: [&str; 16] = [
ADDRESS,
BALANCE,
BLOCK_NUMBER,
CALL,
CALLER,
Expand Down
26 changes: 23 additions & 3 deletions crates/llvm-context/src/polkavm/evm/ether_gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,31 @@ where

/// Translates the `balance` instructions.
pub fn balance<'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 balance_pointer = context.build_alloca(context.word_type(), "balance_pointer");
let address_pointer = context.build_alloca(context.word_type(), "address_pointer");
context.build_store(address_pointer, address)?;

let balance = context.builder().build_ptr_to_int(
balance_pointer.value,
context.xlen_type(),
"balance",
)?;
let address = context.builder().build_ptr_to_int(
address_pointer.value,
context.xlen_type(),
"address",
)?;

context.build_runtime_call(
runtime_api::imports::BALANCE,
&[address.into(), balance.into()],
);

context.build_load(balance_pointer, "balance")
}

0 comments on commit 5ff17da

Please sign in to comment.