Go

SmartAccount Utilities

Functions

SignPayloadWithECDSA

Implementation of PayloadSigner which signs the payload using an ECDSA private key.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
payload[]byteThe payload that needs to be signed.
secretstringThe ECDSA private key.
client*clients.BaseClientNot used and should be nil.
var SignPayloadWithECDSA PayloadSigner = func(ctx context.Context, payload []byte, secret interface{}, client *clients.BaseClient) ([]byte, error)

Examples

Sign EIP712 transaction hash.

privateKey := os.Getenv("PRIVATE_KEY")
client, err := clients.DialBase(ZkSyncEraProvider)
if err != nil {
  log.Panic(err)
}
defer client.Close()

chainId, err := client.ChainID(context.Background())
if err != nil {
  log.Panic(err)
}

tx := zkTypes.Transaction712{
  Nonce:     big.NewInt(0),
  GasTipCap: big.NewInt(0),
  GasFeeCap: big.NewInt(1_000_000_000),
  Gas:       big.NewInt(1_000_000_000),
  To:        &Address2,
  Value:     big.NewInt(7_000_000_000),
  Data:      hexutil.Bytes{},
  ChainID:   chainId,
  From:      &Address1,
  Meta: &zkTypes.Eip712Meta{
    GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()),
  },
}

domain := eip712.ZkSyncEraEIP712Domain(chainId.Int64())

eip712Msg, err := tx.EIP712Message()
if err != nil {
  log.Panic(err)
}

hash, _, err := apitypes.TypedDataAndHash(apitypes.TypedData{
  Types: apitypes.Types{
    tx.EIP712Type():     tx.EIP712Types(),
    domain.EIP712Type(): domain.EIP712Types(),
  },
  PrimaryType: tx.EIP712Type(),
        Domain:      domain.EIP712Domain(),
        Message:     eip712Msg,
    })
if err != nil {
  log.Panic(err)
}

signature, err := accounts.SignPayloadWithECDSA(context.Background(), hash, privateKey, nil)
if err != nil {
  log.Panic(err)
}

Sign message hash.

privateKey := os.Getenv("PRIVATE_KEY")
signature, err := accounts.SignPayloadWithECDSA(context.Background(), ethAccounts.TextHash([]byte("Hello World!")), privateKey, nil)
if err != nil {
  log.Panic(err)
}

Sign typed data hash.

privateKey := os.Getenv("PRIVATE_KEY")
client, err := clients.DialBase(ZkSyncEraProvider)
if err != nil {
  log.Panic(err)
}
defer client.Close()

chainId, err := client.ChainID(context.Background())
if err != nil {
  log.Panic(err)
}

hash, _, err := apitypes.TypedDataAndHash(apitypes.TypedData{
        Domain: apitypes.TypedDataDomain{
            Name:    "Example",
            Version: "1",
            ChainId: math.NewHexOrDecimal256(chainId.Int64()),
        },
        Types: apitypes.Types{
            "Person": []apitypes.Type{
                {Name: "name", Type: "string"},
                {Name: "age", Type: "uint8"},
            },
            "EIP712Domain": []apitypes.Type{
                {Name: "name", Type: "string"},
                {Name: "version", Type: "string"},
                {Name: "chainId", Type: "uint256"},
            },
        },
        PrimaryType: "Person",
        Message: apitypes.TypedDataMessage{
            "name": "John",
            "age":  hexutil.EncodeUint64(30),
        },
    })
if err != nil {
  log.Panic(err)
}

signature, err := accounts.SignPayloadWithECDSA(context.Background(), hash, privateKey, nil)
if err != nil {
  log.Panic(err)
}

SignPayloadWithMultipleECDSA

Implementation of PayloadSigner which signs the payload using multiple ECDSA private keys. The signature is generated by concatenating signatures created by signing with each key individually. The length of the resulting signature is len(secret) * 65.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
payload[]byteThe payload that needs to be signed.
secret[]stringThe list of the ECDSA private keys.
client*clients.BaseClientNot used and should be nil.
var SignPayloadWithMultipleECDSA PayloadSigner = func(ctx context.Context, payload []byte, secret interface{}, client *clients.BaseClient) ([]byte, error)

Examples

Sign EIP712 transaction hash.

privateKey1 := os.Getenv("PRIVATE_KEY1")
privateKey2 := os.Getenv("PRIVATE_KEY2")
client, err := clients.DialBase(ZkSyncEraProvider)
if err != nil {
  log.Panic(err)
}
defer client.Close()

chainId, err := client.ChainID(context.Background())
if err != nil {
  log.Panic(err)
}

tx := zkTypes.Transaction712{
  Nonce:     big.NewInt(0),
  GasTipCap: big.NewInt(0),
  GasFeeCap: big.NewInt(1_000_000_000),
  Gas:       big.NewInt(1_000_000_000),
  To:        &Address2,
  Value:     big.NewInt(7_000_000_000),
  Data:      hexutil.Bytes{},
  ChainID:   big.NewInt(270),
  From:      &Address1,
  Meta: &zkTypes.Eip712Meta{
    GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()),
  },
}

domain := eip712.ZkSyncEraEIP712Domain(chainId.Int64())

