sui_move_natives_v1/
address.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::NativesCostTable;
5use move_binary_format::errors::PartialVMResult;
6use move_core_types::{account_address::AccountAddress, gas_algebra::InternalGas, u256::U256};
7use move_vm_runtime::{native_charge_gas_early_exit, native_functions::NativeContext};
8use move_vm_types::{
9    loaded_data::runtime_types::Type, natives::function::NativeResult, pop_arg, values::Value,
10};
11use smallvec::smallvec;
12use std::collections::VecDeque;
13
14const E_ADDRESS_PARSE_ERROR: u64 = 0;
15#[derive(Clone)]
16pub struct AddressFromBytesCostParams {
17    /// addresses are constant size, so base cost suffices
18    pub address_from_bytes_cost_base: InternalGas,
19}
20/***************************************************************************************************
21 * native fun from_bytes
22 * Implementation of the Move native function `address::from_bytes(bytes: vector<u8>)`
23 *   gas cost: address_from_bytes_cost_base                                        | addresses are constant size, so base cost suffices
24 **************************************************************************************************/
25pub fn from_bytes(
26    context: &mut NativeContext,
27    ty_args: Vec<Type>,
28    mut args: VecDeque<Value>,
29) -> PartialVMResult<NativeResult> {
30    debug_assert!(ty_args.is_empty());
31    debug_assert!(args.len() == 1);
32
33    let address_from_bytes_cost_params = context
34        .extensions_mut()
35        .get::<NativesCostTable>()
36        .address_from_bytes_cost_params
37        .clone();
38
39    // Charge base fee
40    native_charge_gas_early_exit!(
41        context,
42        address_from_bytes_cost_params.address_from_bytes_cost_base
43    );
44
45    let addr_bytes = pop_arg!(args, Vec<u8>);
46    let cost = context.gas_used();
47
48    // Address parsing can fail if fed the incorrect number of bytes.
49    Ok(match AccountAddress::from_bytes(addr_bytes) {
50        Ok(addr) => NativeResult::ok(cost, smallvec![Value::address(addr)]),
51        Err(_) => NativeResult::err(cost, E_ADDRESS_PARSE_ERROR),
52    })
53}
54#[derive(Clone)]
55pub struct AddressToU256CostParams {
56    /// addresses and u256 are constant size, so base cost suffices
57    pub address_to_u256_cost_base: InternalGas,
58}
59/***************************************************************************************************
60 * native fun to_u256
61 * Implementation of the Move native function `address::to_u256(address): u256`
62 *   gas cost:  address_to_u256_cost_base                   | addresses and u256 are constant size, so base cost suffices
63 **************************************************************************************************/
64pub fn to_u256(
65    context: &mut NativeContext,
66    ty_args: Vec<Type>,
67    mut args: VecDeque<Value>,
68) -> PartialVMResult<NativeResult> {
69    debug_assert!(ty_args.is_empty());
70    debug_assert!(args.len() == 1);
71
72    let address_to_u256_cost_params = context
73        .extensions_mut()
74        .get::<NativesCostTable>()
75        .address_to_u256_cost_params
76        .clone();
77
78    // Charge flat cost
79    native_charge_gas_early_exit!(
80        context,
81        address_to_u256_cost_params.address_to_u256_cost_base
82    );
83
84    let addr = pop_arg!(args, AccountAddress);
85    let mut addr_bytes_le = addr.to_vec();
86    addr_bytes_le.reverse();
87
88    // unwrap safe because we know addr_bytes_le is length 32
89    let u256_val = Value::u256(U256::from_le_bytes(&addr_bytes_le.try_into().unwrap()));
90    Ok(NativeResult::ok(context.gas_used(), smallvec![u256_val]))
91}
92
93#[derive(Clone)]
94pub struct AddressFromU256CostParams {
95    /// addresses and u256 are constant size, so base cost suffices
96    pub address_from_u256_cost_base: InternalGas,
97}
98/***************************************************************************************************
99 * native fun from_u256
100 * Implementation of the Move native function `address::from_u256(u256): address`
101 *   gas cost: address_from_u256_cost_base              | addresses and u256 are constant size, so base cost suffices
102 **************************************************************************************************/
103pub fn from_u256(
104    context: &mut NativeContext,
105    ty_args: Vec<Type>,
106    mut args: VecDeque<Value>,
107) -> PartialVMResult<NativeResult> {
108    debug_assert!(ty_args.is_empty());
109    debug_assert!(args.len() == 1);
110
111    let address_from_u256_cost_params = context
112        .extensions_mut()
113        .get::<NativesCostTable>()
114        .address_from_u256_cost_params
115        .clone();
116
117    // charge flat fee
118    native_charge_gas_early_exit!(
119        context,
120        address_from_u256_cost_params.address_from_u256_cost_base
121    );
122
123    let u256 = pop_arg!(args, U256);
124    let mut u256_bytes = u256.to_le_bytes().to_vec();
125    u256_bytes.reverse();
126
127    // unwrap safe because we are passing a 32 byte slice
128    let addr_val = Value::address(AccountAddress::from_bytes(&u256_bytes[..]).unwrap());
129    Ok(NativeResult::ok(context.gas_used(), smallvec![addr_val]))
130}