github.com/ava-labs/subnet-evm@v0.6.4/accounts/abi/bind/precompilebind/precompile_event_template.go (about)

     1  // (c) 2019-2023, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  package precompilebind
     4  
     5  const tmplSourcePrecompileEventGo = `
     6  // Code generated
     7  // This file is a generated precompile contract config with stubbed abstract functions.
     8  // The file is generated by a template. Please inspect every code and comment in this file before use.
     9  
    10  package {{.Package}}
    11  
    12  import (
    13  	"math/big"
    14  
    15  	"github.com/ava-labs/subnet-evm/precompile/contract"
    16  	"github.com/ethereum/go-ethereum/common"
    17  )
    18  
    19  // CUSTOM CODE STARTS HERE
    20  // Reference imports to suppress errors from unused imports. This code and any unnecessary imports can be removed.
    21  var (
    22  	_ = big.NewInt
    23  	_ = common.Big0
    24  	_ = contract.LogGas
    25  )
    26  
    27  {{$structs := .Structs}}
    28  {{$contract := .Contract}}
    29  /* NOTE: Events can only be emitted in state-changing functions. So you cannot use events in read-only (view) functions.
    30  Events are generally emitted at the end of a state-changing function with AddLog method of the StateDB. The AddLog method takes 4 arguments:
    31  	1. Address of the contract that emitted the event.
    32  	2. Topic hashes of the event.
    33  	3. Encoded non-indexed data of the event.
    34  	4. Block number at which the event was emitted.
    35  The first argument is the address of the contract that emitted the event.
    36  Topics can be at most 4 elements, the first topic is the hash of the event signature and the rest are the indexed event arguments. There can be at most 3 indexed arguments.
    37  Topics cannot be fully unpacked into their original values since they're 32-bytes hashes.
    38  The non-indexed arguments are encoded using the ABI encoding scheme. The non-indexed arguments can be unpacked into their original values.
    39  Before packing the event, you need to calculate the gas cost of the event. The gas cost of an event is the base gas cost + the gas cost of the topics + the gas cost of the non-indexed data.
    40  See Get{EvetName}EventGasCost functions for more details.
    41  You can use the following code to emit an event in your state-changing precompile functions (generated packer might be different)):
    42  topics, data, err := PackMyEvent(
    43  	topic1,
    44  	topic2,
    45  	data1,
    46  	data2,
    47  )
    48  if err != nil {
    49  	return nil, remainingGas, err
    50  }
    51  accessibleState.GetStateDB().AddLog(
    52  	ContractAddress,
    53  	topics,
    54  	data,
    55  	accessibleState.GetBlockContext().Number().Uint64(),
    56  )
    57  */
    58  {{range .Contract.Events}}
    59  	{{$event := .}}
    60  	{{$createdDataStruct := false}}
    61  	{{$topicCount := 1}}
    62  	{{- range .Normalized.Inputs}}
    63  		{{- if .Indexed}}
    64  			{{$topicCount = add $topicCount 1}}
    65  			{{ continue }}
    66  		{{- end}}
    67  		{{- if not $createdDataStruct}}
    68  			{{$createdDataStruct = true}}
    69  			// {{$contract.Type}}{{$event.Normalized.Name}} represents a {{$event.Normalized.Name}} non-indexed event data raised by the {{$contract.Type}} contract.
    70  			type {{$event.Normalized.Name}}EventData struct {
    71  		{{- end}}
    72  		{{capitalise .Name}} {{bindtype .Type $structs}}
    73  	{{- end}}
    74  	{{- if $createdDataStruct}}
    75  			}
    76  	{{- end}}
    77  
    78  	// Get{{.Normalized.Name}}EventGasCost returns the gas cost of the event.
    79  	// The gas cost of an event is the base gas cost + the gas cost of the topics + the gas cost of the non-indexed data.
    80  	// The base gas cost and the gas cost of per topics are fixed and can be found in the contract package.
    81  	// The gas cost of the non-indexed data depends on the data type and the data size.
    82  	func Get{{.Normalized.Name}}EventGasCost({{if $createdDataStruct}} data {{.Normalized.Name}}EventData{{end}}) uint64 {
    83  		gas := contract.LogGas // base gas cost
    84  		{{if $topicCount | lt 1}}
    85  		// Add topics gas cost ({{$topicCount}} topics)
    86  		// Topics always include the signature hash of the event. The rest are the indexed event arguments.
    87  		gas += contract.LogTopicGas * {{$topicCount}}
    88  		{{end}}
    89  
    90  		{{range .Normalized.Inputs}}
    91  			{{- if not .Indexed}}
    92  				// CUSTOM CODE STARTS HERE
    93  				// TODO: calculate gas cost for packing the data.{{decapitalise .Name}} according to the type.
    94  				// Keep in mind that the data here will be encoded using the ABI encoding scheme.
    95  				// So the computation cost might change according to the data type + data size and should be charged accordingly.
    96  				// i.e gas += LogDataGas * uint64(len(data.{{decapitalise .Name}}))
    97  				gas += contract.LogDataGas // * ...
    98  				// CUSTOM CODE ENDS HERE
    99  			{{- end}}
   100  		{{- end}}
   101  
   102  		// CUSTOM CODE STARTS HERE
   103  		// TODO: do any additional gas cost calculation here (only if needed)
   104  		return gas
   105  	}
   106  
   107  	// Pack{{.Normalized.Name}}Event packs the event into the appropriate arguments for {{.Original.Name}}.
   108  	// It returns topic hashes and the encoded non-indexed data.
   109  	func Pack{{.Normalized.Name}}Event({{range .Normalized.Inputs}} {{if .Indexed}}{{decapitalise .Name}} {{bindtype .Type $structs}},{{end}}{{end}}{{if $createdDataStruct}} data {{.Normalized.Name}}EventData{{end}}) ([]common.Hash, []byte, error) {
   110  		return {{$contract.Type}}ABI.PackEvent("{{.Original.Name}}"{{range .Normalized.Inputs}},{{if .Indexed}}{{decapitalise .Name}}{{else}}data.{{capitalise .Name}}{{end}}{{end}})
   111  	}
   112  	{{ if $createdDataStruct }}
   113  		// Unpack{{.Normalized.Name}}EventData attempts to unpack non-indexed [dataBytes].
   114  		func Unpack{{.Normalized.Name}}EventData(dataBytes []byte) ({{.Normalized.Name}}EventData, error) {
   115  			eventData := {{.Normalized.Name}}EventData{}
   116  			err := {{$contract.Type}}ABI.UnpackIntoInterface(&eventData, "{{.Original.Name}}", dataBytes)
   117  			return eventData, err
   118  		}
   119  	{{else}}
   120  		// Unpack{{.Normalized.Name}}Event won't be generated because the event does not have any non-indexed data.
   121  	{{end}}
   122  {{end}}
   123  `