Write a Smart Contract
To start our contract, we need to import the interface to our HybridAccount
contract. The address of this HybridAccount is passed to the constructor and is stored as an immutable variable. Next we define other contract variables and helper functions.
The "counters" mapping provides a unique numeric counter scoped to each user who calls the contract.
To implement our function to waste gas, we can leverage a for
loop to increase transaction time:
Now we can add the count()
method. We initialize the HybridAccount
with the hcAccount
created prior, and allow for parameters a
and b
, our numbers to add and subtract together. We define x
and y
, do a quick check for b == 0
, and encode our function offchain_addsub2()
. We registered HybridAccount
in the previous section to provide access to the offchain_addsub2()
function on our off-chain function.
The truly unique functionality of Hybrid Compute comes from HA.CallOffChain(userkey, req)
; this call will (assuming no error) return us the two numbers a
and b
after making computations off-chain The userKey
parameter we pass in, generated by encoding msg.sender
, distinguishes requests so that they may be processed concurrently without interefering with each other. As already mentioned in the previous section, our off-chain server maps the request made by the bundler via the hashed representation of our function-signature.
If we encounter an error during the CallOffChain()
call, we either revert or set the counter forward by varying amounts. We can add these different cases in a series of else if
blocks:
Notably, in the first if
block, we decode the returned object ret
into two uint256
values as the off-chain function returns two integers. The variables x
and y
hold the results of the addition and subtraction, respectively.
Calling Off-Chain
Within the HybridAccount
contract itself, the CallOffchain()
method calls through to another system contract named HCHelper
. This is the source code of the function:
In this example, the HybridAccount
implements a simple whitelist of contracts which are allowed to call its methods. It would also be possible for a HybridAccount
to implement additional logic here, such as requiring payment of an ERC20
token to perform an off-chain call. Conversely, the owner of a HybridAccount
could choose to make the CallOffchain()
method available to all callers without restriction.
You could take the optional opportunity for a HybridAccount
contract to implement a billing system here, requiring a payment of ERC20
tokens or some other mechanism of collecting payment from the calling contract.
HybridAccount / HCHelper Interaction
Our HCHelper
contract acts as a system-wide interface to the Hybrid Compute framework. Let's examine some of the calls we made to it in our own contract.
First, the helper checks an internal mapping to see if a response exists for the given request. If not, the method reverts with a special prefix, followed by an encoded version of the request parameters.
If a response does exist, it's removed from the internal mapping and is returned to the caller. The map key encodes the request parameters, so that a response initiated by one request will not be returned later in response to a modified request from the caller.
To populate the response mapping, HybridAccount
contracts use another method in the Helper:
Note that the msg.sender
is included in the calculation of the internal map key, ensuring that only HybridAccount
is able to populate the response (which it will later receive back in the TryCallOffchain()
call). However, in the case of an error result of (success == false)
, there's also a provision for the HC implementation to insert a result under a different map key.
Account Abstraction calls PutResponse()
and the off-chain userOperation
must carry a valid signature in order to execute the operation.
That finishes our smart contract! Proceed to the next section to learn how to deploy it.
Last updated