Add initial contract macro benchmarks (#9600)

* Add erc20 benchmarks

* Fix typos

Co-authored-by: Michael Müller <michi@parity.io>

* Fix compilation issue on case sensitive fs

Co-authored-by: Michael Müller <michi@parity.io>
This commit is contained in:
Alexander Theißen
2021-09-06 13:30:28 +02:00
committed by GitHub
parent 61941f2806
commit 13f3e25ebb
8 changed files with 1560 additions and 13 deletions
@@ -0,0 +1,9 @@
# Benchmarks
This directory contains real world (ink!, solang) contracts which are used in macro benchmarks.
Those benchmarks are not used to determine weights but rather to compare different contract
languages and execution engines with larger wasm modules.
Files in this directory are used by `#[extra]` benchmarks in `src/benchmarking`. The json
files are for informational purposes only and are not consumed by the benchmarks.
@@ -0,0 +1,819 @@
{
"metadataVersion": "0.1.0",
"source": {
"hash": "0x6be8492017fe96b7a92bb39b4ede04b96effb8fcaf9237bfdccef7d9e732c760",
"language": "ink! 3.0.0-rc4",
"compiler": "rustc 1.56.0-nightly"
},
"contract": {
"name": "erc20",
"version": "3.0.0-rc4",
"authors": [
"Parity Technologies <admin@parity.io>"
]
},
"spec": {
"constructors": [
{
"args": [
{
"name": "initial_supply",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [
"Creates a new ERC-20 contract with the specified initial supply."
],
"name": [
"new"
],
"selector": "0x9bae9d5e"
}
],
"docs": [],
"events": [
{
"args": [
{
"docs": [],
"indexed": true,
"name": "from",
"type": {
"displayName": [
"Option"
],
"type": 15
}
},
{
"docs": [],
"indexed": true,
"name": "to",
"type": {
"displayName": [
"Option"
],
"type": 15
}
},
{
"docs": [],
"indexed": false,
"name": "value",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [
" Event emitted when a token transfer occurs."
],
"name": "Transfer"
},
{
"args": [
{
"docs": [],
"indexed": true,
"name": "owner",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"docs": [],
"indexed": true,
"name": "spender",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"docs": [],
"indexed": false,
"name": "value",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [
" Event emitted when an approval occurs that `spender` is allowed to withdraw",
" up to the amount of `value` tokens from `owner`."
],
"name": "Approval"
}
],
"messages": [
{
"args": [],
"docs": [
" Returns the total token supply."
],
"mutates": false,
"name": [
"total_supply"
],
"payable": false,
"returnType": {
"displayName": [
"Balance"
],
"type": 1
},
"selector": "0xdb6375a8"
},
{
"args": [
{
"name": "owner",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
}
],
"docs": [
" Returns the account balance for the specified `owner`.",
"",
" Returns `0` if the account is non-existent."
],
"mutates": false,
"name": [
"balance_of"
],
"payable": false,
"returnType": {
"displayName": [
"Balance"
],
"type": 1
},
"selector": "0x0f755a56"
},
{
"args": [
{
"name": "owner",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"name": "spender",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
}
],
"docs": [
" Returns the amount which `spender` is still allowed to withdraw from `owner`.",
"",
" Returns `0` if no allowance has been set `0`."
],
"mutates": false,
"name": [
"allowance"
],
"payable": false,
"returnType": {
"displayName": [
"Balance"
],
"type": 1
},
"selector": "0x6a00165e"
},
{
"args": [
{
"name": "to",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"name": "value",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [
" Transfers `value` amount of tokens from the caller's account to account `to`.",
"",
" On success a `Transfer` event is emitted.",
"",
" # Errors",
"",
" Returns `InsufficientBalance` error if there are not enough tokens on",
" the caller's account balance."
],
"mutates": true,
"name": [
"transfer"
],
"payable": false,
"returnType": {
"displayName": [
"Result"
],
"type": 12
},
"selector": "0x84a15da1"
},
{
"args": [
{
"name": "spender",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"name": "value",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [
" Allows `spender` to withdraw from the caller's account multiple times, up to",
" the `value` amount.",
"",
" If this function is called again it overwrites the current allowance with `value`.",
"",
" An `Approval` event is emitted."
],
"mutates": true,
"name": [
"approve"
],
"payable": false,
"returnType": {
"displayName": [
"Result"
],
"type": 12
},
"selector": "0x681266a0"
},
{
"args": [
{
"name": "from",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"name": "to",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"name": "value",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [
" Transfers `value` tokens on the behalf of `from` to the account `to`.",
"",
" This can be used to allow a contract to transfer tokens on ones behalf and/or",
" to charge fees in sub-currencies, for example.",
"",
" On success a `Transfer` event is emitted.",
"",
" # Errors",
"",
" Returns `InsufficientAllowance` error if there are not enough tokens allowed",
" for the caller to withdraw from `from`.",
"",
" Returns `InsufficientBalance` error if there are not enough tokens on",
" the account balance of `from`."
],
"mutates": true,
"name": [
"transfer_from"
],
"payable": false,
"returnType": {
"displayName": [
"Result"
],
"type": 12
},
"selector": "0x0b396f18"
}
]
},
"storage": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0000000000000000000000000000000000000000000000000000000000000000",
"ty": 1
}
},
"name": "total_supply"
},
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0100000000000000000000000000000000000000000000000000000000000000",
"ty": 2
}
},
"name": "header"
},
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0200000000000000000000000000000000000000000000000000000000000000",
"ty": 3
}
},
"name": "len"
},
{
"layout": {
"array": {
"cellsPerElem": 1,
"layout": {
"cell": {
"key": "0x0200000001000000000000000000000000000000000000000000000000000000",
"ty": 4
}
},
"len": 4294967295,
"offset": "0x0300000000000000000000000000000000000000000000000000000000000000"
}
},
"name": "elems"
}
]
}
},
"name": "entries"
}
]
}
},
"name": "keys"
},
{
"layout": {
"hash": {
"layout": {
"cell": {
"key": "0x0300000001000000000000000000000000000000000000000000000000000000",
"ty": 9
}
},
"offset": "0x0200000001000000000000000000000000000000000000000000000000000000",
"strategy": {
"hasher": "Blake2x256",
"postfix": "",
"prefix": "0x696e6b20686173686d6170"
}
}
},
"name": "values"
}
]
}
},
"name": "balances"
},
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0300000001000000000000000000000000000000000000000000000000000000",
"ty": 2
}
},
"name": "header"
},
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0400000001000000000000000000000000000000000000000000000000000000",
"ty": 3
}
},
"name": "len"
},
{
"layout": {
"array": {
"cellsPerElem": 1,
"layout": {
"cell": {
"key": "0x0400000002000000000000000000000000000000000000000000000000000000",
"ty": 10
}
},
"len": 4294967295,
"offset": "0x0500000001000000000000000000000000000000000000000000000000000000"
}
},
"name": "elems"
}
]
}
},
"name": "entries"
}
]
}
},
"name": "keys"
},
{
"layout": {
"hash": {
"layout": {
"cell": {
"key": "0x0500000002000000000000000000000000000000000000000000000000000000",
"ty": 9
}
},
"offset": "0x0400000002000000000000000000000000000000000000000000000000000000",
"strategy": {
"hasher": "Blake2x256",
"postfix": "",
"prefix": "0x696e6b20686173686d6170"
}
}
},
"name": "values"
}
]
}
},
"name": "allowances"
}
]
}
},
"types": [
{
"def": {
"primitive": "u128"
}
},
{
"def": {
"composite": {
"fields": [
{
"name": "last_vacant",
"type": 3,
"typeName": "Index"
},
{
"name": "len",
"type": 3,
"typeName": "u32"
},
{
"name": "len_entries",
"type": 3,
"typeName": "u32"
}
]
}
},
"path": [
"ink_storage",
"collections",
"stash",
"Header"
]
},
{
"def": {
"primitive": "u32"
}
},
{
"def": {
"variant": {
"variants": [
{
"fields": [
{
"type": 8,
"typeName": "VacantEntry"
}
],
"name": "Vacant"
},
{
"fields": [
{
"type": 5,
"typeName": "T"
}
],
"name": "Occupied"
}
]
}
},
"params": [
5
],
"path": [
"ink_storage",
"collections",
"stash",
"Entry"
]
},
{
"def": {
"composite": {
"fields": [
{
"type": 6,
"typeName": "[u8; 32]"
}
]
}
},
"path": [
"ink_env",
"types",
"AccountId"
]
},
{
"def": {
"array": {
"len": 32,
"type": 7
}
}
},
{
"def": {
"primitive": "u8"
}
},
{
"def": {
"composite": {
"fields": [
{
"name": "next",
"type": 3,
"typeName": "Index"
},
{
"name": "prev",
"type": 3,
"typeName": "Index"
}
]
}
},
"path": [
"ink_storage",
"collections",
"stash",
"VacantEntry"
]
},
{
"def": {
"composite": {
"fields": [
{
"name": "value",
"type": 1,
"typeName": "V"
},
{
"name": "key_index",
"type": 3,
"typeName": "KeyIndex"
}
]
}
},
"params": [
1
],
"path": [
"ink_storage",
"collections",
"hashmap",
"ValueEntry"
]
},
{
"def": {
"variant": {
"variants": [
{
"fields": [
{
"type": 8,
"typeName": "VacantEntry"
}
],
"name": "Vacant"
},
{
"fields": [
{
"type": 11,
"typeName": "T"
}
],
"name": "Occupied"
}
]
}
},
"params": [
11
],
"path": [
"ink_storage",
"collections",
"stash",
"Entry"
]
},
{
"def": {
"tuple": [
5,
5
]
}
},
{
"def": {
"variant": {
"variants": [
{
"fields": [
{
"type": 13,
"typeName": "T"
}
],
"name": "Ok"
},
{
"fields": [
{
"type": 14,
"typeName": "E"
}
],
"name": "Err"
}
]
}
},
"params": [
13,
14
],
"path": [
"Result"
]
},
{
"def": {
"tuple": []
}
},
{
"def": {
"variant": {
"variants": [
{
"discriminant": 0,
"name": "InsufficientBalance"
},
{
"discriminant": 1,
"name": "InsufficientAllowance"
}
]
}
},
"path": [
"erc20",
"erc20",
"Error"
]
},
{
"def": {
"variant": {
"variants": [
{
"name": "None"
},
{
"fields": [
{
"type": 5,
"typeName": "T"
}
],
"name": "Some"
}
]
}
},
"params": [
5
],
"path": [
"Option"
]
}
]
}
Binary file not shown.
@@ -0,0 +1,581 @@
{
"contract": {
"authors": [
"unknown"
],
"name": "ERC20PresetFixedSupply",
"version": "0.0.1"
},
"metadataVersion": "0.1.0",
"source": {
"compiler": "solang 0.1.7",
"hash": "0x9c55e342566e89c741eb641eec3af796836da750fc930c55bccc0604a47ef700",
"language": "Solidity 0.1.7"
},
"spec": {
"constructors": [
{
"args": [
{
"name": "name",
"type": {
"display_name": [
"String"
],
"type": 2
}
},
{
"name": "symbol",
"type": {
"display_name": [
"String"
],
"type": 2
}
},
{
"name": "initialSupply",
"type": {
"display_name": [
"u256"
],
"type": 1
}
},
{
"name": "owner",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
}
],
"docs": [
""
],
"name": "new",
"selector": "0xa6f1f5e1"
}
],
"events": [
{
"args": [
{
"indexed": true,
"name": "owner",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"indexed": true,
"name": "spender",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"indexed": false,
"name": "value",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
""
],
"name": "Approval"
},
{
"args": [
{
"indexed": true,
"name": "from",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"indexed": true,
"name": "to",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"indexed": false,
"name": "value",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
""
],
"name": "Transfer"
}
],
"messages": [
{
"args": [
{
"name": "account",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"name": "amount",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
""
],
"mutates": true,
"name": "burnFrom",
"payable": false,
"return_type": null,
"selector": "0x0f1354f3"
},
{
"args": [
{
"name": "account",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
}
],
"docs": [
""
],
"mutates": false,
"name": "balanceOf",
"payable": false,
"return_type": {
"display_name": [
"u256"
],
"type": 1
},
"selector": "0x6c7f1542"
},
{
"args": [],
"docs": [
""
],
"mutates": false,
"name": "totalSupply",
"payable": false,
"return_type": {
"display_name": [
"u256"
],
"type": 1
},
"selector": "0x18160ddd"
},
{
"args": [],
"docs": [
""
],
"mutates": false,
"name": "decimals",
"payable": false,
"return_type": {
"display_name": [
"u8"
],
"type": 3
},
"selector": "0x313ce567"
},
{
"args": [
{
"name": "owner",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"name": "spender",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
}
],
"docs": [
""
],
"mutates": false,
"name": "allowance",
"payable": false,
"return_type": {
"display_name": [
"u256"
],
"type": 1
},
"selector": "0xf2a9a8c7"
},
{
"args": [],
"docs": [
""
],
"mutates": false,
"name": "name",
"payable": false,
"return_type": {
"display_name": [
"String"
],
"type": 2
},
"selector": "0x06fdde03"
},
{
"args": [
{
"name": "spender",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"name": "subtractedValue",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
""
],
"mutates": true,
"name": "decreaseAllowance",
"payable": false,
"return_type": {
"display_name": [
"bool"
],
"type": 6
},
"selector": "0x4b76697b"
},
{
"args": [
{
"name": "sender",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"name": "recipient",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"name": "amount",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
""
],
"mutates": true,
"name": "transferFrom",
"payable": false,
"return_type": {
"display_name": [
"bool"
],
"type": 6
},
"selector": "0x2fb840f5"
},
{
"args": [],
"docs": [
""
],
"mutates": false,
"name": "symbol",
"payable": false,
"return_type": {
"display_name": [
"String"
],
"type": 2
},
"selector": "0x95d89b41"
},
{
"args": [
{
"name": "spender",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"name": "addedValue",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
""
],
"mutates": true,
"name": "increaseAllowance",
"payable": false,
"return_type": {
"display_name": [
"bool"
],
"type": 6
},
"selector": "0xb936c899"
},
{
"args": [
{
"name": "recipient",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"name": "amount",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
""
],
"mutates": true,
"name": "transfer",
"payable": false,
"return_type": {
"display_name": [
"bool"
],
"type": 6
},
"selector": "0x6a467394"
},
{
"args": [
{
"name": "spender",
"type": {
"display_name": [
"AccountId"
],
"type": 5
}
},
{
"name": "amount",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
""
],
"mutates": true,
"name": "approve",
"payable": false,
"return_type": {
"display_name": [
"bool"
],
"type": 6
},
"selector": "0x47144421"
},
{
"args": [
{
"name": "amount",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
""
],
"mutates": true,
"name": "burn",
"payable": false,
"return_type": null,
"selector": "0x42966c68"
}
]
},
"storage": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0000000000000000000000000000000000000000000000000000000000000002",
"ty": 1
}
},
"name": "_totalSupply"
},
{
"layout": {
"cell": {
"key": "0x0000000000000000000000000000000000000000000000000000000000000003",
"ty": 2
}
},
"name": "_name"
},
{
"layout": {
"cell": {
"key": "0x0000000000000000000000000000000000000000000000000000000000000004",
"ty": 2
}
},
"name": "_symbol"
}
]
}
},
"types": [
{
"def": {
"primitive": "u256"
}
},
{
"def": {
"primitive": "str"
}
},
{
"def": {
"primitive": "u8"
}
},
{
"def": {
"array": {
"len": 32,
"type": 3
}
}
},
{
"def": {
"composite": {
"fields": [
{
"type": 4
}
]
}
},
"path": [
"AccountId"
]
},
{
"def": {
"primitive": "bool"
}
}
]
}
@@ -26,14 +26,12 @@
use crate::Config;
use frame_support::traits::Get;
use pwasm_utils::{
parity_wasm::{
builder,
elements::{
self, BlockType, CustomSection, FuncBody, Instruction, Instructions, Section, ValueType,
},
use pwasm_utils::parity_wasm::{
builder,
elements::{
self, BlockType, CustomSection, External, FuncBody, Instruction, Instructions, Module,
Section, ValueType,
},
stack_height::inject_limiter,
};
use sp_core::crypto::UncheckedFrom;
use sp_runtime::traits::Hash;
@@ -241,9 +239,8 @@ where
let mut code = contract.build();
// Inject stack height metering
if def.inject_stack_metering {
code = inject_limiter(code, T::Schedule::get().limits.stack_height).unwrap();
code = inject_stack_metering::<T>(code);
}
let code = code.to_bytes().unwrap();
@@ -257,6 +254,34 @@ where
T: Config,
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
/// Uses the supplied wasm module and instruments it when requested.
pub fn instrumented(code: &[u8], inject_gas: bool, inject_stack: bool) -> Self {
let module = {
let mut module = Module::from_bytes(code).unwrap();
if inject_gas {
module = inject_gas_metering::<T>(module);
}
if inject_stack {
module = inject_stack_metering::<T>(module);
}
module
};
let limits = module
.import_section()
.unwrap()
.entries()
.iter()
.find_map(|e| if let External::Memory(mem) = e.external() { Some(mem) } else { None })
.unwrap()
.limits()
.clone();
let code = module.to_bytes().unwrap();
let hash = T::Hashing::hash(&code);
let memory =
ImportedMemory { min_pages: limits.initial(), max_pages: limits.maximum().unwrap() };
Self { code, hash, memory: Some(memory) }
}
/// Creates a wasm module with an empty `call` and `deploy` function and nothing else.
pub fn dummy() -> Self {
ModuleDefinition::default().into()
@@ -519,3 +544,14 @@ where
{
T::Schedule::get().limits.memory_pages
}
fn inject_gas_metering<T: Config>(module: Module) -> Module {
let schedule = T::Schedule::get();
let gas_rules = schedule.rules(&module);
pwasm_utils::inject_gas_counter(module, &gas_rules, "seal0").unwrap()
}
fn inject_stack_metering<T: Config>(module: Module) -> Module {
let height = T::Schedule::get().limits.stack_height;
pwasm_utils::stack_height::inject_limiter(module, height).unwrap()
}
@@ -30,7 +30,7 @@ use self::{
sandbox::Sandbox,
};
use crate::{
exec::StorageKey,
exec::{AccountIdOf, StorageKey},
rent::Rent,
schedule::{API_BENCHMARK_BATCH_SIZE, INSTR_BENCHMARK_BATCH_SIZE},
storage::Storage,
@@ -124,9 +124,9 @@ where
.saturating_mul(<BalanceOf<T>>::from(storage_size) / 2u32.into())
.saturating_add(T::DepositPerContract::get());
(storage_size, endowment)
(Some(storage_size), endowment)
},
Endow::Max => (0u32.into(), Endow::max::<T>()),
Endow::Max => (None, Endow::max::<T>()),
};
T::Currency::make_free_balance_be(&caller, caller_funding::<T>());
let salt = vec![0xff];
@@ -158,7 +158,9 @@ where
};
let mut contract = result.alive_info()?;
contract.storage_size = storage_size;
if let Some(size) = storage_size {
contract.storage_size = size;
}
ContractInfoOf::<T>::insert(&result.account_id, ContractInfo::Alive(contract));
Ok(result)
@@ -278,6 +280,24 @@ fn caller_funding<T: Config>() -> BalanceOf<T> {
BalanceOf::<T>::max_value() / 2u32.into()
}
/// Load the specified contract file from disk by including it into the runtime.
///
/// We need to load a different version of ink! contracts when the benchmark is run as
/// a test. This is because ink! contracts depend on the sizes of types that are defined
/// differently in the test environment. Solang is more lax in that regard.
macro_rules! load_benchmark {
($name:expr) => {{
#[cfg(not(test))]
{
include_bytes!(concat!("../../benchmarks/", $name, ".wasm"))
}
#[cfg(test)]
{
include_bytes!(concat!("../../benchmarks/", $name, "_test.wasm"))
}
}};
}
benchmarks! {
where_clause { where
T::AccountId: UncheckedFrom<T::Hash>,
@@ -2536,6 +2556,88 @@ benchmarks! {
#[cfg(not(feature = "std"))]
return Err("Run this bench with a native runtime in order to see the schedule.");
}: {}
// Execute one erc20 transfer using the ink! erc20 example contract.
//
// `g` is used to enable gas instrumentation to compare the performance impact of
// that instrumentation at runtime.
#[extra]
ink_erc20_transfer {
let g in 0 .. 1;
let gas_metering = if g == 0 { false } else { true };
let code = load_benchmark!("ink_erc20");
let data = {
let new: ([u8; 4], BalanceOf<T>) = ([0x9b, 0xae, 0x9d, 0x5e], 1000u32.into());
new.encode()
};
let instance = Contract::<T>::new(
WasmModule::instrumented(code, gas_metering, true), data, Endow::Max,
)?;
let data = {
let transfer: ([u8; 4], AccountIdOf<T>, BalanceOf<T>) = (
[0x84, 0xa1, 0x5d, 0xa1],
account::<T::AccountId>("receiver", 0, 0),
1u32.into(),
);
transfer.encode()
};
}: {
<Contracts<T>>::bare_call(
instance.caller,
instance.account_id,
0u32.into(),
Weight::MAX,
data,
false,
)
.result?;
}
// Execute one erc20 transfer using the open zeppelin erc20 contract compiled with solang.
//
// `g` is used to enable gas instrumentation to compare the performance impact of
// that instrumentation at runtime.
#[extra]
solang_erc20_transfer {
let g in 0 .. 1;
let gas_metering = if g == 0 { false } else { true };
let code = include_bytes!("../../benchmarks/solang_erc20.wasm");
let caller = account::<T::AccountId>("instantiator", 0, 0);
let mut balance = [0u8; 32];
balance[0] = 100;
let data = {
let new: ([u8; 4], &str, &str, [u8; 32], AccountIdOf<T>) = (
[0xa6, 0xf1, 0xf5, 0xe1],
"KSM",
"K",
balance,
caller.clone(),
);
new.encode()
};
let instance = Contract::<T>::with_caller(
caller, WasmModule::instrumented(code, gas_metering, true), data, Endow::Max,
)?;
balance[0] = 1;
let data = {
let transfer: ([u8; 4], AccountIdOf<T>, [u8; 32]) = (
[0x6a, 0x46, 0x73, 0x94],
account::<T::AccountId>("receiver", 0, 0),
balance,
);
transfer.encode()
};
}: {
<Contracts<T>>::bare_call(
instance.caller,
instance.account_id,
0u32.into(),
Weight::MAX,
data,
false,
)
.result?;
}
}
impl_benchmark_test_suite!(