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 `