Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions substrate/runtime/contract/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

use super::{CodeOf, ContractAddressFor, Module, Trait};
use super::{CodeOf, MaxDepth, ContractAddressFor, Module, Trait};
use account_db::{AccountDb, OverlayAccountDb};
use gas::GasMeter;
use vm;

use rstd::prelude::*;
use runtime_primitives::traits::{Zero, CheckedAdd, CheckedSub};
use runtime_support::StorageMap;
use runtime_support::{StorageMap, StorageValue};
use staking;
use system;

Expand Down Expand Up @@ -50,15 +50,17 @@ impl<'a, T: Trait> ExecutionContext<'a, T> {
gas_meter: &mut GasMeter<T>,
_data: &[u8],
) -> Result<CallReceipt, &'static str> {
let dest_code = <CodeOf<T>>::get(&dest);

// TODO: check the new depth
if self.depth == <MaxDepth<T>>::get() as usize {
return Err("reached maximum depth, cannot make a call");
}

let call_base_fee = <Module<T>>::call_base_fee();
if gas_meter.charge(call_base_fee).is_out_of_gas() {
return Err("not enough gas to pay base call fee");
}

let dest_code = <CodeOf<T>>::get(&dest);

let (exec_result, change_set) = {
let mut overlay = OverlayAccountDb::new(&self.overlay);

Expand Down Expand Up @@ -112,6 +114,10 @@ impl<'a, T: Trait> ExecutionContext<'a, T> {
ctor: &[u8],
_data: &[u8],
) -> Result<CreateReceipt<T>, &'static str> {
if self.depth == <MaxDepth<T>>::get() as usize {
return Err("reached maximum depth, cannot create");
}

let create_base_fee = <Module<T>>::create_base_fee();
if gas_meter.charge(create_base_fee).is_out_of_gas() {
return Err("not enough gas to pay base create fee");
Expand Down
34 changes: 33 additions & 1 deletion substrate/runtime/contract/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ fn new_test_ext(existential_deposit: u64, gas_price: u64) -> runtime_io::TestExt
call_base_fee: 135,
create_base_fee: 175,
gas_price,
max_depth: 1024,
max_depth: 100,
}.build_storage()
.unwrap(),
);
Expand Down Expand Up @@ -221,6 +221,38 @@ fn contract_transfer_oog() {

}

#[test]
fn contract_transfer_max_depth() {
const CONTRACT_SHOULD_TRANSFER_TO: u64 = 9;

let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap();

with_externalities(&mut new_test_ext(0, 2), || {
<CodeOf<Test>>::insert(CONTRACT_SHOULD_TRANSFER_TO, code_transfer.to_vec());

Staking::set_free_balance(&0, 100_000_000);
Staking::set_free_balance(&CONTRACT_SHOULD_TRANSFER_TO, 11);

assert_err!(
Contract::call(&0, CONTRACT_SHOULD_TRANSFER_TO, 3, 100_000, Vec::new()),
"vm execute returned error while call"
);

assert_eq!(
Staking::free_balance(&0),
// 3 - value sent with the transaction
// 2 * 6 * 100 - gas used by the contract (6) multiplied by gas price (2)
// multiplied by max depth (100).
// 2 * 135 * 100 - base gas fee for call (by transaction) multiplied by max depth (100).
100_000_000 - (2 * 135 * 100) - (2 * 6 * 100),
);
assert_eq!(
Staking::free_balance(&CONTRACT_SHOULD_TRANSFER_TO),
11,
);
});
}

/// Convert a byte slice to a string with hex values.
///
/// Each value is preceeded with a `\` character.
Expand Down