@effectstream/sm 0.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/Stm.ts +88 -0
  2. package/delegate-wallet.ts +431 -0
  3. package/mod.ts +4 -0
  4. package/package.json +27 -0
  5. package/primitives/Primitive.ts +80 -0
  6. package/primitives/PrimitiveRegistry.ts +59 -0
  7. package/primitives/mod.ts +5 -0
  8. package/primitives/processing.ts +72 -0
  9. package/primitives/src/README.md +3 -0
  10. package/primitives/src/avail-generic/avail-generic-grammar.ts +5 -0
  11. package/primitives/src/avail-generic/avail-primitive.ts +103 -0
  12. package/primitives/src/bitcoin-address/bitcoin-grammar.ts +16 -0
  13. package/primitives/src/bitcoin-address/bitcoin-primitive.ts +113 -0
  14. package/primitives/src/builtin.ts +47 -0
  15. package/primitives/src/celestia-generic/celestia-generic-grammar.ts +5 -0
  16. package/primitives/src/celestia-generic/celestia-primitive.ts +97 -0
  17. package/primitives/src/evm-effectstream-l2/effectstream-l2-abi.ts +1 -0
  18. package/primitives/src/evm-effectstream-l2/effectstream-l2-primitive.ts +484 -0
  19. package/primitives/src/evm-erc1155/erc1155-abi.ts +1 -0
  20. package/primitives/src/evm-erc1155/erc1155-grammar.ts +13 -0
  21. package/primitives/src/evm-erc1155/erc1155-ivm.ts +104 -0
  22. package/primitives/src/evm-erc1155/erc1155-primitive.ts +242 -0
  23. package/primitives/src/evm-erc20/erc20-abi.ts +1 -0
  24. package/primitives/src/evm-erc20/erc20-grammar.ts +7 -0
  25. package/primitives/src/evm-erc20/erc20-ivm.ts +93 -0
  26. package/primitives/src/evm-erc20/erc20-primitive.test.ts +123 -0
  27. package/primitives/src/evm-erc20/erc20-primitive.ts +152 -0
  28. package/primitives/src/evm-erc721/erc721-abi.ts +1 -0
  29. package/primitives/src/evm-erc721/erc721-grammar.ts +9 -0
  30. package/primitives/src/evm-erc721/erc721-ivm.ts +85 -0
  31. package/primitives/src/evm-erc721/erc721-primitive.ts +149 -0
  32. package/primitives/src/evm-generic/evm-generic-primitive.ts +124 -0
  33. package/primitives/src/grammar.ts +34 -0
  34. package/primitives/src/midnight-generic/midnight-genetic-grammar.ts +8 -0
  35. package/primitives/src/midnight-generic/midnight-genetic.ts +271 -0
  36. package/primitives/src/midnight-nullifier/midnight-nullifier-grammar.ts +8 -0
  37. package/primitives/src/midnight-nullifier/midnight-nullifier.ts +114 -0
  38. package/primitives/src/mod.ts +81 -0
  39. package/primitives/src/near-account-watch/near-account-watch-grammar.ts +10 -0
  40. package/primitives/src/near-account-watch/near-account-watch-primitive.ts +106 -0
  41. package/primitives/src/near-generic/near-generic-grammar.ts +5 -0
  42. package/primitives/src/near-generic/near-generic-primitive.ts +105 -0
  43. package/primitives/src/near-intent/near-intent-grammar.ts +10 -0
  44. package/primitives/src/near-intent/near-intent-ivm.ts +71 -0
  45. package/primitives/src/near-intent/near-intent-primitive.ts +149 -0
  46. package/primitives/src/near-intent/near-intent-token-id-parser.ts +47 -0
  47. package/primitives/src/near-nep141/nep141-grammar.ts +7 -0
  48. package/primitives/src/near-nep141/nep141-ivm.ts +70 -0
  49. package/primitives/src/near-nep141/nep141-primitive.ts +117 -0
  50. package/primitives/src/near-nep171/nep171-grammar.ts +8 -0
  51. package/primitives/src/near-nep171/nep171-ivm.ts +71 -0
  52. package/primitives/src/near-nep171/nep171-primitive.ts +138 -0
  53. package/primitives/src/near-nep245/nep245-grammar.ts +11 -0
  54. package/primitives/src/near-nep245/nep245-ivm.ts +84 -0
  55. package/primitives/src/near-nep245/nep245-primitive.ts +147 -0
  56. package/primitives/src/utxorpc-generic/utxorpc-generic-grammar.ts +6 -0
  57. package/primitives/src/utxorpc-generic/utxorpc-generic.ts +88 -0
  58. package/primitives/types.ts +14 -0
  59. package/types.ts +28 -0
  60. package/verify-signature.ts +51 -0
