Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

abi.gno

12.51 Kb · 463 lines
  1package zkgm
  2
  3import (
  4	"bytes"
  5	"errors"
  6
  7	"gno.land/p/onbloc/encoding/abi"
  8	u256 "gno.land/p/onbloc/math/uint256"
  9)
 10
 11var InstructionSchema = abi.Schema{Fields: []abi.Field{
 12	{Type: abi.TypeUint8}, // version
 13	{Type: abi.TypeUint8}, // opcode
 14	{Type: abi.TypeBytes}, // operand
 15}}
 16
 17var CallSchema = abi.Schema{Fields: []abi.Field{
 18	{Type: abi.TypeBytes}, // sender
 19	{Type: abi.TypeBool},  // eureka
 20	{Type: abi.TypeBytes}, // contract_address / contractAddress
 21	{Type: abi.TypeBytes}, // contract_calldata / contractCalldata
 22}}
 23
 24var ZkgmPacketSchema = abi.Schema{Fields: []abi.Field{
 25	{Type: abi.TypeBytes32},                         // salt
 26	{Type: abi.TypeUint256},                         // path
 27	{Type: abi.TypeStruct, Sub: &InstructionSchema}, // instruction
 28}}
 29
 30var ForwardSchema = abi.Schema{Fields: []abi.Field{
 31	{Type: abi.TypeUint256},                         // path
 32	{Type: abi.TypeUint64},                          // timeout_height / timeoutHeight
 33	{Type: abi.TypeUint64},                          // timeout_timestamp / timeoutTimestamp
 34	{Type: abi.TypeStruct, Sub: &InstructionSchema}, // instruction
 35}}
 36
 37var BatchSchema = abi.Schema{Fields: []abi.Field{
 38	{Type: abi.TypeArray, Elem: &abi.Field{Type: abi.TypeStruct, Sub: &InstructionSchema}}, // instructions
 39}}
 40
 41var TokenOrderV2Schema = abi.Schema{Fields: []abi.Field{
 42	{Type: abi.TypeBytes},   // sender
 43	{Type: abi.TypeBytes},   // receiver
 44	{Type: abi.TypeBytes},   // base_token / baseToken
 45	{Type: abi.TypeUint256}, // base_amount / baseAmount
 46	{Type: abi.TypeBytes},   // quote_token / quoteToken
 47	{Type: abi.TypeUint256}, // quote_amount / quoteAmount
 48	{Type: abi.TypeUint8},   // kind
 49	{Type: abi.TypeBytes},   // metadata
 50}}
 51
 52var TokenOrderV1Schema = abi.Schema{Fields: []abi.Field{
 53	{Type: abi.TypeBytes},   // sender
 54	{Type: abi.TypeBytes},   // receiver
 55	{Type: abi.TypeBytes},   // base_token / baseToken
 56	{Type: abi.TypeUint256}, // base_amount / baseAmount
 57	{Type: abi.TypeString},  // base_token_symbol / baseTokenSymbol
 58	{Type: abi.TypeString},  // base_token_name / baseTokenName
 59	{Type: abi.TypeUint8},   // base_token_decimals / baseTokenDecimals
 60	{Type: abi.TypeUint256}, // base_token_path / baseTokenPath
 61	{Type: abi.TypeBytes},   // quote_token / quoteToken
 62	{Type: abi.TypeUint256}, // quote_amount / quoteAmount
 63}}
 64
 65var AckSchema = abi.Schema{Fields: []abi.Field{
 66	{Type: abi.TypeUint256}, // tag
 67	{Type: abi.TypeBytes},   // inner_ack / innerAck
 68}}
 69
 70var BatchAckSchema = abi.Schema{Fields: []abi.Field{
 71	{Type: abi.TypeArray, Elem: &abi.Field{Type: abi.TypeBytes}}, // acknowledgements
 72}}
 73
 74var TokenOrderAckSchema = abi.Schema{Fields: []abi.Field{
 75	{Type: abi.TypeUint256}, // fill_type / fillType
 76	{Type: abi.TypeBytes},   // market_maker / marketMaker
 77}}
 78
 79var TokenMetadataSchema = abi.Schema{Fields: []abi.Field{
 80	{Type: abi.TypeBytes}, // implementation
 81	{Type: abi.TypeBytes}, // initializer
 82}}
 83
 84// tokenInitializerSelector is the first 4 bytes of
 85// keccak256("initialize(address,address,string,string,uint8)"), the ZkgmERC20
 86// contract's initializer. Every TokenMetadata.Initializer carries this
 87// calldata verbatim regardless of what the wrapped token's origin is
 88// (Gno-native GRC20/native, or a real EVM ERC20): a receiving EVM chain only
 89// knows how to deploy and initialize a ZkgmERC20 clone from this exact wire
 90// format, so a Gno-only encoding is not a valid substitute for it.
 91var tokenInitializerSelector = []byte{0x84, 0x20, 0xce, 0x99}
 92
 93// TokenInitializerSchema mirrors the Solidity ABI params for ZkgmERC20's
 94// initialize(address authority, address minter, string name, string symbol,
 95// uint8 decimals), excluding the 4-byte selector. It is not a Union ZKGM
 96// top-level struct in com.rs or Types.sol.
 97var TokenInitializerSchema = abi.Schema{Fields: []abi.Field{
 98	{Type: abi.TypeAddress}, // authority
 99	{Type: abi.TypeAddress}, // minter
100	{Type: abi.TypeString},  // name
101	{Type: abi.TypeString},  // symbol
102	{Type: abi.TypeUint8},   // decimals
103}}
104
105var SolverMetadataSchema = abi.Schema{Fields: []abi.Field{
106	{Type: abi.TypeBytes}, // solverAddress / solver_address
107	{Type: abi.TypeBytes}, // metadata
108}}
109
110// PredictWrappedTokenSchema mirrors abi.encode(path, channel, token) used by Union's
111// _predictWrappedToken helper.
112var PredictWrappedTokenSchema = abi.Schema{Fields: []abi.Field{
113	{Type: abi.TypeUint256}, // path
114	{Type: abi.TypeUint32},  // channel / channelId
115	{Type: abi.TypeBytes},   // token / baseToken
116}}
117
118// PredictV2Schema mirrors abi.encode(path, channel, token, metadataImage) used
119// by Union's _predictWrappedTokenFromMetadataImageV2 helper.
120var PredictV2Schema = abi.Schema{Fields: []abi.Field{
121	{Type: abi.TypeUint256}, // path
122	{Type: abi.TypeUint32},  // channel / channelId
123	{Type: abi.TypeBytes},   // token / baseToken
124	{Type: abi.TypeUint256}, // metadataImage
125}}
126
127func EncodeZkgmPacket(p ZkgmPacket) ([]byte, error) {
128	return abi.Encode(ZkgmPacketSchema, []any{
129		p.Salt,
130		p.Path,
131		instructionValues(p.Instruction),
132	})
133}
134
135func DecodeZkgmPacket(data []byte) (ZkgmPacket, error) {
136	out, err := abi.Decode(ZkgmPacketSchema, data)
137	if err != nil {
138		return ZkgmPacket{}, err
139	}
140
141	return ZkgmPacket{
142		Salt:        out[0].([32]byte),
143		Path:        out[1].(*u256.Uint),
144		Instruction: instructionFromValues(out[2].([]any)),
145	}, nil
146}
147
148func EncodeInstruction(ins Instruction) ([]byte, error) {
149	return abi.Encode(InstructionSchema, instructionValues(ins))
150}
151
152func DecodeInstruction(data []byte) (Instruction, error) {
153	out, err := abi.Decode(InstructionSchema, data)
154	if err != nil {
155		return Instruction{}, err
156	}
157
158	return instructionFromValues(out), nil
159}
160
161func EncodeForward(f Forward) ([]byte, error) {
162	return abi.Encode(ForwardSchema, []any{
163		f.Path,
164		f.TimeoutHeight,
165		f.TimeoutTimestamp,
166		instructionValues(f.Instruction),
167	})
168}
169
170func DecodeForward(data []byte) (Forward, error) {
171	out, err := abi.Decode(ForwardSchema, data)
172	if err != nil {
173		return Forward{}, err
174	}
175
176	return Forward{
177		Path:             out[0].(*u256.Uint),
178		TimeoutHeight:    out[1].(uint64),
179		TimeoutTimestamp: out[2].(uint64),
180		Instruction:      instructionFromValues(out[3].([]any)),
181	}, nil
182}
183
184func EncodeCall(c Call) ([]byte, error) {
185	return abi.Encode(CallSchema, []any{
186		c.Sender,
187		c.Eureka,
188		c.ContractAddress,
189		c.ContractCalldata,
190	})
191}
192
193func DecodeCall(data []byte) (Call, error) {
194	out, err := abi.Decode(CallSchema, data)
195	if err != nil {
196		return Call{}, err
197	}
198
199	return Call{
200		Sender:           out[0].([]byte),
201		Eureka:           out[1].(bool),
202		ContractAddress:  out[2].([]byte),
203		ContractCalldata: out[3].([]byte),
204	}, nil
205}
206
207func EncodeBatch(b Batch) ([]byte, error) {
208	items := make([]any, len(b.Instructions))
209	for i, ins := range b.Instructions {
210		items[i] = instructionValues(ins)
211	}
212
213	return abi.Encode(BatchSchema, []any{items})
214}
215
216func DecodeBatch(data []byte) (Batch, error) {
217	out, err := abi.Decode(BatchSchema, data)
218	if err != nil {
219		return Batch{}, err
220	}
221
222	items := out[0].([]any)
223	instructions := make([]Instruction, len(items))
224
225	for i, item := range items {
226		instructions[i] = instructionFromValues(item.([]any))
227	}
228
229	return Batch{Instructions: instructions}, nil
230}
231
232func EncodeTokenOrderV1(o TokenOrderV1) ([]byte, error) {
233	return abi.Encode(TokenOrderV1Schema, []any{
234		o.Sender,
235		o.Receiver,
236		o.BaseToken,
237		o.BaseAmount,
238		o.BaseTokenSymbol,
239		o.BaseTokenName,
240		o.BaseTokenDecimals,
241		o.BaseTokenPath,
242		o.QuoteToken,
243		o.QuoteAmount,
244	})
245}
246
247func DecodeTokenOrderV1(data []byte) (TokenOrderV1, error) {
248	out, err := abi.Decode(TokenOrderV1Schema, data)
249	if err != nil {
250		return TokenOrderV1{}, err
251	}
252
253	return TokenOrderV1{
254		Sender:            out[0].([]byte),
255		Receiver:          out[1].([]byte),
256		BaseToken:         out[2].([]byte),
257		BaseAmount:        out[3].(*u256.Uint),
258		BaseTokenSymbol:   out[4].(string),
259		BaseTokenName:     out[5].(string),
260		BaseTokenDecimals: out[6].(uint8),
261		BaseTokenPath:     out[7].(*u256.Uint),
262		QuoteToken:        out[8].([]byte),
263		QuoteAmount:       out[9].(*u256.Uint),
264	}, nil
265}
266
267func EncodeTokenOrderV2(o TokenOrderV2) ([]byte, error) {
268	return abi.Encode(TokenOrderV2Schema, []any{
269		o.Sender,
270		o.Receiver,
271		o.BaseToken,
272		o.BaseAmount,
273		o.QuoteToken,
274		o.QuoteAmount,
275		o.Kind,
276		o.Metadata,
277	})
278}
279
280func DecodeTokenOrderV2(data []byte) (TokenOrderV2, error) {
281	out, err := abi.Decode(TokenOrderV2Schema, data)
282	if err != nil {
283		return TokenOrderV2{}, err
284	}
285
286	return TokenOrderV2{
287		Sender:      out[0].([]byte),
288		Receiver:    out[1].([]byte),
289		BaseToken:   out[2].([]byte),
290		BaseAmount:  out[3].(*u256.Uint),
291		QuoteToken:  out[4].([]byte),
292		QuoteAmount: out[5].(*u256.Uint),
293		Kind:        out[6].(uint8),
294		Metadata:    out[7].([]byte),
295	}, nil
296}
297
298// EncodeTokenInitializer encodes the ZkgmERC20 initialize(...) calldata
299// carried in TokenMetadata.Initializer. i.Authority/i.Minter default to the
300// zero address when nil; callers that need a real EVM authority/minter
301// (production sends targeting a real chain) set them explicitly.
302func EncodeTokenInitializer(i TokenInitializer) ([]byte, error) {
303	// Authority/Minter are EVM-only addresses (the Gno chain has no notion of
304	// either); fill with the 20-byte zero address when the caller left them nil.
305	authority := i.Authority
306	if len(authority) == 0 {
307		authority = make([]byte, 20)
308	}
309
310	minter := i.Minter
311	if len(minter) == 0 {
312		minter = make([]byte, 20)
313	}
314
315	body, err := abi.Encode(TokenInitializerSchema, []any{
316		authority,
317		minter,
318		i.Name,
319		i.Symbol,
320		i.Decimals,
321	})
322	if err != nil {
323		return nil, err
324	}
325
326	return append(append([]byte{}, tokenInitializerSelector...), body...), nil
327}
328
329// DecodeTokenInitializer decodes the ZkgmERC20 initialize(...) calldata
330// carried in TokenMetadata.Initializer, round-tripping every field encoded by
331// EncodeTokenInitializer (including Authority/Minter, which a receiving Gno
332// chain otherwise has no use for beyond display/reconstruction).
333func DecodeTokenInitializer(data []byte) (TokenInitializer, error) {
334	if len(data) < 4 || !bytes.Equal(data[:4], tokenInitializerSelector) {
335		return TokenInitializer{}, errors.New("zkgm: unrecognized token initializer selector")
336	}
337
338	out, err := abi.Decode(TokenInitializerSchema, data[4:])
339	if err != nil {
340		return TokenInitializer{}, err
341	}
342
343	return TokenInitializer{
344		Authority: out[0].([]byte),
345		Minter:    out[1].([]byte),
346		Name:      out[2].(string),
347		Symbol:    out[3].(string),
348		Decimals:  out[4].(uint8),
349	}, nil
350}
351
352func EncodeTokenMetadata(m TokenMetadata) ([]byte, error) {
353	return abi.Encode(TokenMetadataSchema, []any{
354		m.Implementation,
355		m.Initializer,
356	})
357}
358
359func DecodeTokenMetadata(data []byte) (TokenMetadata, error) {
360	out, err := abi.Decode(TokenMetadataSchema, data)
361	if err != nil {
362		return TokenMetadata{}, err
363	}
364
365	return TokenMetadata{
366		Implementation: out[0].([]byte),
367		Initializer:    out[1].([]byte),
368	}, nil
369}
370
371func EncodeSolverMetadata(m SolverMetadata) ([]byte, error) {
372	return abi.Encode(SolverMetadataSchema, []any{
373		m.SolverAddress,
374		m.Metadata,
375	})
376}
377
378func DecodeSolverMetadata(data []byte) (SolverMetadata, error) {
379	out, err := abi.Decode(SolverMetadataSchema, data)
380	if err != nil {
381		return SolverMetadata{}, err
382	}
383
384	return SolverMetadata{
385		SolverAddress: out[0].([]byte),
386		Metadata:      out[1].([]byte),
387	}, nil
388}
389
390func EncodeAck(a Ack) ([]byte, error) {
391	return abi.Encode(AckSchema, []any{
392		a.Tag,
393		a.InnerAck,
394	})
395}
396
397func DecodeAck(data []byte) (Ack, error) {
398	out, err := abi.Decode(AckSchema, data)
399	if err != nil {
400		return Ack{}, err
401	}
402
403	return Ack{
404		Tag:      out[0].(*u256.Uint),
405		InnerAck: out[1].([]byte),
406	}, nil
407}
408
409func EncodeBatchAck(a BatchAck) ([]byte, error) {
410	items := make([]any, len(a.Acknowledgements))
411	for i, ack := range a.Acknowledgements {
412		items[i] = ack
413	}
414
415	return abi.Encode(BatchAckSchema, []any{items})
416}
417
418func DecodeBatchAck(data []byte) (BatchAck, error) {
419	out, err := abi.Decode(BatchAckSchema, data)
420	if err != nil {
421		return BatchAck{}, err
422	}
423
424	items := out[0].([]any)
425	acks := make([][]byte, len(items))
426
427	for i, item := range items {
428		acks[i] = item.([]byte)
429	}
430
431	return BatchAck{Acknowledgements: acks}, nil
432}
433
434func EncodeTokenOrderAck(a TokenOrderAck) ([]byte, error) {
435	return abi.Encode(TokenOrderAckSchema, []any{
436		a.FillType,
437		a.MarketMaker,
438	})
439}
440
441func DecodeTokenOrderAck(data []byte) (TokenOrderAck, error) {
442	out, err := abi.Decode(TokenOrderAckSchema, data)
443	if err != nil {
444		return TokenOrderAck{}, err
445	}
446
447	return TokenOrderAck{
448		FillType:    out[0].(*u256.Uint),
449		MarketMaker: out[1].([]byte),
450	}, nil
451}
452
453func instructionValues(ins Instruction) []any {
454	return []any{ins.Version, ins.Opcode, ins.Operand}
455}
456
457func instructionFromValues(values []any) Instruction {
458	return Instruction{
459		Version: values[0].(uint8),
460		Opcode:  values[1].(uint8),
461		Operand: values[2].([]byte),
462	}
463}