Replies: 3 comments 1 reply
-
Comparison sheet with epoch style architecture Purpose Callback-Callback mechanism Epoch-Scheduling actions to happen at the beginning of a new epoch Guarantees Callback-No guarantees about when the callback will be executed Epoch-Guarantees that callbacks will be executed at the beginning of the next epoch Fees Callback-Charges a fee for requesting a callback Epoch-Does not charge a fee Epoch module also guarantees that callbacks will be executed at the beginning of the next epoch, which kindly means that the smart contract developer can plan ahead and schedule callbacks for times when the network is less congested. Callback queue architecture One way to do this is to kindly have a callback queue that could be part of the epoch module. The callback queue would contain a list of callbacks that need to be executed at the beginning of the next epoch. When a contract wants to schedule a callback, it would send a message to the epoch module with the callback information. The epoch module would then add the callback to the callback queue. At the beginning of each epoch, the epoch module would iterate over the callback queue and execute all of the callbacks. This approach should kindly allow callbacks to be executed in a predictable and efficient manner. It should also kindly allow the epoch module to provide guarantees about when callbacks would be executed. |
Beta Was this translation helpful? Give feedback.
-
This RFC has been promoted to an AIP (Archway Improvement Proposal) |
Beta Was this translation helpful? Give feedback.
-
Shipped with Archway v7 |
Beta Was this translation helpful? Give feedback.
-
Abstract
We propose a x/cw-callback module which enables CosmWasm smart contracts to receive callbacks at the end of each block.
This is useful for scheduling actions to happen at an expected time by reserving blockspace in advance.
Background
Currently on Archway, the smart contracts can only be executed when called on by a user or by other contracts1. The decentralized nature of ecosystem should allow enforcement of predefined protocols without the need for intermediaries.
However, for some applications, dapps still rely on trusted third parties to instigate the executions or state changes. Examples, epochs for defi primitives, price balancing arbitrage bots, vesting distribution of funds, settling of auctions.
To overcome this dependence, there is a need for a callback mechanism in smart contracts which can be handled in a transparent, secure and market-efficient way.
Existing Solutions
To not have to reinvent the wheel, let's take a look at other cosmos chains which solve similar problems.
1. Stargaze's x/cron & Juno's x/clock modules
Stargaze has the x/cron module and Juno implements the x/clock module. Both operate by pinging configured contracts every block. They have a governance process which allows a dapp developer to add their contract address to the EndBlocker hooks. Therefore, at the end of every block, the chain calls the contract and the contract can handle this trigger however it wishes. This happens in perpetuity unless a governance process removes the contract from receiving the callbacks.
We don't believe this works for Archway for the following reasons:
Interesting features:
ContractGasLimit
which is a governance-controlled parameter which controls the maximum gas which can be consumed by the contracts in a given block. This prevents contracts from abusing the free execution2.2. Neutron's x/cron
Neutron's x/cron module is similar to the above solutions in the sense that it is governance gated.
However, this module allows custom cron schedule and specifies a list of CosmWasm msgs which will be called with the execution.
Along with the reasons specified for the previous modules, we don't believe this is ideal for Archway either, due to
Interesting features:
limit
which is a governance-controlled parameter which controls the number of schedules which can be handled by the module.Proposal
Taking into consideration the above solutions' drawbacks while also learning from what they did right, we propose the following implementation of a new module called x/cw-callback which solves the specified problem and enables automated, time-triggered actions. A dapp should be able to ask the chain to give a callback in a permissionless way, so it can perform operations at a specified time.
The proposed module would allow any contract to request a callback at a specified block height. At the end of every block, the module executes all the specified callback requests for that block, in the order they were requested. This ensures that there is no unfair advantage in the protocol towards one contract over another.
To ensure the contracts are not using this feature just to perform high gas computations, we propose a module param
callback_gas_limit
3. This is the hard limit of the gas which can be consumed by the contract. This value is exepected to be large enough to allow meaningful executions but small enough to prevent abuse.The contracts do benefit from free execution2 during the callback, as such we expect the contracts to pay the required fees upfront. As Archway has a custom
estimate-fees
function, we will use that multiplied by thecallback_gas_limit
to calculate how much fees the contract needs to pay to request callback. Post execution, we could look at how much gas was actually consumed and refund the rest. As it is the validators who will be paying for the actual execution, we propose this collected amount goes to thefee_collector
.To ensure contracts do not abuse this feature when the fees are low and reserve callbacks for far future, we propose a module param
callback_reservation_block_limit
. If this value is set to 1000, the contracts will only be allowed to request callbacks within the next 1000 blocks. The module allows guaranteed blockspace, therefore, this limit is a necessity to ensure the block spaces aren't reserved without meaningful intention.To further reduce incentive to be bad actor, we can also have a reservation fee mechanism which ensures requesting callbacks far in the future requires higher fees to be paid that requesting callbacks in near future. e.g We take the delta between the callback requested height and the current block height and multiply it with
reservation_fee_multiplier
param. So a fee multiplier of 0.001 would mean reserving for immediate block would cost 0.001arch while reserving 1000 blocks from now would cost 1arch.The module parameterizations:
To schedule a callback from the module the contract needs to execute the following message:
The contract can provide the job ID which we will be stored and passed on during the callback to help the contract in maintaining any relevant context. A contract can only request callbacks for itself for safety reasons.
The contract can always cancel the callback and their tx execution fees will be refunded. But the reservation fee will not completely be refunded.
When the contract is set to receive its callback, it will be called on the Sudo endpoint as the following message
Discussions
Here we are outlining the discussions held internally at Phi Labs regarding this proposal before publishing.
Should there be a limit on how many callbacks can be done in a block?
To prevent too many callbacks from being registered on a single block and possibly slowing down the performance, it would be ideal to have a solution to this as well. There are two main ways to go about it. We can chose one or do a combination of both. Open to ideas for this in the discussion below.
callback_block_capacity
. This will store the number of maximum callbacks which can be registered per block.How to handle errors when the contract callback fails?
There is no easy way to handle this sadly. The implementation can log the errors and throw events that the execution failed but it will be up to the contract developer to keep track of it.
Consequences
Backwards compatibility
Since the feature is being added as a new module, this should not cause any backwards compatibility issues.
Positive
Negative
Footnotes
The contracts can also be called by on-chain governance, but that is not relevant to the discussion. ↩
There is no free execution on the blockchain. By free execution, we mean that the validators are paying for the execution. ↩ ↩2 ↩3 ↩4
Inspired by
ContractGasLimit
of Juno's x/clock module ↩Beta Was this translation helpful? Give feedback.
All reactions