It seems this is related to running sub calls in transactions. The batch is somewhat unrelated although it exacerbates the issue by doubling the transaction fees. There is no difference between the contracts node and aura node - I was previously confused by the difference in decimal places between the two types of nodeEdited after feedback from @German Nikolishin below.
The fee is small when calling an ink!
function that does not call another ink!
message (a sub-call).
#[ink(message)]
pub fn faucet(&mut self, accountid: AccountId) -> Result<(), Error> {
let token_holder = self.token_holder;
self.transfer_from_to(&token_holder, &accountid, self.faucet_amount)?;
Ok(())
}
Tx Cost: 1 UNIT for extrinsic without sub call
The fee is doubled when the above call is batched butIt seems this transfer is still small:
Tx Cost: 2 UNIT for extrinsic without sub call in batch
The fee explodes when calling an ink!
function that makes a sub-call.
/// Faucet function for sending tokens to humans that includes a call #[ink(message)]
pub fn faucet_with_subcall(&mut self, accountid: AccountId) -> Result<(), Error> {
let token_holder = self.token_holder;
self.transfer_from_to(&token_holder, &accountid, self.faucet_amount)?;
// SUB-CALL to a second #[ink(message)]
// record transfer or return error
match self.record_transfer(Transfer {
Tx Cost: 481 UNIT for extrinsic with sub call
And batching the txcost associated with the sub-call causes the fee to double again.
Tx Cost: 962 UNIT for extrinsic with sub call in batch`
The .Transfer
eventsstoring data in the block appear when the transactions contain sub-calls:
contract. The value inside themthe transfer is sent to what I presume is the contract's deposit_account
, which is why it isn't a contract itself.
faucetWithSubcallfaucetWithStore response.storageDeposit { Charge: '480.0000 Unit' }
The deposit stays in the deposit account until the contract is terminated, at which point the deposit account uses the funds to remove any storage associated with the contract and then sends the remaining funds back to the recipient.
ink::env::terminate_contract::<ink::env::DefaultEnvironment>(recipient);
I've created a demo repo to demonstrate the fees shown above.
It would be nice if the ink!
developers could comment on the preferred approach when calling additional functions inside ink!
.