eip712Msg, err := tx.EIP712Message()
if err != nil {
  log.Panic(err)
}

hash, _, err := apitypes.TypedDataAndHash(apitypes.TypedData{
  Types: apitypes.Types{
    tx.EIP712Type():     tx.EIP712Types(),
    domain.EIP712Type(): domain.EIP712Types(),
  },
  PrimaryType: tx.EIP712Type(),
        Domain:      domain.EIP712Domain(),
        Message:     eip712Msg,
    })
if err != nil {
  log.Panic(err)
}

signature, err := accounts.SignPayloadWithMultipleECDSA(context.Background(), hash, []string{privateKey1, privateKey2}, nil)
if err != nil {
  log.Panic(err)
}

Sign message hash.

privateKey1 := os.Getenv("PRIVATE_KEY1")
privateKey2 := os.Getenv("PRIVATE_KEY2")
signature, err := accounts.SignPayloadWithMultipleECDSA(context.Background(), hash, []string{privateKey1, privateKey2}, nil)
if err != nil {
  log.Panic(err)
}

Sign typed data hash.

privateKey1 := os.Getenv("PRIVATE_KEY1")
privateKey2 := os.Getenv("PRIVATE_KEY2")
client, err := clients.DialBase(ZkSyncEraProvider)
if err != nil {
    log.Panic(err)
}
defer client.Close()

chainId, err := client.ChainID(context.Background())
if err != nil {
    log.Panic(err)
}


hash, _, err := apitypes.TypedDataAndHash(apitypes.TypedData{
        Domain: apitypes.TypedDataDomain{
            Name:    "Example",
            Version: "1",
            ChainId: math.NewHexOrDecimal256(chainId.Int64()),
        },
        Types: apitypes.Types{
            "Person": []apitypes.Type{
                {Name: "name", Type: "string"},
                {Name: "age", Type: "uint8"},
            },
            "EIP712Domain": []apitypes.Type{
                {Name: "name", Type: "string"},
                {Name: "version", Type: "string"},
                {Name: "chainId", Type: "uint256"},
            },
        },
        PrimaryType: "Person",
        Message: apitypes.TypedDataMessage{
            "name": "John",
            "age":  hexutil.EncodeUint64(30),
        },
    })
if err != nil {
  log.Panic(err)
}

signature, err := accounts.SignPayloadWithMultipleECDSA(context.Background(), hash, []string{privateKey1, privateKey2}, nil)
if err != nil {
  log.Panic(err)
}

PopulateTransactionECDSA

Populates missing properties meant for signing using an ECDSA private key:

  • Populates tx.From using the address derived from the ECDSA private key.
  • Populates tx.Nonce via client.NonceAt().
  • Populates tx.Gas via client.EstimateGasL2(). If tx.From is not EOA, the estimation is done with address derived from the ECDSA private key.
  • Populates tx.GasFeeCap via client.SuggestGasPrice().
  • Populates tx.GasTipCap with 0 if is not set.
  • Populates tx.ChainID via client.ChainID().
  • Populates tx.Data with "0x".
  • Populates tx.Meta.GasPerPubdata with utils.DefaultGasPerPubdataLimit.

Expects the secret to be ECDSA private in hex format.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tx*zkTypes.Transaction712The transaction that needs to be populated.
secretstringThe ECDSA private key.
client*clients.BaseClientThe client which fetches data from the network.
var PopulateTransactionECDSA TransactionBuilder = func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error

Examples

privateKey := os.Getenv("PRIVATE_KEY")
client, err := clients.DialBase(ZkSyncEraProvider)
if err != nil {
  log.Panic(err)
}
defer client.Close()

tx := zkTypes.Transaction712{
  To:      &Address2,
  Value:   big.NewInt(7_000_000_000),
  From:    &Address1,
}

err = accounts.PopulateTransactionECDSA(context.Background(), &tx, privateKey, client)
if err != nil {
  log.Panic(err)
}

PopulateTransactionMultipleECDSA

Populates missing properties meant for signing using multiple ECDSA private keys. It uses PopulateTransactionECDSA, where the address of the first ECDSA key is set as the secret argument. Expects the secret to be a slice of ECDSA private in hex format.

Inputs

ParameterTypeDescription
ctxcontext.ContextContext.
tx*zkTypes.Transaction712The transaction that needs to be populated.
secret[]stringThe list of the ECDSA private keys.
client*clients.BaseClientThe client which fetches data from the network.
var PopulateTransactionMultipleECDSA TransactionBuilder = func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error

Examples

privateKey1 := os.Getenv("PRIVATE_KEY1")
privateKey2 := os.Getenv("PRIVATE_KEY2")
client, err := clients.DialBase(ZkSyncEraProvider)
if err != nil {
  log.Panic(err)
}
defer client.Close()

tx := zkTypes.Transaction712{
  To:      &Address2,
  Value:   big.NewInt(7_000_000_000),
  From:    &Address1,
}

err = accounts.PopulateTransactionECDSA(context.Background(), &tx, privateKey, client)
if err != nil {
  log.Panic(err)
}

Made with ❤️ by the ZKsync Community