Skip to content

Commit 3c03b9c

Browse files
committed
Add a few corrections and formatting.
1 parent a81fa68 commit 3c03b9c

File tree

5 files changed

+66
-50
lines changed

5 files changed

+66
-50
lines changed

linera-base/src/data_types.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,12 @@ impl From<Amount> for U256 {
8888
}
8989
}
9090

91-
/// Converting amount from `U256` to Amount can fail since
92-
/// `Amount` is a `u128`.
91+
/// Error converting from `U256` to `Amount`.
92+
/// This can fail since `Amount` is a `u128`.
9393
#[derive(Error, Debug)]
94+
#[error("Failed to convert U256 to Amount. {0} has more than 128 bits")]
9495
pub struct AmountConversionError(U256);
9596

96-
impl fmt::Display for AmountConversionError {
97-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98-
write!(f, "Amount conversion error for {}", self.0)
99-
}
100-
}
101-
10297
impl TryFrom<U256> for Amount {
10398
type Error = AmountConversionError;
10499
fn try_from(value: U256) -> Result<Amount, Self::Error> {

linera-execution/solidity/LineraTypes.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ Amount:
4848
TUPLEARRAY:
4949
CONTENT: U8
5050
SIZE: 32
51+
Account:
52+
STRUCT:
53+
- chain_id:
54+
TYPENAME: ChainId
55+
- owner:
56+
TYPENAME: AccountOwner
5157
AccountOwnerBalanceInner:
5258
STRUCT:
5359
- account_owner:
@@ -196,6 +202,13 @@ ContractRuntimePrecompile:
196202
- query: BYTES
197203
11:
198204
ValidationRound: UNIT
205+
12:
206+
Transfer:
207+
STRUCT:
208+
- account:
209+
TYPENAME: Account
210+
- amount:
211+
TYPENAME: Amount
199212
ServiceRuntimePrecompile:
200213
ENUM:
201214
0:

linera-execution/src/evm/database.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ pub(crate) struct DatabaseRuntime<Runtime> {
7777
/// This is the EVM address of the contract.
7878
/// At the creation, it is set to `Address::ZERO` and then later set to the correct value.
7979
pub contract_address: Address,
80-
/// The caller to the smart contract
80+
/// The caller to the smart contract.
8181
pub caller: Address,
82-
/// The value of the smart contract
82+
/// The value of the smart contract.
8383
pub value: U256,
8484
/// The runtime of the contract.
8585
pub runtime: Arc<Mutex<Runtime>>,
@@ -114,8 +114,8 @@ pub enum KeyCategory {
114114
}
115115

116116
impl<Runtime: BaseRuntime> DatabaseRuntime<Runtime> {
117-
/// Encode the `index` of the EVM storage associated to the smart contract
118-
/// in a linera key.
117+
/// Encodes the `index` of the EVM storage associated to the smart contract
118+
/// in a Linera key.
119119
fn get_linera_key(key_prefix: &[u8], index: U256) -> Vec<u8> {
120120
let mut key = key_prefix.to_vec();
121121
key.extend(index.as_le_slice());
@@ -211,7 +211,7 @@ where
211211
{
212212
type Error = ExecutionError;
213213

214-
/// The `basic_ref` is the function for reading the state of
214+
/// The `basic_ref` is the function for reading the state of the application.
215215
fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, ExecutionError> {
216216
if address == FAUCET_ADDRESS {
217217
return Ok(Some(AccountInfo {
@@ -435,7 +435,7 @@ where
435435
let timestamp_linera = runtime.read_system_timestamp()?;
436436
let timestamp_evm = timestamp_linera.micros() / 1_000_000;
437437
// The basefee is the minimum feee for executing. We have no such
438-
// concept in Linera
438+
// concept in Linera.
439439
let basefee = 0;
440440
let chain_id = runtime.chain_id()?;
441441
let entry = format!("{}{}", chain_id, block_height_linera);

linera-execution/src/evm/revm.rs

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use linera_base::{
1818
Amount, ApplicationDescription, Bytecode, Resources, SendMessageRequest, StreamUpdate,
1919
},
2020
ensure,
21-
identifiers::{Account, AccountOwner, ApplicationId, ChainId, StreamName},
21+
identifiers::{Account, AccountOwner, ApplicationId, ChainId, ModuleId, StreamName},
2222
vm::{EvmInstantiation, EvmOperation, EvmQuery, VmRuntime},
2323
};
2424
use revm::{primitives::Bytes, InspectCommitEvm, InspectEvm, Inspector};
@@ -350,10 +350,6 @@ fn get_precompile_argument<Ctx: ContextTr>(
350350
context: &mut Ctx,
351351
inputs: &InputsImpl,
352352
) -> Result<Vec<u8>, ExecutionError> {
353-
ensure!(
354-
inputs.call_value == U256::ZERO,
355-
EvmExecutionError::NoTransferInRuntimeCall
356-
);
357353
Ok(get_argument(context, &inputs.input))
358354
}
359355

@@ -764,6 +760,24 @@ impl<'a, Runtime: ContractRuntime> Inspector<Ctx<'a, Runtime>>
764760
}
765761

766762
impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
763+
/// Gets the expected `ApplicationId`.
764+
fn get_expected_application_id(runtime: &mut Runtime, module_id: ModuleId) -> Result<ApplicationId, ExecutionError> {
765+
let chain_id = runtime.chain_id()?;
766+
let block_height = runtime.block_height()?;
767+
let application_index = runtime.application_index()?;
768+
let parameters = JSON_EMPTY_VECTOR.to_vec(); // No constructor
769+
let required_application_ids = Vec::new();
770+
let application_description = ApplicationDescription {
771+
module_id,
772+
creator_chain_id: chain_id,
773+
block_height,
774+
application_index,
775+
parameters: parameters.clone(),
776+
required_application_ids,
777+
};
778+
Ok(ApplicationId::from(&application_description))
779+
}
780+
767781
/// The function `fn create` of the inspector trait is called
768782
/// when a contract is going to be instantiated. Since the
769783
/// function can have some error case which are not supported
@@ -866,7 +880,10 @@ impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
866880
} else {
867881
if inputs.value != U256::ZERO {
868882
// decrease the balance of the contract address by the expected amount.
869-
// We put the address as
883+
// We put the tokens in FAUCET_ADDRESS because we cannot transfer to
884+
// a contract that do not yet exist.
885+
// It is a common construction. We can see that in ERC20 contract code
886+
// for example for burning and minting.
870887
Self::revm_transfer(
871888
context,
872889
self.db.contract_address,
@@ -879,8 +896,6 @@ impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
879896
let mut runtime = context.db().0.runtime.lock().unwrap();
880897
let module_id = runtime.publish_module(contract, service, VmRuntime::Evm)?;
881898
let chain_id = runtime.chain_id()?;
882-
let block_height = runtime.block_height()?;
883-
let application_index = runtime.application_index()?;
884899
let application_id = runtime.application_id()?;
885900
let parameters = JSON_EMPTY_VECTOR.to_vec(); // No constructor
886901
let evm_call = EvmInstantiation {
@@ -889,15 +904,7 @@ impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
889904
};
890905
let argument = serde_json::to_vec(&evm_call)?;
891906
let required_application_ids = Vec::new();
892-
let application_description = ApplicationDescription {
893-
module_id,
894-
creator_chain_id: chain_id,
895-
block_height,
896-
application_index,
897-
parameters: parameters.clone(),
898-
required_application_ids: Vec::new(),
899-
};
900-
let expected_application_id = ApplicationId::from(&application_description);
907+
let expected_application_id = Self::get_expected_application_id(&mut runtime, module_id)?;
901908
if inputs.value != U256::ZERO {
902909
let amount = Amount::try_from(inputs.value).map_err(EvmExecutionError::from)?;
903910
let destination = Account {
@@ -969,18 +976,20 @@ impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
969976
let owner: AccountOwner = inputs.bytecode_address.into();
970977
if value != U256::ZERO {
971978
// In Linera, only non-zero transfers matter
972-
let mut runtime = context
973-
.db()
974-
.0
975-
.runtime
976-
.lock()
977-
.expect("The lock should be possible");
978-
let amount = Amount::try_from(value).map_err(EvmExecutionError::from)?;
979-
let chain_id = runtime.chain_id()?;
980-
let destination = Account { chain_id, owner };
981-
runtime.transfer(source, destination, amount)?;
979+
{
980+
let mut runtime = context
981+
.db()
982+
.0
983+
.runtime
984+
.lock()
985+
.expect("The lock should be possible");
986+
let amount = Amount::try_from(value).map_err(EvmExecutionError::from)?;
987+
let chain_id = runtime.chain_id()?;
988+
let destination = Account { chain_id, owner };
989+
runtime.transfer(source, destination, amount)?;
990+
}
991+
Self::revm_transfer(context, inputs.caller, inputs.target_address, value)?;
982992
}
983-
Self::revm_transfer(context, inputs.caller, inputs.target_address, value)?;
984993
}
985994
// Other smart contracts calls are handled by the runtime
986995
let target = address_to_user_application_id(inputs.target_address);
@@ -1027,13 +1036,11 @@ impl<Runtime: ContractRuntime> CallInterceptorContract<Runtime> {
10271036
destination: Address,
10281037
value: U256,
10291038
) -> Result<(), ExecutionError> {
1030-
if value != U256::ZERO {
1031-
// In Ethereum, all transfers matter
1032-
if let Some(error) = context.journal().transfer(source, destination, value)? {
1033-
let error = format!("{error:?}");
1034-
let error = EvmExecutionError::TransactError(error);
1035-
return Err(error.into());
1036-
}
1039+
// In Ethereum, all transfers matter
1040+
if let Some(error) = context.journal().transfer(source, destination, value)? {
1041+
let error = format!("{error:?}");
1042+
let error = EvmExecutionError::TransactError(error);
1043+
return Err(error.into());
10371044
}
10381045
Ok(())
10391046
}

linera-execution/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,8 @@ pub trait ContractRuntime: BaseRuntime {
865865
required_application_ids: Vec<ApplicationId>,
866866
) -> Result<ApplicationId, ExecutionError>;
867867

868-
/// Returns the current application_index.
868+
/// Returns the current application index, i.e. the number of new applications
869+
/// created so far in this block.
869870
fn application_index(&mut self) -> Result<u32, ExecutionError>;
870871

871872
/// Creates a new data blob and returns its hash.

0 commit comments

Comments
 (0)