Skip to content

LayerZero-Labs/gasolina-aws

Repository files navigation

gasolina-aws

Description

This repository provides tooling for deploying a Gasolina-based DVN on AWS. The recommended approach uses Infrastructure-As-Code (IAC) via AWS CDK, which automates the entire setup:

  • Bootstraps CDK
  • Creates a VPC
  • Uploads providers to S3
  • Sets up a CloudWatch log group
  • Deploys the Gasolina API app on ECS
  • Sets up a load balancer on Fargate in the VPC private subnet
  • Sets up API Gateway to route to the Gasolina API (we don't expose the load balancer directly, API Gateway offers TLS without the need for a certificate)

If your organization has constraints that prevent using CDK (e.g., custom networking policies, existing infrastructure, or specific compliance requirements), a manual deployment path is also documented below.


Prerequisites

1. AWS credentials

Authenticate with AWS CLI using a valid method: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html

2. Install dependencies

In the root directory of the project, run:

pnpm i

3. Choose a signer strategy

You need to decide how the DVN will sign payloads. There are two options:

Strategy Description When to use
Mnemonic You supply your own mnemonic(s) stored in AWS Secrets Manager. You already manage your own keys.
KMS AWS KMS creates HSM-backed asymmetric keys for you. You want AWS-managed key security.

Mnemonic setup: Go to AWS Secrets Manager and create a new secret (key-value pair) for each signer:

  • Key LAYERZERO_WALLET_MNEMONIC — the mnemonic phrase
  • Key LAYERZERO_WALLET_PATH — the derivation path

img.png

KMS setup: No manual key creation is needed for CDK deployments — CDK handles it. For manual deployments, see the KMS section under manual deployment.


Option A: CDK Deployment (Recommended)

CDK automates infrastructure provisioning and application deployment in a single command. This is the fastest and most reliable way to get running.

1. Bootstrap CDK

If this is your first time using CDK in the AWS account, run the following in cdk/gasolina/:

cdk bootstrap

2. Configure infrastructure and application

cdk/gasolina/config/index.ts — edit the CONFIG object:

  • Configure the AWS account number as the key of the object.
  • projectName — a unique project name (used for the S3 bucket, which must be globally unique on AWS).
  • environment — the LayerZero environment (mainnet or testnet).
  • availableChainNames — comma-separated chain names, e.g. ethereum,bsc,avalanche.
  • signerTypeMNEMONIC or KMS.
    • If MNEMONIC, the number of signers is based on your wallet definitions in walletConfig/<environment>.json.
    • If KMS, you can optionally set kmsNumOfSigners to create and register multiple keys.

cdk/gasolina/config/providers/<environment>/providers.json — add RPC provider entries for every chain listed in availableChainNames.

cdk/gasolina/config/walletConfig/<environment>.json (mnemonic only) — under definitions, add one wallet definition per signer:

  • address — the signer's wallet address
  • secretName — the Secrets Manager secret name used at runtime to retrieve the mnemonic

3. Deploy

In cdk/gasolina/, run:

cdk deploy

After deployment completes, the output will include Oracle.ApiGatewayUrl = <URL>. Send this URL to LayerZero Labs.

4. Verify

See Testing below.


Option B: Manual (Non-CDK) Deployment

Use this path only if CDK is not viable for your organization. You are responsible for provisioning each component, assigning IAM permissions, and configuring environment variables yourself.

Required components

# Component AWS examples Purpose
1 Container runtime ECS, EKS, EC2 Runs the Gasolina Docker image
2 Signer credentials Secrets Manager, KMS Provides signing keys to the application
3 RPC provider config S3 Stores providers.json for chain RPC endpoints
4 Logging (optional) CloudWatch Application metrics and logs

The container (1) must have IAM permissions to access the signer credentials (2) and the provider config bucket (3). If logging is enabled, it also needs read/write access to the log group (4).

Set up signer credentials

Mnemonic in Secrets Manager (AWS)

Follow the same steps described in Prerequisites > Choose a signer strategy. Note the secret name — you will reference it in environment variables.

KMS (AWS)

For each signer key you need, create a KMS key with the following steps:

  1. Create key — choose an asymmetric key type suitable for signing. create-key.png
  2. Set configuration — configure the key spec as required (ECC_SECG_P256K1, sign/verify usage). key-configuration.png
  3. Enable service role — grant your container's IAM role permission to use the key. key-usage
  4. Note the Key ID — you will use this in the LAYERZERO_KMS_IDS environment variable. key-id

Set up RPC provider config

  1. Create a private S3 bucket with read access granted to your service role.
  2. Upload a file named providers.json following the format in cdk/gasolina/config/providers/mainnet/providers.json.
  3. Note the bucket name — you will use this in the CONFIG_BUCKET_NAME environment variable.

Set up logging (optional)

Create a CloudWatch Log Group and grant read/write permissions to your service role. Gasolina currently only supports AWS CloudWatch for logging.

Run the Docker image

Pull the latest version of the Gasolina image:

us-east1-docker.pkg.dev/lz-docker/gasolina/gasolina

Ensure the service has network/IAM permissions to:

  • Be called externally (ingress)
  • Reach external URLs listed in providers.json (egress)
  • Access signing keys (Secrets Manager or KMS)
  • Read the S3 bucket with provider config
  • (if logging is configured) Read/write the CloudWatch log group

Environment variables

Set the following environment variables on your container:

Variable Required Description
LAYERZERO_ENVIRONMENT Yes mainnet or testnet
LAYERZERO_AVAILABLE_CHAIN_NAMES Yes Comma-separated chain names, e.g. ethereum,arbitrum
LAYERZERO_CDK_DEPLOY_REGION Yes AWS region of the service, e.g. us-east-1
SERVER_PORT Yes Port exposed by the service, e.g. 8081
SIGNER_TYPE Yes KMS or MNEMONIC
LAYERZERO_WALLETS If mnemonic JSON-stringified wallet config (see below)
KMS_CLOUD_TYPE If KMS AWS or GCP
LAYERZERO_KMS_IDS If KMS Comma-separated KMS key IDs, e.g. abcdef,bcdefa
LAYERZERO_SUPPORTED_ULN_VERSIONS Yes ["V2"]
LAYERZERO_METRIC_NAMESPACE Optional Metric namespace, e.g. layerzero-gasolina
CONFIG_BUCKET_NAME Yes Name of the S3 bucket with providers.json
PROVIDER_CONFIG_TYPE Yes S3 or GCS
LAYERZERO_METRIC_LOG_GROUP_NAME If logging CloudWatch log group name

LAYERZERO_WALLETS format (mnemonic signer only):

{
    "definitions": [
        {
            "name": "signer-1",
            "secretName": "my-secret-name"
        }
    ]
}

secretName is the Secrets Manager secret created earlier, and name is an arbitrary label.

Verify

See Testing below.


Testing

Health check

curl https://<service-url>/
# Expected: HEALTHY

Available chains

curl https://<service-url>/available-chains

Provider health

curl https://<service-url>/provider-health

If any provider returns false, check the service logs for details. Common causes: misconfigured URLs in providers.json, or the service lacking egress permissions. If your organization requires a proxy for external domains, ensure the TLS configuration is valid and pass the full proxy address in providers.json — Gasolina does not allow unverified TLS connections.

Signer info

curl https://<service-url>/signer-info?chainName=ethereum

This should return address information for your signers. If it fails, verify your signer-related environment variables and IAM permissions.

End-to-end test

From the project root directory:

ts-node scripts/testDeployment -u <service-url> -e <environment>

A successful response:

--- [200] Successful request ---
Response: {
  signatures: [
    {
      signature: '<signature>',
      address: '<address>'
    }
  ]
}

[Optional] Extra Context Verification

You can enhance message verification by adding custom rules. Set up an API that Gasolina will call whenever a message is received. The API receives the full message context (including on-chain data) and returns a boolean indicating whether the message should be signed.

Setup: In cdk/gasolina/config/index.ts, set extraContextGasolinaUrl to your API's URL in the CONFIG object.

API input schema
{
    sentEvent: { // PacketSent event, emitted from the Endpoint contract
        lzMessageId: {
            pathwayId: {
                srcEid: number // Source chain eid (https://github.com/LayerZero-Labs/LayerZero-v2/blob/main/packages/layerzero-v2/evm/protocol/contracts/EndpointV2.sol#L23)
                dstEid: number
                sender: string // Sender oApp address on source chain
                receiver: string // Receiver oApp address on destination chain
                srcChainName: string // Source Chain Name
                dstChainName: string // Destination Chain Name
            }
            nonce: number
            ulnSendVersion: UlnVersion
        }
        guid: string // onchain guid
        message: string
        options: {
            // Adapter Params set on the source transaction
            lzReceive?: {
                gas: string
                value: string
            }
            nativeDrop?: {
                amount: string
                receiver: string
            }[]
            compose?: {
                index: number
                gas: string
                value: string
            }[]
            ordered?: boolean
        }
        payload?: string
        sendLibrary?: string
        onChainEvent: { // Transaction on the source chain
            chainName: string
            txHash: string
            blockHash: string
            blockNumber: number
        }
    }
    from: string // Address that initiated the transaction
}

API output: Return a boolean — true to allow signing, false to reject.


Getting Signatures to Change DVN On-Chain Configs

Setup

Depending on the environment (testnet/mainnet), fill in the appropriate information regarding DVN addresses and KMS key IDs in scripts/configChangePayloads/data/. The files should be named dvn-addresses-<environment>.json and kms-keyids-<environment>.json. See the existing testnet examples in that folder for reference.

Changing quorum

ts-node scripts/configChangePayloads/createSetQuorumSignatures.ts \
  -e <environment> \
  -c <comma-separated-chain-names> \
  --oldQuorum <number> \
  --newQuorum <number>

# Example:
# ts-node scripts/configChangePayloads/createSetQuorumSignatures.ts -e testnet -c bsc,avalanche,fantom --oldQuorum 2 --newQuorum 1

Adding or removing a signer

Set --shouldRevoke to 0 when adding a signer, or 1 when removing.

ts-node scripts/configChangePayloads/createAddOrRemoveSignerSignatures.ts \
  -e <environment> \
  -c <comma-separated-chain-names> \
  -q <quorum> \
  --signerAddress <address> \
  --shouldRevoke <0 or 1>

# Example:
# ts-node scripts/configChangePayloads/createAddOrRemoveSignerSignatures.ts -e testnet -c bsc,avalanche,fantom -q 1 --signerAddress 0x85e4857b7f15bbbbbc72d933a6357d3c22a0bbc7 --shouldRevoke 1

Troubleshooting

CDK: Deploy failed — resource already exists

Some resources have deletion protection policies. Delete these before redeploying:

  • CloudWatch log group: GasolinaMetricLogGroup
  • S3 bucket: providerconfigs-<projectName>-<environment>-gasolina

Non-CDK: Service fails with S3ProviderConfigUpdateFailed

The service does not have permissions to access the bucket specified in CONFIG_BUCKET_NAME. Verify the IAM role attached to your container has s3:GetObject permission on that bucket.

Provider health returns false

Check the service logs for specifics. Common causes:

  • Misconfigured RPC URLs in providers.json
  • Service lacks egress permissions to reach the provider URLs
  • If using a corporate proxy, ensure TLS is properly configured and pass the full proxy address in providers.json

It's important to note that if using multiple providers and any of them fail, the result will be false.

Signer info endpoint fails

Verify that:

  • Signer-related environment variables (SIGNER_TYPE, LAYERZERO_WALLETS or LAYERZERO_KMS_IDS) are set correctly
  • The service role has permissions to access Secrets Manager or KMS

About

This repository provides Infrastructure-As-Code (IAC) for installing Gasolina on AWS via CDK.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors