‘Smart contracts’ is a misnomer. Despite its name, digital agreements. Smart contract code only run when triggered by an . In other words, you need an external process to trigger the smart contract. smart contracts on Ethereum are not self-executing external account In this article, we’ll build a solution to this problem. You’ll learn: Why we need off-chain smart contract automation Use cases for smart contract automation How to deploy serverless functions with the Serverless framework Finally, we’ll go through , a fully-functional smart contract automation service that you can run and deploy out-of-the box. You can use this project as a base for building custom smart contract automation that fit your needs. serverless-ethers Just clone and hit deploy! The serverless-ethers sample application is open source and available on Github. Read on to learn why we need automation and how it works. The Problem: Smart contracts are not self-executing ⏳⚙️ Imagine that we want to implement a smart contract with a function that should be automatically executed every 1 hour. How can you accomplish this? You can’t. This is with plain Solidity smart contracts. Despite its name, ‘smart’ contracts in Ethereum are not self-executing. You need an external source (either human or machine) to call the smart contract and execute its code. not possible The most a contract can do is enforce a 1-hour interval between executions, for example: { (block.timestamp >= lastTriggeredAt + hour); ... } ( ) function runMe public require 1 The above require() statement ensures that there is at least an hour in between executions. Otherwise, the transaction reverts. However, somebody still needs to call the smart contract for the code to run in the first place. An Aside on Self-Execution Technically, it is possible to use to automatically execute certain operations. One example of this is ’s COMP distribution. Once an address has earned 0.001 COMP, any Compound transaction (e.g. supplying an asset, or transferring a cToken) will automatically transfer COMP to their wallet. function modifiers Compound Governance You can implement the above logic in a function modifier (a decorator), wrap the modifier around a function, and have the logic automatically executed whenever the function is called. The caller will pay the gas required for the additional logic. However, not all smart contract systems follow this approach. One reason is that it can lead to unpredictable gas usage, since these modifiers may only run under certain conditions. It also forces additional gas fees onto a random subset of users, who just happened to be the unlucky few selected to ‘rebalance’ the contract. Finally, still needs to call the smart contract for the code to run. somebody Common Use Cases for Smart Contract Automation DeFi protocols already rely on some kind of off-chain smart contract automation. MakerDAO relies on third party to monitor the collateralization ratios of debt positions and liquidate any undercollateralized position. Other DeFi protocols have similar needs. Keepers There are two, often overlapping use cases around off-chain smart contract automation: You want to execute a contract under a certain condition. Automated Triggers: You want to know when a contract is in a certain condition. State and Event Monitoring: 1. Automated Triggers You often want to execute a contract periodically or under certain conditions. For example: Rebalancing a pool periodically Closing out voting rounds in a DAO / governance process Poking oracles to refresh data Paying out pro-rated dividends for security tokens 2. State and Event Monitoring You want to know if certain conditions are met. For example: You want to know if a value in a smart contract has changed You want to be notified of all Access Control changes You want to know when a specific smart contract Event was emitted The Solution: Serverless functions? The above use cases sounds like for a serverless function. By going serverless, we can deploy code without provisioning anything beforehand, or managing anything afterward. It’s easier than ever to make your idea live. a good fit Quickstart: Going Serverless with the Serverless Framework The gives you everything you need to develop, deploy, monitor and secure serverless applications. We’ll be using it to speed up our development and reduce mental overhead. Serverless Framework > npm install -g serverless > serverless -v x.x.x Let’s quickly go through how the Serverless Framework operates. You can if you’re just interested in seeing things working. Read on to learn more about the Serverless framework. skip ahead 0. serverless.yml All of the Lambda functions and events in your Serverless service can be found in a configuration file called the . It defines a service with Functions and Events. serverless.yml service: serverless-ethers provider: name: aws runtime: nodejs12.x environment: CHAIN_ID: 3 DEFAULT_GAS_PRICE: 60000000000 functions: myFunc: handler: functions/myFunc.handler events: - schedule: rate(2 hours) Under the property, you define your serverless functions. In the above example: functions We have a Function called . myFunc The property points to the file and module containing the code you want to run in your function. handler The property specifies Event triggers for the function to be executed. events You can have multiple functions in a single service. 1. Functions A Function is an AWS Lambda function. It’s an independent unit of deployment, like a microservice. It’s merely code, deployed in the cloud, that is most often written to perform a single job. exports.handler = { }; // functions/myFunc.js async ( ) function event, context // Do anything Functions are just normal JS functions. They can take an event object as payload. 2. Events Events are the things that trigger your functions to run. Events belong to each Function and can be found in the events property in . serverless.yml You can use the trigger to automatically execute functions periodically. For example, to run the myFunc function every 2 hours we specify: Scheduled Events # serverless.yml functions: myFunc: handler: functions/myFunc.handler events: - schedule: rate(2 hours) You can also specify the schedule using : cron schedule expressions # serverless.yml events: - schedule: cron( * * ? *) # PM UTC 0 12 12 If you are using AWS as your provider, in the service are anything in AWS that can trigger an AWS Lambda function, like: all events An AWS API Gateway HTTP endpoint request (e.g., for a REST API) An AWS S3 bucket upload (e.g., for an image) A CloudWatch timer (e.g., run every 5 minutes) An AWS SNS topic (e.g., a message) And more… That’s all you need to know for now. To learn more about the Serverless framework, check out . the docs With the Serverless Framework basics out of the way, let’s jump into the service. serverless-ethers Introducing serverless-ethers is a fully-functional Serverless service that you can deploy and run out-of-the box. serverless-ethers git git@github.com:yosriady/serverless-ethers.git serverless-ethers nvm use npm install clone cd You can use this project as a base for building custom smart contract automation. It comes preconfigured for AWS, but can be modified to work with other cloud providers such as , Azure, and many others. GCP The project is structured as follows: serverless-ethers ├── contracts/ │ ├── abis/ │ ├── abis.js │ └── addresses.js ├── / │ └── exec.js └── serverless.yml functions contain smart contract ABIs and addresses. contracts/ contain JS functions that implement the business logic. functions/ describe the service’s configuration. serverless.yml Let’s look at each section in detail. Aside: Sample Smart Contracts I’ve written and deployed a sample smart contract for testing purposes: pragma solidity ^ ; contract DummyStorage { ; _currentValue; { _currentValue; } { ; _currentValue = ; } } // SPDX-License-Identifier: GPL-3.0 0.6 .10 ( ) event Write address indexed source, uint256 value uint internal function ( ) view ( ) get public returns uint return function ( ) put uint value public emit ( ) Write msg.sender, value value The smart contract has the following functions: DummyStorage is a read-only function that returns the contract’s current value. get is a write function that updates the contract’s current value. put The sample contract is verified and . Feel free to use it to test your functions! live on Ropsten 1. Smart Contract ABIs The directory contains the of contracts the functions interact with. In the sample project, it contains the ABI for the DummyStorage contract. contracts ABIs ├── contracts/ │ ├── abis/ │ │ └── DummyStorage.json │ ├── abis.js │ └── addresses.js You can think of an ABI as a smart contract’s public API specification, kind of like an OpenAPI specification. You need the ABI to call a contract’s functions. The contracts/ directory structure lets us import both the contract ABI and address like so: { abis, addresses } = ( ); DummyStorageABI = abis.DummyStorage; DummyStorageAddress = addresses.DummyStorage; // functions/exec.js const require '../contracts' const const We’ll need these in our function. 2. Functions The function uses to load contract ABIs and call a smart contract: exec Ethers contract = ethers.Contract( DummyStorageAddress, DummyStorageABI, wallet, ) RANDOM_INTEGER = .floor( .random() * ); tx = contract.put(RANDOM_INTEGER) // Initialize contract const new // Call smart contract function `put(uint)` const Math Math 100 // returns a random integer from 0 to 99 const await Loading the contract ABI and address gives us an abstraction with all the functions of our smart contract, including and . ethers.Contract get() put() In the sample function, we call with a random integer. exec contract.put() 3. serverless.yml Before you can run the exec function, you’ll need to specify some environment variables in your serverless.yml: # serverless.yml service: serverless-ethers provider: name: aws runtime: nodejs12.x region: ap-southeast-1 timeout: 30 environment: DEFAULT_GAS_PRICE: 60000000000 MNEMONIC: ... SLACK_HOOK_URL: ... uses the following environment variables: serverless-ethers : Default gas price used when making write transactions. DEFAULT_GAS_PRICE : 12-word mnemonic used to derive an Ethereum address. Make sure it’s if you intend to write data to Ethereum! MNEMONIC funded with Ether : The example sends messages to Slack using . You can get this URL from your Slack dashboard. (Optional) SLACK_HOOK_URL Incoming Webhooks You can change your deployed function’s environment variables on the fly from the AWS Lambda console. make sure you do not store keys in plaintext in production. Use a secure parameter store such as when storing credentials such as mnemonics and API keys. Since every project has its own security requirements and setup, we leave it up to readers to decide how they want to approach storing secrets. Important Note: AWS Secrets Manager Running locally You can use the command invoke local to run your functions locally. This is great for testing! serverless CLI > serverless invoke -f Starting... Contract ABIs loaded Ethers wallet loaded Contract loaded Sending transaction... :white_check_mark: Transaction sent https://ropsten.etherscan.io/tx/0x72204f07911a319b4e5f7eb54ad15ed666cfc1403b53def40c9d60188b176383 Completed local exec true Deploying to AWS Deploying is as easy as y: serverless deplo > serverless deploy Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: Creating Stack... Serverless: Checking Stack create progress... ........ Serverless: Stack create finished... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Uploading service serverless-ethers.zip file to S3 (2.95 MB)... Serverless: Validating template... Serverless: Updating Stack... Serverless: Checking Stack update progress... ..................... Serverless: Stack update finished... Service Information service: serverless-ethers stage: dev region: ap-southeast-1 stack: serverless-ethers-dev resources: 8 api keys: None endpoints: None : : serverless-ethers-dev-exec layers: None functions exec That’s it! You now have a live serverless function that you can use to automate and monitor your smart contracts. You can use this project as a base for building your own smart contract automation. In Closing Congratulations! You learned about: Why we need off-chain smart contract automation Use cases for smart contract automation The Serverless framework How the serverless-ethers sample application works Feel free to let me know if you found this useful, or if you have any questions! I’d be interested to know what your automation use cases are. Star the repo if you found it useful! The serverless-ethers sample application is open source and available on Github. Extra: ChatOps support with Slack Included with serverless-ethers is a function to help you integrate with Slack. postToSlack successMessage = ; postToSlack(successMessage); const `:white_check_mark: Transaction sent https://ropsten.etherscan.io/tx/ ` ${tx.hash} await The function makes use of a environment variable that you can get from your . Once set up, you’ll be able to notify Slack whenever a transaction was sent successfully: postToSlack SLACK_HOOK_URL Slack console It’s a nice and simple way to monitor your functions. Extra: Monitoring Smart Contract Events So far, we’ve only implemented the ‘Automated Trigger’ use case. What about monitoring smart contract state and events? You can use the Ethers v5 to periodically monitor for certain events. In your function, you can do the following: Events API filter = contract.filters.Transfer(userAccount, ); logs = contract.queryFilter(filter, , ); logs.forEach( { .log(log.args._to, log.args._value); }); // Given the following Event: // event Transfer(bytes32 indexed node, address owner) // Get the filter (the second null could be omitted) const null // Query the filter const 0 "latest" // from block 0 to latest block // Print out all the values: ( ) => log console Assuming that you want to have this function execute periodically (e.g. every 5 minutes), you’ll also need to store a flag that keeps track of the last block the function has seen since the last execution. Event monitoring is especially useful if you have an Access Control whitelist that you need to keep an eye on. With an event monitoring function, you can notify a Slack channel whenever new addresses are whitelisted for admin roles. Very handy! Previously published at https://yos.io/2020/07/04/serverless-smart-contract-automation/