Cycle cost to pass cycles

Is there a significant cycle cost to pass cycles to another canister?

Or put another way, would it be better to pass cycles with every call, or to do one top up call? How much of a difference in cycles would this be?

Short answer: there are no additional costs, you can send cycles with every single call for free.

Long one: if canister A calls canister B, the cost of the. call is 590K cycles to execute the update on canister B side and 590K to execute response on canister A side + number of instructions executed.

Adding cycles to the call has no provisions or whatever, and it’s guaranteed to be either fully or partially accepted by canister B, or returned back to canister A.

Links:

  1. Computation and Storage Costs on IC
  2. Example Cycles Flow between canister A and B
3 Likes

What about the 260K for the Xnet call? (from https://internetcomputer.org/docs/current/developer-docs/deploy/computation-and-storage-costs/)

Sure, for cross-net calls there are additional charges per call and per byte. But anyway, there are no additional charges for adding cycles to each such a call.

3 Likes

Are you saying this library here is free to call add cycles by a calling canister?

How about accept? That single call is free?

Now one more thing. If I call a canister without cycles and it was suppose to run out of cycles lets say three lines of code down the call. If i call accept cycles two lines up will i be safe?

Ie.
without cycles send
func something(){
do something1()
do something 2()
//runs out of cycles here
do something 3()
}

And if i do it again with

func something(){
do something1()
experimentalCycles.Accept(enough for full call)
do something 2()
//Am i safe here or do the cycles get processed after?
do something 3()
}

How about for this case where the call wouldn’t even have gone through. Would calling accept on the first line save it??
Ie.
without cycles send

//out of cycles error would here occured ran out before even getting into something somehow
func somethingagain( ){
do something1()
do something 2()
do something 3()
}

func somethingagain(){
//am i safe here?
experimentalCycles.Accept(enough for full call)
do something1()
do something 2()
do something 3()
}

Accepting the cycles doesn’t do anything to change the instruction limit of a single call. It just lets you accept the cycles and add them to your over-all cycle balance.

2 Likes

Technically, there is a small fee associated with the execution, i.e. the calling canister has to add the cycles. This adds a slight overhead for both the calling and the called canister.

I agree with Austin’s point regarding the one more thing, assuming there’s a single message execution, i.e. there are no nested calls in do something N() functions.

If there are nested calls, accepting the cycles earlier might make a difference.

1 Like