@@ -0,0 +1,104 @@
1
+ import { PrimitiveTypeEVMERC1155 } from "../builtin.ts";
2
+
3
+ /**
4
+ * Creates a new IVM for the ERC1155 token with the given name.
5
+ * This will track the current owner of each token.
6
+ * @param name - The name of the ERC1155 token.
7
+ * @returns A string containing the SQL script to create the IVM.
8
+ */
9
+ export function erc1155Ivm(name: string) {
10
+ const lowerName = name.toLowerCase();
11
+ const validSQLName = lowerName.replace(/[^a-zA-Z0-9_]/g, "");
12
+ if (validSQLName !== lowerName) {
13
+ throw new Error(`Invalid name: ${name}`);
14
+ }
15
+
16
+ const ownershipTable =
17
+ `primitives.erc1155_ownership_intermediate_${validSQLName}`;
18
+
19
+ return `
20
+ -- Intermediate table for current ERC1155 ownership (maintained by triggers)
21
+ CREATE TABLE ${ownershipTable} (
22
+ primitive_name TEXT NOT NULL,
23
+ token_id TEXT NOT NULL,
24
+ owner_address TEXT NOT NULL,
25
+ amount BIGINT NOT NULL,
26
+ last_transfer_block_height INTEGER NOT NULL,
27
+ last_transfer_id INTEGER NOT NULL,
28
+ PRIMARY KEY (primitive_name, token_id, owner_address)
29
+ );
30
+
31
+ -- Trigger function to maintain current ownership
32
+ CREATE OR REPLACE FUNCTION update_erc1155_ownership_${validSQLName}() RETURNS TRIGGER AS $$
33
+ BEGIN
34
+ -- Only process ERC1155 transfers for this specific primitive
35
+ IF NEW.payload_type = '${PrimitiveTypeEVMERC1155}' AND NEW.primitive_name = '${name}' THEN
36
+ -- Decrease balance of the sender if it's not a mint operation
37
+ IF NOT (NEW.payload->>'isMint')::boolean THEN
38
+ UPDATE ${ownershipTable}
39
+ SET amount = amount - (NEW.payload->>'amount')::bigint,
40
+ last_transfer_block_height = NEW.effectstream_block_height,
41
+ last_transfer_id = NEW.id
42
+ WHERE primitive_name = NEW.primitive_name
43
+ AND token_id = NEW.payload->>'tokenId'
44
+ AND owner_address = lower(NEW.payload->>'from');
45
+
46
+ -- Clean up entries with no tokens left
47
+ DELETE FROM ${ownershipTable}
48
+ WHERE primitive_name = NEW.primitive_name
49
+ AND token_id = NEW.payload->>'tokenId'
50
+ AND owner_address = lower(NEW.payload->>'from')
51
+ AND amount <= 0;
52
+ END IF;
53
+
54
+ -- Increase balance of the receiver if it's not a burn operation
55
+ IF NOT (NEW.payload->>'isBurn')::boolean THEN
56
+ INSERT INTO ${ownershipTable} (
57
+ primitive_name,
58
+ token_id,
59
+ owner_address,
60
+ amount,
61
+ last_transfer_block_height,
62
+ last_transfer_id
63
+ ) VALUES (
64
+ NEW.primitive_name,
65
+ NEW.payload->>'tokenId',
66
+ lower(NEW.payload->>'to'),
67
+ (NEW.payload->>'amount')::bigint,
68
+ NEW.effectstream_block_height,
69
+ NEW.id
70
+ )
71
+ ON CONFLICT (primitive_name, token_id, owner_address) DO UPDATE SET
72
+ amount = ${ownershipTable}.amount + (NEW.payload->>'amount')::bigint,
73
+ last_transfer_block_height = NEW.effectstream_block_height,
74
+ last_transfer_id = NEW.id;
75
+ END IF;
76
+ END IF;
77
+
78
+ RETURN NEW;
79
+ END;
80
+ $$ LANGUAGE plpgsql;
81
+
82
+ -- Create trigger on primitive_accounting
83
+ CREATE TRIGGER trigger_update_erc1155_ownership_${validSQLName}
84
+ AFTER INSERT ON effectstream.primitive_accounting
85
+ FOR EACH ROW
86
+ EXECUTE FUNCTION update_erc1155_ownership_${validSQLName}();
87
+
88
+ -- Simple incrementally maintained view on the intermediate table
89
+ SELECT pgivm.create_immv('primitives.erc1155_ownership_view_${validSQLName}',
90
+ 'SELECT
91
+ primitive_name,
92
+ token_id,
93
+ owner_address,
94
+ amount
95
+ FROM ${ownershipTable}
96
+ WHERE amount > 0;
97
+ ');
98
+ `;
99
+ }
100
+
101
+ // Naming helpers kept in this file to co-locate schema naming with IVM DDL
102
+ export const ERC1155_VIEW_PREFIX = "erc1155_ownership_view_" as const;
103
+ export const ERC1155_INTERMEDIATE_PREFIX =
104
+ "erc1155_ownership_intermediate_" as const;
@@ -0,0 +1,242 @@
1
+ import { Value } from "@sinclair/typebox/value";
2
+ import type { StaticDecode } from "@sinclair/typebox";
3
+ import {
4
+ type ConfigSyncProtocolType,
5
+ type FlattenSyncProtocolIOFor,
6
+ getEvmEvent,
7
+ type ProtocolPrimitiveMap,
8
+ } from "@effectstream/config";
9
+ import {
10
+ type AddressAndType,
11
+ AddressType,
12
+ type EvmAddress,
13
+ type EffectstreamBlockNumber,
14
+ TypeboxHelpers,
15
+ } from "@effectstream/utils";
16
+ import { type JsonObject, Primitive } from "@effectstream/sm";
17
+ import {
18
+ type CommandTuple,
19
+ generateRawStmInput,
20
+ type ParamToData,
21
+ } from "@effectstream/concise";
22
+ import type { StateUpdateStream } from "@effectstream/coroutine";
23
+ import { ERC1155_VIEW_PREFIX, erc1155Ivm } from "./erc1155-ivm.ts";
24
+ import { ERC1155_INTERMEDIATE_PREFIX } from "./erc1155-ivm.ts";
25
+ import { erc1155 } from "./erc1155-abi.ts";
26
+ import { erc1155Grammar } from "./erc1155-grammar.ts";
27
+ import { PrimitiveTypeEVMERC1155 } from "../builtin.ts";
28
+
29
+ /**
30
+ * Erc721 Primitive
31
+ *
32
+ * This is a concrete implementation of the Primitive class for ERC721.
33
+ */
34
+
35
+ export class Erc1155Primitive extends Primitive<
36
+ ConfigSyncProtocolType.EVM_RPC_PARALLEL,
37
+ typeof erc1155Grammar
38
+ > {
39
+ // Primitive defined
40
+ readonly internalTypeName = PrimitiveTypeEVMERC1155;
41
+ readonly abi = [
42
+ getEvmEvent(
43
+ erc1155.abi,
44
+ "TransferSingle(address,address,address,uint256,uint256)"
45
+ ),
46
+ getEvmEvent(
47
+ erc1155.abi,
48
+ "TransferBatch(address,address,address,uint256[],uint256[])"
49
+ ),
50
+ ];
51
+ override grammar = erc1155Grammar;
52
+ readonly contractAddress: EvmAddress;
53
+ // Dynamic table to track the owner of each token.
54
+ override dynamicTables = erc1155Ivm;
55
+ override getIntermediatePrefix(): string[] {
56
+ return [ERC1155_INTERMEDIATE_PREFIX];
57
+ }
58
+ override getViewPrefix(): string[] {
59
+ return [ERC1155_VIEW_PREFIX];
60
+ }
61
+
62
+ constructor(config: {
63
+ instanceName: string;
64
+ startBlockHeight: number;
65
+ contractAddress: EvmAddress;
66
+ stateMachinePrefix: string | undefined;
67
+ }) {
68
+ super(config);
69
+ this.contractAddress = Value.Decode(
70
+ TypeboxHelpers.Evm.Address,
71
+ config.contractAddress
72
+ );
73
+ }
74
+
75
+ override *getPayload(
76
+ _: EffectstreamBlockNumber,
77
+ primitiveTransactionData: FlattenSyncProtocolIOFor<ConfigSyncProtocolType.EVM_RPC_PARALLEL>
78
+ ): StateUpdateStream<{
79
+ isBatched: boolean;
80
+ data: {
81
+ fromAddressAndType: AddressAndType;
82
+ stateMachinePayload: StaticDecode<
83
+ CommandTuple<string, typeof erc1155Grammar>
84
+ > | null;
85
+ accountingPayload: JsonObject;
86
+ }[];
87
+ }> {
88
+ const abiFunctionName = primitiveTransactionData.output.payloadType;
89
+ const data: {
90
+ isBatched: boolean;
91
+ data: {
92
+ fromAddressAndType: AddressAndType;
93
+ stateMachinePayload: StaticDecode<
94
+ CommandTuple<string, typeof erc1155Grammar>
95
+ > | null;
96
+ accountingPayload: JsonObject;
97
+ }[];
98
+ } = {
99
+ isBatched: false,
100
+ data: [],
101
+ };
102
+
103
+ switch (abiFunctionName) {
104
+ case "TransferSingle": {
105
+ const { operator, from, to, id, value } =
106
+ primitiveTransactionData.output.payload;
107
+ const toAddr = Value.Decode(
108
+ TypeboxHelpers.Evm.Address,
109
+ to.toLowerCase()
110
+ );
111
+ const operatorAddr = Value.Decode(
112
+ TypeboxHelpers.Evm.Address,
113
+ operator.toLowerCase()
114
+ );
115
+ const fromAddr = Value.Decode(
116
+ TypeboxHelpers.Evm.Address,
117
+ from.toLowerCase()
118
+ );
119
+ const isBurn = Boolean(
120
+ toAddr.toLocaleLowerCase().match(/^0x0+(dead)?$/g)
121
+ );
122
+ const isMint = Boolean(
123
+ fromAddr.toLocaleLowerCase().match(/^0x0+(dead)?$/g)
124
+ );
125
+ const tokenId = Value.Decode(TypeboxHelpers.Uint256, id);
126
+ const amount = Value.Decode(TypeboxHelpers.Uint256, value);
127
+
128
+ const accountingPayload: ParamToData<typeof erc1155Grammar> = {
129
+ type: abiFunctionName,
130
+ to: toAddr,
131
+ from: fromAddr,
132
+ tokenId: tokenId,
133
+ amount: amount,
134
+ isBurn: isBurn,
135
+ isMint: isMint,
136
+ operator: operatorAddr,
137
+ };
138
+ const stateMachinePayload: StaticDecode<
139
+ CommandTuple<string, typeof this.grammar>
140
+ > | null = this.stateMachinePrefix
141
+ ? generateRawStmInput(
142
+ this.grammar,
143
+ this.stateMachinePrefix,
144
+ accountingPayload
145
+ )
146
+ : null;
147
+
148
+ data.data.push({
149
+ fromAddressAndType: {
150
+ type: AddressType.NONE,
151
+ address: "0x0",
152
+ },
153
+ accountingPayload,
154
+ stateMachinePayload,
155
+ });
156
+ break;
157
+ }
158
+ case "TransferBatch": {
159
+ // inputs":[
160
+ // {"name":"operator","type":"address","indexed":true,"internalType":"address"},
161
+ // {"name":"from","type":"address","indexed":true,"internalType":"address"},
162
+ // {"name":"to","type":"address","indexed":true,"internalType":"address"},
163
+ // {"name":"ids","type":"uint256[]","indexed":false,"internalType":"uint256[]"},
164
+ // {"name":"values","type":"uint256[]","indexed":false,"internalType":"uint256[]"}
165
+ // ]
166
+ data.isBatched = true;
167
+ const { operator, from, to, ids, values } =
168
+ primitiveTransactionData.output.payload;
169
+ const toAddr = Value.Decode(
170
+ TypeboxHelpers.Evm.Address,
171
+ to.toLowerCase()
172
+ );
173
+ const operatorAddr = Value.Decode(
174
+ TypeboxHelpers.Evm.Address,
175
+ operator.toLowerCase()
176
+ );
177
+ const fromAddr = Value.Decode(
178
+ TypeboxHelpers.Evm.Address,
179
+ from.toLowerCase()
180
+ );
181
+ const isBurn = Boolean(
182
+ toAddr.toLocaleLowerCase().match(/^0x0+(dead)?$/g)
183
+ );
184
+ const isMint = Boolean(
185
+ fromAddr.toLocaleLowerCase().match(/^0x0+(dead)?$/g)
186
+ );
187
+
188
+ const itemsCount = ids.length;
189
+ for (let i = 0; i < itemsCount; i++) {
190
+ const tokenId = Value.Decode(TypeboxHelpers.Uint256, ids[i]);
191
+ const amount = Value.Decode(TypeboxHelpers.Uint256, values[i]);
192
+
193
+ const accountingPayload: ParamToData<typeof erc1155Grammar> = {
194
+ type: abiFunctionName,
195
+ to: toAddr,
196
+ from: fromAddr,
197
+ tokenId: tokenId,
198
+ amount: amount,
199
+ isBurn: isBurn,
200
+ isMint: isMint,
201
+ operator: operatorAddr,
202
+ };
203
+ const stateMachinePayload: StaticDecode<
204
+ CommandTuple<string, typeof this.grammar>
205
+ > | null = this.stateMachinePrefix
206
+ ? generateRawStmInput(
207
+ this.grammar,
208
+ this.stateMachinePrefix,
209
+ accountingPayload
210
+ )
211
+ : null;
212
+
213
+ data.data.push({
214
+ fromAddressAndType: {
215
+ type: AddressType.NONE,
216
+ address: "0x0",
217
+ },
218
+ accountingPayload,
219
+ stateMachinePayload,
220
+ });
221
+ }
222
+ break;
223
+ }
224
+ default:
225
+ throw new Error(`Unknown ABI function name: ${abiFunctionName}`);
226
+ }
227
+
228
+ return data;
229
+ }
230
+
231
+ override getConfig(): ProtocolPrimitiveMap[ConfigSyncProtocolType.EVM_RPC_PARALLEL] {
232
+ return {
233
+ name: this.instanceName,
234
+ type: this.internalTypeName,
235
+ startBlockHeight: this.startBlockHeight,
236
+ contractAddress: this.contractAddress as EvmAddress,
237
+ abi: this.abi,
238
+ // TODO This should be optional.
239
+ scheduledPrefix: this.stateMachinePrefix ?? "",
240
+ } as const;
241
+ }
242
+ }
@@ -0,0 +1 @@
1
+ export const erc20 = {"abi":[{"type":"constructor","inputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"allowance","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"spender","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"approve","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"balanceOf","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"mint","inputs":[{"name":"_to","type":"address","internalType":"address"},{"name":"_amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"transfer","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferFrom","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"event","name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"spender","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"value","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"error","name":"ERC20InsufficientAllowance","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"allowance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC20InsufficientBalance","inputs":[{"name":"sender","type":"address","internalType":"address"},{"name":"balance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"ERC20InvalidApprover","inputs":[{"name":"approver","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidReceiver","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSender","inputs":[{"name":"sender","type":"address","internalType":"address"}]},{"type":"error","name":"ERC20InvalidSpender","inputs":[{"name":"spender","type":"address","internalType":"address"}]}],"bytecode":{"object":"0x608060405234801561001057600080fd5b506040518060400160405280600a81526020017f4d6f636b204552433230000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f4d45524300000000000000000000000000000000000000000000000000000000815250816003908161008c91906102f4565b50806004908161009c91906102f4565b5050506103c6565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061012557607f821691505b602082108103610138576101376100de565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026101a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610163565b6101aa8683610163565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006101f16101ec6101e7846101c2565b6101cc565b6101c2565b9050919050565b6000819050919050565b61020b836101d6565b61021f610217826101f8565b848454610170565b825550505050565b600090565b610234610227565b61023f818484610202565b505050565b5b818110156102635761025860008261022c565b600181019050610245565b5050565b601f8211156102a8576102798161013e565b61028284610153565b81016020851015610291578190505b6102a561029d85610153565b830182610244565b50505b505050565b600082821c905092915050565b60006102cb600019846008026102ad565b1980831691505092915050565b60006102e483836102ba565b9150826002028217905092915050565b6102fd826100a4565b67ffffffffffffffff811115610316576103156100af565b5b610320825461010d565b61032b828285610267565b600060209050601f83116001811461035e576000841561034c578287015190505b61035685826102d8565b8655506103be565b601f19841661036c8661013e565b60005b828110156103945784890151825560018201915060208501945060208101905061036f565b868310156103b157848901516103ad601f8916826102ba565b8355505b6001600288020188555050505b505050505050565b610f0c806103d56000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c806340c10f191161006657806340c10f191461015d57806370a082311461017957806395d89b41146101a9578063a9059cbb146101c7578063dd62ed3e146101f75761009e565b806306fdde03146100a3578063095ea7b3146100c157806318160ddd146100f157806323b872dd1461010f578063313ce5671461013f575b600080fd5b6100ab610227565b6040516100b89190610b60565b60405180910390f35b6100db60048036038101906100d69190610c1b565b6102b9565b6040516100e89190610c76565b60405180910390f35b6100f96102dc565b6040516101069190610ca0565b60405180910390f35b61012960048036038101906101249190610cbb565b6102e6565b6040516101369190610c76565b60405180910390f35b610147610315565b6040516101549190610d2a565b60405180910390f35b61017760048036038101906101729190610c1b565b61031e565b005b610193600480360381019061018e9190610d45565b61032c565b6040516101a09190610ca0565b60405180910390f35b6101b1610374565b6040516101be9190610b60565b60405180910390f35b6101e160048036038101906101dc9190610c1b565b610406565b6040516101ee9190610c76565b60405180910390f35b610211600480360381019061020c9190610d72565b610429565b60405161021e9190610ca0565b60405180910390f35b60606003805461023690610de1565b80601f016020809104026020016040519081016040528092919081815260200182805461026290610de1565b80156102af5780601f10610284576101008083540402835291602001916102af565b820191906000526020600020905b81548152906001019060200180831161029257829003601f168201915b5050505050905090565b6000806102c46104b0565b90506102d18185856104b8565b600191505092915050565b6000600254905090565b6000806102f16104b0565b90506102fe8582856104ca565b61030985858561055e565b60019150509392505050565b60006012905090565b6103288282610652565b5050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60606004805461038390610de1565b80601f01602080910402602001604051908101604052809291908181526020018280546103af90610de1565b80156103fc5780601f106103d1576101008083540402835291602001916103fc565b820191906000526020600020905b8154815290600101906020018083116103df57829003601f168201915b5050505050905090565b6000806104116104b0565b905061041e81858561055e565b600191505092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b6104c583838360016106d4565b505050565b60006104d68484610429565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146105585781811015610548578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161053f93929190610e21565b60405180910390fd5b610557848484840360006106d4565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036105d05760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016105c79190610e58565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036106425760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016106399190610e58565b60405180910390fd5b61064d8383836108ab565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036106c45760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016106bb9190610e58565b60405180910390fd5b6106d0600083836108ab565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036107465760006040517fe602df0500000000000000000000000000000000000000000000000000000000815260040161073d9190610e58565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036107b85760006040517f94280d620000000000000000000000000000000000000000000000000000000081526004016107af9190610e58565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080156108a5578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161089c9190610ca0565b60405180910390a35b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036108fd5780600260008282546108f19190610ea2565b925050819055506109d0565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015610989578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161098093929190610e21565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a195780600260008282540392505081905550610a66565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610ac39190610ca0565b60405180910390a3505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610b0a578082015181840152602081019050610aef565b60008484015250505050565b6000601f19601f8301169050919050565b6000610b3282610ad0565b610b3c8185610adb565b9350610b4c818560208601610aec565b610b5581610b16565b840191505092915050565b60006020820190508181036000830152610b7a8184610b27565b905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610bb282610b87565b9050919050565b610bc281610ba7565b8114610bcd57600080fd5b50565b600081359050610bdf81610bb9565b92915050565b6000819050919050565b610bf881610be5565b8114610c0357600080fd5b50565b600081359050610c1581610bef565b92915050565b60008060408385031215610c3257610c31610b82565b5b6000610c4085828601610bd0565b9250506020610c5185828601610c06565b9150509250929050565b60008115159050919050565b610c7081610c5b565b82525050565b6000602082019050610c8b6000830184610c67565b92915050565b610c9a81610be5565b82525050565b6000602082019050610cb56000830184610c91565b92915050565b600080600060608486031215610cd457610cd3610b82565b5b6000610ce286828701610bd0565b9350506020610cf386828701610bd0565b9250506040610d0486828701610c06565b9150509250925092565b600060ff82169050919050565b610d2481610d0e565b82525050565b6000602082019050610d3f6000830184610d1b565b92915050565b600060208284031215610d5b57610d5a610b82565b5b6000610d6984828501610bd0565b91505092915050565b60008060408385031215610d8957610d88610b82565b5b6000610d9785828601610bd0565b9250506020610da885828601610bd0565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610df957607f821691505b602082108103610e0c57610e0b610db2565b5b50919050565b610e1b81610ba7565b82525050565b6000606082019050610e366000830186610e12565b610e436020830185610c91565b610e506040830184610c91565b949350505050565b6000602082019050610e6d6000830184610e12565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610ead82610be5565b9150610eb883610be5565b9250828201905080821115610ed057610ecf610e73565b5b9291505056fea2646970667358221220e3860444d9a2c1a6c52dcf91a6a77c6acbea4df2a988185a99dbb137b2b71eb664736f6c634300081e0033","sourceMap":"129:174:20:-:0;;;162:44;;;;;;;;;;1601:113:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1675:5;1667;:13;;;;;;:::i;:::-;;1700:7;1690;:17;;;;;;:::i;:::-;;1601:113;;129:174:20;;7:99:42;59:6;93:5;87:12;77:22;;7:99;;;:::o;112:180::-;160:77;157:1;150:88;257:4;254:1;247:15;281:4;278:1;271:15;298:180;346:77;343:1;336:88;443:4;440:1;433:15;467:4;464:1;457:15;484:320;528:6;565:1;559:4;555:12;545:22;;612:1;606:4;602:12;633:18;623:81;;689:4;681:6;677:17;667:27;;623:81;751:2;743:6;740:14;720:18;717:38;714:84;;770:18;;:::i;:::-;714:84;535:269;484:320;;;:::o;810:141::-;859:4;882:3;874:11;;905:3;902:1;895:14;939:4;936:1;926:18;918:26;;810:141;;;:::o;957:93::-;994:6;1041:2;1036;1029:5;1025:14;1021:23;1011:33;;957:93;;;:::o;1056:107::-;1100:8;1150:5;1144:4;1140:16;1119:37;;1056:107;;;;:::o;1169:393::-;1238:6;1288:1;1276:10;1272:18;1311:97;1341:66;1330:9;1311:97;:::i;:::-;1429:39;1459:8;1448:9;1429:39;:::i;:::-;1417:51;;1501:4;1497:9;1490:5;1486:21;1477:30;;1550:4;1540:8;1536:19;1529:5;1526:30;1516:40;;1245:317;;1169:393;;;;;:::o;1568:77::-;1605:7;1634:5;1623:16;;1568:77;;;:::o;1651:60::-;1679:3;1700:5;1693:12;;1651:60;;;:::o;1717:142::-;1767:9;1800:53;1818:34;1827:24;1845:5;1827:24;:::i;:::-;1818:34;:::i;:::-;1800:53;:::i;:::-;1787:66;;1717:142;;;:::o;1865:75::-;1908:3;1929:5;1922:12;;1865:75;;;:::o;1946:269::-;2056:39;2087:7;2056:39;:::i;:::-;2117:91;2166:41;2190:16;2166:41;:::i;:::-;2158:6;2151:4;2145:11;2117:91;:::i;:::-;2111:4;2104:105;2022:193;1946:269;;;:::o;2221:73::-;2266:3;2221:73;:::o;2300:189::-;2377:32;;:::i;:::-;2418:65;2476:6;2468;2462:4;2418:65;:::i;:::-;2353:136;2300:189;;:::o;2495:186::-;2555:120;2572:3;2565:5;2562:14;2555:120;;;2626:39;2663:1;2656:5;2626:39;:::i;:::-;2599:1;2592:5;2588:13;2579:22;;2555:120;;;2495:186;;:::o;2687:543::-;2788:2;2783:3;2780:11;2777:446;;;2822:38;2854:5;2822:38;:::i;:::-;2906:29;2924:10;2906:29;:::i;:::-;2896:8;2892:44;3089:2;3077:10;3074:18;3071:49;;;3110:8;3095:23;;3071:49;3133:80;3189:22;3207:3;3189:22;:::i;:::-;3179:8;3175:37;3162:11;3133:80;:::i;:::-;2792:431;;2777:446;2687:543;;;:::o;3236:117::-;3290:8;3340:5;3334:4;3330:16;3309:37;;3236:117;;;;:::o;3359:169::-;3403:6;3436:51;3484:1;3480:6;3472:5;3469:1;3465:13;3436:51;:::i;:::-;3432:56;3517:4;3511;3507:15;3497:25;;3410:118;3359:169;;;;:::o;3533:295::-;3609:4;3755:29;3780:3;3774:4;3755:29;:::i;:::-;3747:37;;3817:3;3814:1;3810:11;3804:4;3801:21;3793:29;;3533:295;;;;:::o;3833:1395::-;3950:37;3983:3;3950:37;:::i;:::-;4052:18;4044:6;4041:30;4038:56;;;4074:18;;:::i;:::-;4038:56;4118:38;4150:4;4144:11;4118:38;:::i;:::-;4203:67;4263:6;4255;4249:4;4203:67;:::i;:::-;4297:1;4321:4;4308:17;;4353:2;4345:6;4342:14;4370:1;4365:618;;;;5027:1;5044:6;5041:77;;;5093:9;5088:3;5084:19;5078:26;5069:35;;5041:77;5144:67;5204:6;5197:5;5144:67;:::i;:::-;5138:4;5131:81;5000:222;4335:887;;4365:618;4417:4;4413:9;4405:6;4401:22;4451:37;4483:4;4451:37;:::i;:::-;4510:1;4524:208;4538:7;4535:1;4532:14;4524:208;;;4617:9;4612:3;4608:19;4602:26;4594:6;4587:42;4668:1;4660:6;4656:14;4646:24;;4715:2;4704:9;4700:18;4687:31;;4561:4;4558:1;4554:12;4549:17;;4524:208;;;4760:6;4751:7;4748:19;4745:179;;;4818:9;4813:3;4809:19;4803:26;4861:48;4903:4;4895:6;4891:17;4880:9;4861:48;:::i;:::-;4853:6;4846:64;4768:156;4745:179;4970:1;4966;4958:6;4954:14;4950:22;4944:4;4937:36;4372:611;;;4335:887;;3925:1303;;;3833:1395;;:::o;129:174:20:-;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561001057600080fd5b506004361061009e5760003560e01c806340c10f191161006657806340c10f191461015d57806370a082311461017957806395d89b41146101a9578063a9059cbb146101c7578063dd62ed3e146101f75761009e565b806306fdde03146100a3578063095ea7b3146100c157806318160ddd146100f157806323b872dd1461010f578063313ce5671461013f575b600080fd5b6100ab610227565b6040516100b89190610b60565b60405180910390f35b6100db60048036038101906100d69190610c1b565b6102b9565b6040516100e89190610c76565b60405180910390f35b6100f96102dc565b6040516101069190610ca0565b60405180910390f35b61012960048036038101906101249190610cbb565b6102e6565b6040516101369190610c76565b60405180910390f35b610147610315565b6040516101549190610d2a565b60405180910390f35b61017760048036038101906101729190610c1b565b61031e565b005b610193600480360381019061018e9190610d45565b61032c565b6040516101a09190610ca0565b60405180910390f35b6101b1610374565b6040516101be9190610b60565b60405180910390f35b6101e160048036038101906101dc9190610c1b565b610406565b6040516101ee9190610c76565b60405180910390f35b610211600480360381019061020c9190610d72565b610429565b60405161021e9190610ca0565b60405180910390f35b60606003805461023690610de1565b80601f016020809104026020016040519081016040528092919081815260200182805461026290610de1565b80156102af5780601f10610284576101008083540402835291602001916102af565b820191906000526020600020905b81548152906001019060200180831161029257829003601f168201915b5050505050905090565b6000806102c46104b0565b90506102d18185856104b8565b600191505092915050565b6000600254905090565b6000806102f16104b0565b90506102fe8582856104ca565b61030985858561055e565b60019150509392505050565b60006012905090565b6103288282610652565b5050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60606004805461038390610de1565b80601f01602080910402602001604051908101604052809291908181526020018280546103af90610de1565b80156103fc5780601f106103d1576101008083540402835291602001916103fc565b820191906000526020600020905b8154815290600101906020018083116103df57829003601f168201915b5050505050905090565b6000806104116104b0565b905061041e81858561055e565b600191505092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b6104c583838360016106d4565b505050565b60006104d68484610429565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146105585781811015610548578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161053f93929190610e21565b60405180910390fd5b610557848484840360006106d4565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036105d05760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016105c79190610e58565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036106425760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016106399190610e58565b60405180910390fd5b61064d8383836108ab565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036106c45760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016106bb9190610e58565b60405180910390fd5b6106d0600083836108ab565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036107465760006040517fe602df0500000000000000000000000000000000000000000000000000000000815260040161073d9190610e58565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036107b85760006040517f94280d620000000000000000000000000000000000000000000000000000000081526004016107af9190610e58565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080156108a5578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161089c9190610ca0565b60405180910390a35b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036108fd5780600260008282546108f19190610ea2565b925050819055506109d0565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015610989578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161098093929190610e21565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a195780600260008282540392505081905550610a66565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610ac39190610ca0565b60405180910390a3505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610b0a578082015181840152602081019050610aef565b60008484015250505050565b6000601f19601f8301169050919050565b6000610b3282610ad0565b610b3c8185610adb565b9350610b4c818560208601610aec565b610b5581610b16565b840191505092915050565b60006020820190508181036000830152610b7a8184610b27565b905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610bb282610b87565b9050919050565b610bc281610ba7565b8114610bcd57600080fd5b50565b600081359050610bdf81610bb9565b92915050565b6000819050919050565b610bf881610be5565b8114610c0357600080fd5b50565b600081359050610c1581610bef565b92915050565b60008060408385031215610c3257610c31610b82565b5b6000610c4085828601610bd0565b9250506020610c5185828601610c06565b9150509250929050565b60008115159050919050565b610c7081610c5b565b82525050565b6000602082019050610c8b6000830184610c67565b92915050565b610c9a81610be5565b82525050565b6000602082019050610cb56000830184610c91565b92915050565b600080600060608486031215610cd457610cd3610b82565b5b6000610ce286828701610bd0565b9350506020610cf386828701610bd0565b9250506040610d0486828701610c06565b9150509250925092565b600060ff82169050919050565b610d2481610d0e565b82525050565b6000602082019050610d3f6000830184610d1b565b92915050565b600060208284031215610d5b57610d5a610b82565b5b6000610d6984828501610bd0565b91505092915050565b60008060408385031215610d8957610d88610b82565b5b6000610d9785828601610bd0565b9250506020610da885828601610bd0565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610df957607f821691505b602082108103610e0c57610e0b610db2565b5b50919050565b610e1b81610ba7565b82525050565b6000606082019050610e366000830186610e12565b610e436020830185610c91565b610e506040830184610c91565b949350505050565b6000602082019050610e6d6000830184610e12565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610ead82610be5565b9150610eb883610be5565b9250828201905080821115610ed057610ecf610e73565b5b9291505056fea2646970667358221220e3860444d9a2c1a6c52dcf91a6a77c6acbea4df2a988185a99dbb137b2b71eb664736f6c634300081e0033","sourceMap":"129:174:20:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1779:89:1;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3998:186;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2849:97;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4776:244;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2707:82;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;212:89:20;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3004:116:1;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1981:93;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3315:178;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3551:140;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1779:89;1824:13;1856:5;1849:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1779:89;:::o;3998:186::-;4071:4;4087:13;4103:12;:10;:12::i;:::-;4087:28;;4125:31;4134:5;4141:7;4150:5;4125:8;:31::i;:::-;4173:4;4166:11;;;3998:186;;;;:::o;2849:97::-;2901:7;2927:12;;2920:19;;2849:97;:::o;4776:244::-;4863:4;4879:15;4897:12;:10;:12::i;:::-;4879:30;;4919:37;4935:4;4941:7;4950:5;4919:15;:37::i;:::-;4966:26;4976:4;4982:2;4986:5;4966:9;:26::i;:::-;5009:4;5002:11;;;4776:244;;;;;:::o;2707:82::-;2756:5;2780:2;2773:9;;2707:82;:::o;212:89:20:-;275:19;281:3;286:7;275:5;:19::i;:::-;212:89;;:::o;3004:116:1:-;3069:7;3095:9;:18;3105:7;3095:18;;;;;;;;;;;;;;;;3088:25;;3004:116;;;:::o;1981:93::-;2028:13;2060:7;2053:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1981:93;:::o;3315:178::-;3384:4;3400:13;3416:12;:10;:12::i;:::-;3400:28;;3438:27;3448:5;3455:2;3459:5;3438:9;:27::i;:::-;3482:4;3475:11;;;3315:178;;;;:::o;3551:140::-;3631:7;3657:11;:18;3669:5;3657:18;;;;;;;;;;;;;;;:27;3676:7;3657:27;;;;;;;;;;;;;;;;3650:34;;3551:140;;;;:::o;656:96:10:-;709:7;735:10;728:17;;656:96;:::o;8726:128:1:-;8810:37;8819:5;8826:7;8835:5;8842:4;8810:8;:37::i;:::-;8726:128;;;:::o;10415:477::-;10514:24;10541:25;10551:5;10558:7;10541:9;:25::i;:::-;10514:52;;10600:17;10580:16;:37;10576:310;;10656:5;10637:16;:24;10633:130;;;10715:7;10724:16;10742:5;10688:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;10633:130;10804:57;10813:5;10820:7;10848:5;10829:16;:24;10855:5;10804:8;:57::i;:::-;10576:310;10504:388;10415:477;;;:::o;5393:300::-;5492:1;5476:18;;:4;:18;;;5472:86;;5544:1;5517:30;;;;;;;;;;;:::i;:::-;;;;;;;;5472:86;5585:1;5571:16;;:2;:16;;;5567:86;;5639:1;5610:32;;;;;;;;;;;:::i;:::-;;;;;;;;5567:86;5662:24;5670:4;5676:2;5680:5;5662:7;:24::i;:::-;5393:300;;;:::o;7458:208::-;7547:1;7528:21;;:7;:21;;;7524:91;;7601:1;7572:32;;;;;;;;;;;:::i;:::-;;;;;;;;7524:91;7624:35;7640:1;7644:7;7653:5;7624:7;:35::i;:::-;7458:208;;:::o;9701:432::-;9830:1;9813:19;;:5;:19;;;9809:89;;9884:1;9855:32;;;;;;;;;;;:::i;:::-;;;;;;;;9809:89;9930:1;9911:21;;:7;:21;;;9907:90;;9983:1;9955:31;;;;;;;;;;;:::i;:::-;;;;;;;;9907:90;10036:5;10006:11;:18;10018:5;10006:18;;;;;;;;;;;;;;;:27;10025:7;10006:27;;;;;;;;;;;;;;;:35;;;;10055:9;10051:76;;;10101:7;10085:31;;10094:5;10085:31;;;10110:5;10085:31;;;;;;:::i;:::-;;;;;;;;10051:76;9701:432;;;;:::o;6008:1107::-;6113:1;6097:18;;:4;:18;;;6093:540;;6249:5;6233:12;;:21;;;;;;;:::i;:::-;;;;;;;;6093:540;;;6285:19;6307:9;:15;6317:4;6307:15;;;;;;;;;;;;;;;;6285:37;;6354:5;6340:11;:19;6336:115;;;6411:4;6417:11;6430:5;6386:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;6336:115;6603:5;6589:11;:19;6571:9;:15;6581:4;6571:15;;;;;;;;;;;;;;;:37;;;;6271:362;6093:540;6661:1;6647:16;;:2;:16;;;6643:425;;6826:5;6810:12;;:21;;;;;;;;;;;6643:425;;;7038:5;7021:9;:13;7031:2;7021:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;6643:425;7098:2;7083:25;;7092:4;7083:25;;;7102:5;7083:25;;;;;;:::i;:::-;;;;;;;;6008:1107;;;:::o;7:99:42:-;59:6;93:5;87:12;77:22;;7:99;;;:::o;112:169::-;196:11;230:6;225:3;218:19;270:4;265:3;261:14;246:29;;112:169;;;;:::o;287:248::-;369:1;379:113;393:6;390:1;387:13;379:113;;;478:1;473:3;469:11;463:18;459:1;454:3;450:11;443:39;415:2;412:1;408:10;403:15;;379:113;;;526:1;517:6;512:3;508:16;501:27;349:186;287:248;;;:::o;541:102::-;582:6;633:2;629:7;624:2;617:5;613:14;609:28;599:38;;541:102;;;:::o;649:377::-;737:3;765:39;798:5;765:39;:::i;:::-;820:71;884:6;879:3;820:71;:::i;:::-;813:78;;900:65;958:6;953:3;946:4;939:5;935:16;900:65;:::i;:::-;990:29;1012:6;990:29;:::i;:::-;985:3;981:39;974:46;;741:285;649:377;;;;:::o;1032:313::-;1145:4;1183:2;1172:9;1168:18;1160:26;;1232:9;1226:4;1222:20;1218:1;1207:9;1203:17;1196:47;1260:78;1333:4;1324:6;1260:78;:::i;:::-;1252:86;;1032:313;;;;:::o;1432:117::-;1541:1;1538;1531:12;1678:126;1715:7;1755:42;1748:5;1744:54;1733:65;;1678:126;;;:::o;1810:96::-;1847:7;1876:24;1894:5;1876:24;:::i;:::-;1865:35;;1810:96;;;:::o;1912:122::-;1985:24;2003:5;1985:24;:::i;:::-;1978:5;1975:35;1965:63;;2024:1;2021;2014:12;1965:63;1912:122;:::o;2040:139::-;2086:5;2124:6;2111:20;2102:29;;2140:33;2167:5;2140:33;:::i;:::-;2040:139;;;;:::o;2185:77::-;2222:7;2251:5;2240:16;;2185:77;;;:::o;2268:122::-;2341:24;2359:5;2341:24;:::i;:::-;2334:5;2331:35;2321:63;;2380:1;2377;2370:12;2321:63;2268:122;:::o;2396:139::-;2442:5;2480:6;2467:20;2458:29;;2496:33;2523:5;2496:33;:::i;:::-;2396:139;;;;:::o;2541:474::-;2609:6;2617;2666:2;2654:9;2645:7;2641:23;2637:32;2634:119;;;2672:79;;:::i;:::-;2634:119;2792:1;2817:53;2862:7;2853:6;2842:9;2838:22;2817:53;:::i;:::-;2807:63;;2763:117;2919:2;2945:53;2990:7;2981:6;2970:9;2966:22;2945:53;:::i;:::-;2935:63;;2890:118;2541:474;;;;;:::o;3021:90::-;3055:7;3098:5;3091:13;3084:21;3073:32;;3021:90;;;:::o;3117:109::-;3198:21;3213:5;3198:21;:::i;:::-;3193:3;3186:34;3117:109;;:::o;3232:210::-;3319:4;3357:2;3346:9;3342:18;3334:26;;3370:65;3432:1;3421:9;3417:17;3408:6;3370:65;:::i;:::-;3232:210;;;;:::o;3448:118::-;3535:24;3553:5;3535:24;:::i;:::-;3530:3;3523:37;3448:118;;:::o;3572:222::-;3665:4;3703:2;3692:9;3688:18;3680:26;;3716:71;3784:1;3773:9;3769:17;3760:6;3716:71;:::i;:::-;3572:222;;;;:::o;3800:619::-;3877:6;3885;3893;3942:2;3930:9;3921:7;3917:23;3913:32;3910:119;;;3948:79;;:::i;:::-;3910:119;4068:1;4093:53;4138:7;4129:6;4118:9;4114:22;4093:53;:::i;:::-;4083:63;;4039:117;4195:2;4221:53;4266:7;4257:6;4246:9;4242:22;4221:53;:::i;:::-;4211:63;;4166:118;4323:2;4349:53;4394:7;4385:6;4374:9;4370:22;4349:53;:::i;:::-;4339:63;;4294:118;3800:619;;;;;:::o;4425:86::-;4460:7;4500:4;4493:5;4489:16;4478:27;;4425:86;;;:::o;4517:112::-;4600:22;4616:5;4600:22;:::i;:::-;4595:3;4588:35;4517:112;;:::o;4635:214::-;4724:4;4762:2;4751:9;4747:18;4739:26;;4775:67;4839:1;4828:9;4824:17;4815:6;4775:67;:::i;:::-;4635:214;;;;:::o;4855:329::-;4914:6;4963:2;4951:9;4942:7;4938:23;4934:32;4931:119;;;4969:79;;:::i;:::-;4931:119;5089:1;5114:53;5159:7;5150:6;5139:9;5135:22;5114:53;:::i;:::-;5104:63;;5060:117;4855:329;;;;:::o;5190:474::-;5258:6;5266;5315:2;5303:9;5294:7;5290:23;5286:32;5283:119;;;5321:79;;:::i;:::-;5283:119;5441:1;5466:53;5511:7;5502:6;5491:9;5487:22;5466:53;:::i;:::-;5456:63;;5412:117;5568:2;5594:53;5639:7;5630:6;5619:9;5615:22;5594:53;:::i;:::-;5584:63;;5539:118;5190:474;;;;;:::o;5670:180::-;5718:77;5715:1;5708:88;5815:4;5812:1;5805:15;5839:4;5836:1;5829:15;5856:320;5900:6;5937:1;5931:4;5927:12;5917:22;;5984:1;5978:4;5974:12;6005:18;5995:81;;6061:4;6053:6;6049:17;6039:27;;5995:81;6123:2;6115:6;6112:14;6092:18;6089:38;6086:84;;6142:18;;:::i;:::-;6086:84;5907:269;5856:320;;;:::o;6182:118::-;6269:24;6287:5;6269:24;:::i;:::-;6264:3;6257:37;6182:118;;:::o;6306:442::-;6455:4;6493:2;6482:9;6478:18;6470:26;;6506:71;6574:1;6563:9;6559:17;6550:6;6506:71;:::i;:::-;6587:72;6655:2;6644:9;6640:18;6631:6;6587:72;:::i;:::-;6669;6737:2;6726:9;6722:18;6713:6;6669:72;:::i;:::-;6306:442;;;;;;:::o;6754:222::-;6847:4;6885:2;6874:9;6870:18;6862:26;;6898:71;6966:1;6955:9;6951:17;6942:6;6898:71;:::i;:::-;6754:222;;;;:::o;6982:180::-;7030:77;7027:1;7020:88;7127:4;7124:1;7117:15;7151:4;7148:1;7141:15;7168:191;7208:3;7227:20;7245:1;7227:20;:::i;:::-;7222:25;;7261:20;7279:1;7261:20;:::i;:::-;7256:25;;7304:1;7301;7297:9;7290:16;;7325:3;7322:1;7319:10;7316:36;;;7332:18;;:::i;:::-;7316:36;7168:191;;;;:::o","linkReferences":{}},"methodIdentifiers":{"allowance(address,address)":"dd62ed3e","approve(address,uint256)":"095ea7b3","balanceOf(address)":"70a08231","decimals()":"313ce567","mint(address,uint256)":"40c10f19","name()":"06fdde03","symbol()":"95d89b41","totalSupply()":"18160ddd","transfer(address,uint256)":"a9059cbb","transferFrom(address,address,uint256)":"23b872dd"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.30+commit.73712a01\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"allowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSpender\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ERC20InsufficientAllowance(address,uint256,uint256)\":[{\"details\":\"Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\",\"params\":{\"allowance\":\"Amount of tokens a `spender` is allowed to operate with.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"spender\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC20InsufficientBalance(address,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC20InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC20InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC20InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC20InvalidSpender(address)\":[{\"details\":\"Indicates a failure with the `spender` to be approved. Used in approvals.\",\"params\":{\"spender\":\"Address that may be allowed to operate on tokens without being their owner.\"}}]},\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `value` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `value`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `value`. - the caller must have allowance for ``from``'s tokens of at least `value`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"../../../../node_modules/@effectstream/evm-contracts/src/contracts/dev/Erc20Dev.sol\":\"Erc20Dev\"},\"evmVersion\":\"berlin\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin/=../../../../node_modules/@openzeppelin/\",\":@paima/=../../../../node_modules/@paima/\"]},\"sources\":{\"../../../../node_modules/@openzeppelin/contracts/interfaces/draft-IERC6093.sol\":{\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://399594cd8bb0143bc9e55e0f1d071d0d8c850a394fb7a319d50edd55d9ed822b\",\"dweb:/ipfs/QmbPZzgtT6LEm9CMqWfagQFwETbV1ztpECBB1DtQHrKiRz\"]},\"../../../../node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0xbf61ab2ae1d575a17ea58fbb99ca232baddcc4e0eeea180e84cbc74b0c348b31\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4e0968705bad99747a8e5288aa008678c2be2f471f919dce3925a3cc4f1dee09\",\"dweb:/ipfs/QmbAFnCQfo4tw6ssfQSjhA5LzwHWNNryXN8bX7ty8jiqqn\"]},\"../../../../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db\",\"dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9\"]},\"../../../../node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x70f2f713b13b7ce4610bcd0ac9fec0f3cc43693b043abcb8dc40a42a726eb330\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c13d13304ac79a83ab1c30168967d19e2203342ebbd6a9bbce4db7550522dcbf\",\"dweb:/ipfs/QmeN5jKMN2vw5bhacr6tkg78afbTTZUeaacNHqjWt4Ew1r\"]},\"../../../../node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"../../../../node_modules/@effectstream/evm-contracts/src/contracts/dev/Erc20Dev.sol\":{\"keccak256\":\"0x7c86fae8a8e8eec49420ab76d80b13bfc5a129284d0823c7123b067b25230ce7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://849efeb9238b45be38d71554c9bda0a2e8869f2b24e77230d0a989ff4a9481ae\",\"dweb:/ipfs/QmRoDNSnN54odRQ47SK4GZ32DgkUyCzDAZw2kNP5RCrfAX\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.30+commit.73712a01"},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"type":"error","name":"ERC20InsufficientAllowance"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"type":"error","name":"ERC20InsufficientBalance"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"type":"error","name":"ERC20InvalidApprover"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"type":"error","name":"ERC20InvalidReceiver"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"type":"error","name":"ERC20InvalidSender"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"type":"error","name":"ERC20InvalidSpender"},{"inputs":[{"internalType":"address","name":"owner","type":"address","indexed":true},{"internalType":"address","name":"spender","type":"address","indexed":true},{"internalType":"uint256","name":"value","type":"uint256","indexed":false}],"type":"event","name":"Approval","anonymous":false},{"inputs":[{"internalType":"address","name":"from","type":"address","indexed":true},{"internalType":"address","name":"to","type":"address","indexed":true},{"internalType":"uint256","name":"value","type":"uint256","indexed":false}],"type":"event","name":"Transfer","anonymous":false},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"stateMutability":"view","type":"function","name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function","name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"mint"},{"inputs":[],"stateMutability":"view","type":"function","name":"name","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]}],"devdoc":{"kind":"dev","methods":{"allowance(address,address)":{"details":"See {IERC20-allowance}."},"approve(address,uint256)":{"details":"See {IERC20-approve}. NOTE: If `value` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address."},"balanceOf(address)":{"details":"See {IERC20-balanceOf}."},"decimals()":{"details":"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}."},"name()":{"details":"Returns the name of the token."},"symbol()":{"details":"Returns the symbol of the token, usually a shorter version of the name."},"totalSupply()":{"details":"See {IERC20-totalSupply}."},"transfer(address,uint256)":{"details":"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `value`."},"transferFrom(address,address,uint256)":{"details":"See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `value`. - the caller must have allowance for ``from``'s tokens of at least `value`."}},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin/=../../../../node_modules/@openzeppelin/","@paima/=../../../../node_modules/@paima/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"../../../../node_modules/@effectstream/evm-contracts/src/contracts/dev/Erc20Dev.sol":"Erc20Dev"},"evmVersion":"berlin","libraries":{}},"sources":{"../../../../node_modules/@openzeppelin/contracts/interfaces/draft-IERC6093.sol":{"keccak256":"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b","urls":["bzz-raw://399594cd8bb0143bc9e55e0f1d071d0d8c850a394fb7a319d50edd55d9ed822b","dweb:/ipfs/QmbPZzgtT6LEm9CMqWfagQFwETbV1ztpECBB1DtQHrKiRz"],"license":"MIT"},"../../../../node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol":{"keccak256":"0xbf61ab2ae1d575a17ea58fbb99ca232baddcc4e0eeea180e84cbc74b0c348b31","urls":["bzz-raw://4e0968705bad99747a8e5288aa008678c2be2f471f919dce3925a3cc4f1dee09","dweb:/ipfs/QmbAFnCQfo4tw6ssfQSjhA5LzwHWNNryXN8bX7ty8jiqqn"],"license":"MIT"},"../../../../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol":{"keccak256":"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7","urls":["bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db","dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9"],"license":"MIT"},"../../../../node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol":{"keccak256":"0x70f2f713b13b7ce4610bcd0ac9fec0f3cc43693b043abcb8dc40a42a726eb330","urls":["bzz-raw://c13d13304ac79a83ab1c30168967d19e2203342ebbd6a9bbce4db7550522dcbf","dweb:/ipfs/QmeN5jKMN2vw5bhacr6tkg78afbTTZUeaacNHqjWt4Ew1r"],"license":"MIT"},"../../../../node_modules/@openzeppelin/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"../../../../node_modules/@effectstream/evm-contracts/src/contracts/dev/Erc20Dev.sol":{"keccak256":"0x7c86fae8a8e8eec49420ab76d80b13bfc5a129284d0823c7123b067b25230ce7","urls":["bzz-raw://849efeb9238b45be38d71554c9bda0a2e8869f2b24e77230d0a989ff4a9481ae","dweb:/ipfs/QmRoDNSnN54odRQ47SK4GZ32DgkUyCzDAZw2kNP5RCrfAX"],"license":"MIT"}},"version":1},"id":20} as const;
@@ -0,0 +1,7 @@
1
+ import { Type } from "@sinclair/typebox";
2
+
3
+ export const erc20Grammar = [
4
+ ['to', Type.String()],
5
+ ['from', Type.String()],
6
+ ['value', Type.String()],
7
+ ] as const;
@@ -0,0 +1,93 @@
1
+ // TODO This can be replaced by a function that does the insertions.
2
+ // This will allow to create new tables during migrations.
3
+
4
+ import { PrimitiveTypeEVMERC20 } from "../builtin.ts";
5
+
6
+ // TODO The IVM here is not relevant, as the trigger does the work.
7
+
8
+ /**
9
+ * Creates a new IVM for the ERC20 token with the given name.
10
+ * This will track the current balance of each address.
11
+ * @param name - The name of the ERC20 token.
12
+ * @returns A string containing the SQL script to create the IVM.
13
+ */
14
+ export function erc20Ivm(name: string) {
15
+ const lowerName = name.toLowerCase();
16
+ const validSQLName = lowerName.replace(/[^a-zA-Z0-9_]/g, "");
17
+ if (validSQLName !== lowerName) {
18
+ throw new Error(`Invalid name: ${name}`);
19
+ }
20
+
21
+ const balanceTable = `primitives.erc20_balances_intermediate_${validSQLName}`;
22
+
23
+ return `
24
+ -- Intermediate table for current ERC20 balances (maintained by triggers)
25
+ CREATE TABLE IF NOT EXISTS ${balanceTable} (
26
+ primitive_name TEXT NOT NULL,
27
+ address TEXT NOT NULL,
28
+ balance numeric(78,0) DEFAULT 0,
29
+ PRIMARY KEY (primitive_name, address)
30
+ );
31
+
32
+ -- Trigger function to maintain ERC20 balances
33
+ CREATE OR REPLACE FUNCTION update_erc20_balances_${validSQLName}() RETURNS TRIGGER AS $$
34
+ DECLARE
35
+ transfer_value numeric(78,0);
36
+ from_address TEXT;
37
+ to_address TEXT;
38
+ BEGIN
39
+ -- Only process ERC20 transfers
40
+ IF NEW.payload_type = '${PrimitiveTypeEVMERC20}'
41
+ AND NEW.primitive_name = '${name}'
42
+ AND NEW.payload->>'value' IS NOT NULL THEN
43
+
44
+ transfer_value := (NEW.payload->>'value')::numeric(78,0);
45
+ from_address := lower(NEW.payload->>'from');
46
+ to_address := lower(NEW.payload->>'to');
47
+
48
+ -- Handle FROM address (subtract balance, but skip burn address)
49
+ IF from_address IS NOT NULL
50
+ AND from_address != ''
51
+ AND from_address != '0x0000000000000000000000000000000000000000' THEN
52
+
53
+ INSERT INTO ${balanceTable} (primitive_name, address, balance)
54
+ VALUES (NEW.primitive_name, from_address, -transfer_value)
55
+ ON CONFLICT (primitive_name, address) DO UPDATE SET
56
+ balance = ${balanceTable}.balance - transfer_value;
57
+ END IF;
58
+
59
+ -- Handle TO address (add balance)
60
+ IF to_address IS NOT NULL AND to_address != '' THEN
61
+ INSERT INTO ${balanceTable} (primitive_name, address, balance)
62
+ VALUES (NEW.primitive_name, to_address, transfer_value)
63
+ ON CONFLICT (primitive_name, address) DO UPDATE SET
64
+ balance = ${balanceTable}.balance + transfer_value;
65
+ END IF;
66
+ END IF;
67
+
68
+ RETURN NEW;
69
+ END;
70
+ $$ LANGUAGE plpgsql;
71
+
72
+ -- Create trigger on primitive_accounting for ERC20 balances
73
+ CREATE TRIGGER trigger_update_erc20_balances_${validSQLName}
74
+ AFTER INSERT ON effectstream.primitive_accounting -- Note: Qualify with paima schema
75
+ FOR EACH ROW
76
+ EXECUTE FUNCTION update_erc20_balances_${validSQLName}();
77
+
78
+ -- Simple incrementally maintained view on the intermediate table
79
+ SELECT pgivm.create_immv('primitives.erc20_balances_view_${validSQLName}',
80
+ 'SELECT
81
+ primitive_name,
82
+ address,
83
+ balance
84
+ FROM ${balanceTable}
85
+ WHERE balance > 0;
86
+ ');
87
+ `;
88
+ }
89
+
90
+ // Naming helpers kept in this file to co-locate schema naming with IVM DDL
91
+ export const ERC20_VIEW_PREFIX = "erc20_balances_view_" as const;
92
+ export const ERC20_INTERMEDIATE_PREFIX =
93
+ "erc20_balances_intermediate_" as const;