From da8603fa03bd3ea86a012591d9e57b976a851882 Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Fri, 31 May 2024 19:56:10 +0300 Subject: [PATCH 01/14] update: move responses conversion to models package --- internal/service/api/models/aidrop.go | 42 +++++++++++++++++++++++++ internal/service/api/models/transfer.go | 37 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 internal/service/api/models/aidrop.go create mode 100644 internal/service/api/models/transfer.go diff --git a/internal/service/api/models/aidrop.go b/internal/service/api/models/aidrop.go new file mode 100644 index 0000000..be661cf --- /dev/null +++ b/internal/service/api/models/aidrop.go @@ -0,0 +1,42 @@ +package models + +import ( + "github.com/rarimo/evm-airdrop-svc/internal/config" + "github.com/rarimo/evm-airdrop-svc/internal/data" + "github.com/rarimo/evm-airdrop-svc/resources" +) + +func NewAirdropResponse(tx data.Airdrop) resources.AirdropResponse { + return resources.AirdropResponse{ + Data: resources.Airdrop{ + Key: resources.Key{ + ID: tx.ID, + Type: resources.AIRDROP, + }, + Attributes: resources.AirdropAttributes{ + Nullifier: tx.Nullifier, + Address: tx.Address, + TxHash: tx.TxHash, + Amount: tx.Amount, + Status: tx.Status, + CreatedAt: tx.CreatedAt, + UpdatedAt: tx.UpdatedAt, + }, + }, + } +} + +func NewAirdropParams(params config.GlobalParams) resources.AirdropParamsResponse { + return resources.AirdropParamsResponse{ + Data: resources.AirdropParams{ + Key: resources.Key{ + Type: resources.AIRDROP, + }, + Attributes: resources.AirdropParamsAttributes{ + EventId: params.EventID, + StartedAt: params.AirdropStart, + QuerySelector: params.QuerySelector, + }, + }, + } +} diff --git a/internal/service/api/models/transfer.go b/internal/service/api/models/transfer.go new file mode 100644 index 0000000..2214dc3 --- /dev/null +++ b/internal/service/api/models/transfer.go @@ -0,0 +1,37 @@ +package models + +import ( + "math/big" + + "github.com/rarimo/evm-airdrop-svc/resources" +) + +func NewEstimateResponse(amount, fee *big.Int) resources.EstimateResponse { + return resources.EstimateResponse{ + Data: resources.Estimate{ + Key: resources.Key{ + Type: resources.TRANSFER_ERC20, + }, + Attributes: resources.EstimateAttributes{ + Amount: amount.Int64(), + Fee: fee.Int64(), + }, + }, + } +} + +func NewTxResponse(amount, fee *big.Int, hash string) resources.TxResponse { + return resources.TxResponse{ + Data: resources.Tx{ + Key: resources.Key{ + ID: hash, + Type: resources.TRANSFER_ERC20, + }, + Attributes: resources.TxAttributes{ + Amount: amount.Int64(), + Fee: fee.Int64(), + Hash: hash, + }, + }, + } +} From c9bf130890cda943db5ba6e3ecb71570b705c40c Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Fri, 31 May 2024 19:57:03 +0300 Subject: [PATCH 02/14] add: docs for estimate and transfer requests --- docs/spec/components/schemas/Estimate.yaml | 22 ++++++ .../schemas/TransferERC20Token.yaml | 51 +++++++++++++ docs/spec/components/schemas/TransferKey.yaml | 7 ++ docs/spec/components/schemas/Tx.yaml | 27 +++++++ ...ntegrations@evm-airdrop-svc@airdrops.yaml} | 0 ...ions@evm-airdrop-svc@airdrops@params.yaml} | 0 ...evm-airdrop-svc@airdrops@{nullifier}.yaml} | 0 ...integrations@evm-airdrop-svc@transfer.yaml | 71 +++++++++++++++++++ resources/model_estimate.go | 43 +++++++++++ resources/model_estimate_attributes.go | 12 ++++ resources/model_transfer_erc20_token.go | 43 +++++++++++ .../model_transfer_erc20_token_attributes.go | 28 ++++++++ resources/model_tx.go | 43 +++++++++++ resources/model_tx_attributes.go | 14 ++++ 14 files changed, 361 insertions(+) create mode 100644 docs/spec/components/schemas/Estimate.yaml create mode 100644 docs/spec/components/schemas/TransferERC20Token.yaml create mode 100644 docs/spec/components/schemas/TransferKey.yaml create mode 100644 docs/spec/components/schemas/Tx.yaml rename docs/spec/paths/{integrations@airdrop-svc@airdrops.yaml => integrations@evm-airdrop-svc@airdrops.yaml} (100%) rename docs/spec/paths/{integrations@airdrop-svc@airdrops@params.yaml => integrations@evm-airdrop-svc@airdrops@params.yaml} (100%) rename docs/spec/paths/{integrations@airdrop-svc@airdrops@{nullifier}.yaml => integrations@evm-airdrop-svc@airdrops@{nullifier}.yaml} (100%) create mode 100644 docs/spec/paths/integrations@evm-airdrop-svc@transfer.yaml create mode 100644 resources/model_estimate.go create mode 100644 resources/model_estimate_attributes.go create mode 100644 resources/model_transfer_erc20_token.go create mode 100644 resources/model_transfer_erc20_token_attributes.go create mode 100644 resources/model_tx.go create mode 100644 resources/model_tx_attributes.go diff --git a/docs/spec/components/schemas/Estimate.yaml b/docs/spec/components/schemas/Estimate.yaml new file mode 100644 index 0000000..bc9f3ff --- /dev/null +++ b/docs/spec/components/schemas/Estimate.yaml @@ -0,0 +1,22 @@ +allOf: + - $ref: '#/components/schemas/TransferKey' + - type: object + required: + - attributes + properties: + attributes: + type: object + required: + - amount + - fee + properties: + amount: + type: integer + format: int64 + description: Amount of tokens that will be transferred to the destination. + example: 6 + fee: + type: integer + format: int64 + description: Amount of tokens that will be drawn ass fee expenses. + example: 2 diff --git a/docs/spec/components/schemas/TransferERC20Token.yaml b/docs/spec/components/schemas/TransferERC20Token.yaml new file mode 100644 index 0000000..dad6411 --- /dev/null +++ b/docs/spec/components/schemas/TransferERC20Token.yaml @@ -0,0 +1,51 @@ +allOf: + - $ref: '#/components/schemas/TransferKey' + - type: object + x-go-is-request: true + required: + - attributes + properties: + attributes: + type: object + required: + - sender + - receiver + - amount + - deadline + - r + - v + - s + properties: + sender: + type: string + format: common.Address + description: EVM address FROM which tokens are transferred. + example: "0x9E65b5Fac5aD50B7daf51a0F8D8234Cd5658ef17" + receiver: + type: string + format: common.Address + description: EVM address TO which tokens are transferred. + example: "0xBF8080a3FE79bf5e13F28BB743AEC11442365dB0" + amount: + type: integer + format: "*big.Int" + description: Transferred amount of tokens. + example: 8 + deadline: + type: integer + format: "*big.Int" + description: UNIX UTC timestamp in the future till which permit signature may be used. + example: 1717015161 + r: + type: string + description: Hex encoded permit the x coordinate of R value of the signature. + example: "0xaec2aac837bbe808ab9b2b994e6c0bf93ce751d0cef7f4c882f9c0125eb0809c" + s: + type: string + description: Hex encoded permit the x coordinate of S value of the signature. + example: "0x5548ffb8ba6a610ec2f02d75a8ec80c428ed2e07a9bdfd5716af24adb4c2c58f" + v: + type: integer + format: uint8 + description: The parity of the y coordinate of R. + example: 28 diff --git a/docs/spec/components/schemas/TransferKey.yaml b/docs/spec/components/schemas/TransferKey.yaml new file mode 100644 index 0000000..f45cbe6 --- /dev/null +++ b/docs/spec/components/schemas/TransferKey.yaml @@ -0,0 +1,7 @@ +type: object +required: + - type +properties: + type: + type: string + enum: [ transfer_erc20 ] diff --git a/docs/spec/components/schemas/Tx.yaml b/docs/spec/components/schemas/Tx.yaml new file mode 100644 index 0000000..a24bb73 --- /dev/null +++ b/docs/spec/components/schemas/Tx.yaml @@ -0,0 +1,27 @@ +allOf: + - $ref: '#/components/schemas/TransferKey' + - type: object + required: + - attributes + properties: + attributes: + type: object + required: + - hash + - amount + - fee + properties: + hash: + type: string + description: Transfer transaction hash. + example: "0x1b06e10120aab3caee20ca69498de8a52eb977b39fa9811dea9592ea3b3d2985" + amount: + type: integer + format: int64 + description: Amount of tokens that was transferred to the destination. + example: 6 + fee: + type: integer + format: int64 + description: Amount of tokens that was drawn ass fee expenses. + example: 2 diff --git a/docs/spec/paths/integrations@airdrop-svc@airdrops.yaml b/docs/spec/paths/integrations@evm-airdrop-svc@airdrops.yaml similarity index 100% rename from docs/spec/paths/integrations@airdrop-svc@airdrops.yaml rename to docs/spec/paths/integrations@evm-airdrop-svc@airdrops.yaml diff --git a/docs/spec/paths/integrations@airdrop-svc@airdrops@params.yaml b/docs/spec/paths/integrations@evm-airdrop-svc@airdrops@params.yaml similarity index 100% rename from docs/spec/paths/integrations@airdrop-svc@airdrops@params.yaml rename to docs/spec/paths/integrations@evm-airdrop-svc@airdrops@params.yaml diff --git a/docs/spec/paths/integrations@airdrop-svc@airdrops@{nullifier}.yaml b/docs/spec/paths/integrations@evm-airdrop-svc@airdrops@{nullifier}.yaml similarity index 100% rename from docs/spec/paths/integrations@airdrop-svc@airdrops@{nullifier}.yaml rename to docs/spec/paths/integrations@evm-airdrop-svc@airdrops@{nullifier}.yaml diff --git a/docs/spec/paths/integrations@evm-airdrop-svc@transfer.yaml b/docs/spec/paths/integrations@evm-airdrop-svc@transfer.yaml new file mode 100644 index 0000000..8805129 --- /dev/null +++ b/docs/spec/paths/integrations@evm-airdrop-svc@transfer.yaml @@ -0,0 +1,71 @@ +post: + tags: + - Transfer + summary: Send ERC20 transfer + description: "Creates and sends multicall transaction with transfer. Service takes signature from requester creates + transaction and sends it in the network. This call consists of:\n + - Permit - allows service sender to transfer from requester account \n + - Transfer #1 - sends tokens to the desired address\n + - Transfer #2 - sends part from tokens to the sender address to cover fees expenses. Transaction is created, but + not awaited.\n" + operationId: SendTransfer + requestBody: + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/TransferERC20Token' + responses: + 201: + description: Transfer was created, transaction was sent + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Tx' + 400: + $ref: '#/components/responses/invalidParameter' + 500: + $ref: '#/components/responses/internalError' + +get: + tags: + - Transfer + summary: Get transfer params + description: "Returns ERC20 transfer with multicall parameters. Takes all requried parameters for permit and transfer, + simulates transaction and returns the calculated values" + operationId: GetTransferParams + requestBody: + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/TransferERC20Token' + responses: + 200: + description: Transaction was done successfully, all parameters were calculated. + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Estimate' + 400: + $ref: '#/components/responses/invalidParameter' + 500: + $ref: '#/components/responses/internalError' diff --git a/resources/model_estimate.go b/resources/model_estimate.go new file mode 100644 index 0000000..d1d6446 --- /dev/null +++ b/resources/model_estimate.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type Estimate struct { + Key + Attributes EstimateAttributes `json:"attributes"` +} +type EstimateResponse struct { + Data Estimate `json:"data"` + Included Included `json:"included"` +} + +type EstimateListResponse struct { + Data []Estimate `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *EstimateListResponse) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *EstimateListResponse) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustEstimate - returns Estimate from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustEstimate(key Key) *Estimate { + var estimate Estimate + if c.tryFindEntry(key, &estimate) { + return &estimate + } + return nil +} diff --git a/resources/model_estimate_attributes.go b/resources/model_estimate_attributes.go new file mode 100644 index 0000000..a52ff77 --- /dev/null +++ b/resources/model_estimate_attributes.go @@ -0,0 +1,12 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type EstimateAttributes struct { + // Amount of tokens that will be transferred to the destination. + Amount int64 `json:"amount"` + // Amount of tokens that will be drawn ass fee expenses. + Fee int64 `json:"fee"` +} diff --git a/resources/model_transfer_erc20_token.go b/resources/model_transfer_erc20_token.go new file mode 100644 index 0000000..cef9b03 --- /dev/null +++ b/resources/model_transfer_erc20_token.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type TransferErc20Token struct { + Key + Attributes TransferErc20TokenAttributes `json:"attributes"` +} +type TransferErc20TokenRequest struct { + Data TransferErc20Token `json:"data"` + Included Included `json:"included"` +} + +type TransferErc20TokenListRequest struct { + Data []TransferErc20Token `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *TransferErc20TokenListRequest) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *TransferErc20TokenListRequest) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustTransferErc20Token - returns TransferErc20Token from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustTransferErc20Token(key Key) *TransferErc20Token { + var transferERC20Token TransferErc20Token + if c.tryFindEntry(key, &transferERC20Token) { + return &transferERC20Token + } + return nil +} diff --git a/resources/model_transfer_erc20_token_attributes.go b/resources/model_transfer_erc20_token_attributes.go new file mode 100644 index 0000000..628108d --- /dev/null +++ b/resources/model_transfer_erc20_token_attributes.go @@ -0,0 +1,28 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +type TransferErc20TokenAttributes struct { + // Transferred amount of tokens. + Amount *big.Int `json:"amount"` + // UNIX UTC timestamp in the future till which permit signature may be used. + Deadline *big.Int `json:"deadline"` + // Hex encoded permit the x coordinate of R value of the signature. + R string `json:"r"` + // EVM address TO which tokens are transferred. + Receiver common.Address `json:"receiver"` + // Hex encoded permit the x coordinate of S value of the signature. + S string `json:"s"` + // EVM address FROM which tokens are transferred. + Sender common.Address `json:"sender"` + // The parity of the y coordinate of R. + V uint8 `json:"v"` +} diff --git a/resources/model_tx.go b/resources/model_tx.go new file mode 100644 index 0000000..b6bbc0f --- /dev/null +++ b/resources/model_tx.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type Tx struct { + Key + Attributes TxAttributes `json:"attributes"` +} +type TxResponse struct { + Data Tx `json:"data"` + Included Included `json:"included"` +} + +type TxListResponse struct { + Data []Tx `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *TxListResponse) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *TxListResponse) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustTx - returns Tx from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustTx(key Key) *Tx { + var tx Tx + if c.tryFindEntry(key, &tx) { + return &tx + } + return nil +} diff --git a/resources/model_tx_attributes.go b/resources/model_tx_attributes.go new file mode 100644 index 0000000..6d91a65 --- /dev/null +++ b/resources/model_tx_attributes.go @@ -0,0 +1,14 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type TxAttributes struct { + // Amount of tokens that was transferred to the destination. + Amount int64 `json:"amount"` + // Amount of tokens that was drawn ass fee expenses. + Fee int64 `json:"fee"` + // Transfer transaction hash. + Hash string `json:"hash"` +} From ebd6741b8f894f2e215a4a3749f1c2d255e9defe Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Fri, 31 May 2024 19:57:34 +0300 Subject: [PATCH 03/14] add: ERC20Permit and ERC20PermitTransfer contracts --- contracts/abi/erc20_permit.abi | 1 + contracts/abi/erc20_permit_transfer.abi | 140 + contracts/erc20_permit.go | 3576 +++++++++++++++++++++++ contracts/erc20_transfer_permit.go | 428 +++ 4 files changed, 4145 insertions(+) create mode 100644 contracts/abi/erc20_permit.abi create mode 100644 contracts/abi/erc20_permit_transfer.abi create mode 100644 contracts/erc20_permit.go create mode 100644 contracts/erc20_transfer_permit.go diff --git a/contracts/abi/erc20_permit.abi b/contracts/abi/erc20_permit.abi new file mode 100644 index 0000000..93162ca --- /dev/null +++ b/contracts/abi/erc20_permit.abi @@ -0,0 +1 @@ +[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"denylistee","type":"address"}],"name":"IsDenylisted","type":"error"},{"inputs":[{"internalType":"address","name":"denylistee","type":"address"}],"name":"IsNotDenylisted","type":"error"},{"inputs":[{"internalType":"uint256","name":"supply","type":"uint256"}],"name":"IsOverSupplyCap","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"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":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"burner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"denylister","type":"address"},{"indexed":true,"internalType":"address","name":"denylistee","type":"address"}],"name":"Denylist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"denylister","type":"address"},{"indexed":true,"internalType":"address","name":"denylistee","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DestroyDenylistedFunds","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"denylister","type":"address"},{"indexed":true,"internalType":"address","name":"denylistee","type":"address"}],"name":"Undenylist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DENYLISTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"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":"amount","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":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"denylistee","type":"address"}],"name":"denylist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"denylistee","type":"address"}],"name":"destroyDenylistedFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializeV3","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"denylistee","type":"address"}],"name":"isDenylisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"amount","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":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"denylistee","type":"address"}],"name":"undenylist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}] \ No newline at end of file diff --git a/contracts/abi/erc20_permit_transfer.abi b/contracts/abi/erc20_permit_transfer.abi new file mode 100644 index 0000000..d732030 --- /dev/null +++ b/contracts/abi/erc20_permit_transfer.abi @@ -0,0 +1,140 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + }, + { + "internalType": "address", + "name": "owner_", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeAmount_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline_", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v_", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r_", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s_", + "type": "bytes32" + } + ], + "name": "transferWithPermit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/contracts/erc20_permit.go b/contracts/erc20_permit.go new file mode 100644 index 0000000..8abe103 --- /dev/null +++ b/contracts/erc20_permit.go @@ -0,0 +1,3576 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contracts + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// ERC20PermitMetaData contains all meta data concerning the ERC20Permit contract. +var ERC20PermitMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"denylistee\",\"type\":\"address\"}],\"name\":\"IsDenylisted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"denylistee\",\"type\":\"address\"}],\"name\":\"IsNotDenylisted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"}],\"name\":\"IsOverSupplyCap\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"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\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"burner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"denylister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"denylistee\",\"type\":\"address\"}],\"name\":\"Denylist\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"denylister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"denylistee\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DestroyDenylistedFunds\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"denylister\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"denylistee\",\"type\":\"address\"}],\"name\":\"Undenylist\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DENYLISTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PAUSER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPGRADER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\":\"amount\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"denylistee\",\"type\":\"address\"}],\"name\":\"denylist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"denylistee\",\"type\":\"address\"}],\"name\":\"destroyDenylistedFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initializeV3\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"denylistee\",\"type\":\"address\"}],\"name\":\"isDenylisted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"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\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"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\":\"amount\",\"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\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"denylistee\",\"type\":\"address\"}],\"name\":\"undenylist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", +} + +// ERC20PermitABI is the input ABI used to generate the binding from. +// Deprecated: Use ERC20PermitMetaData.ABI instead. +var ERC20PermitABI = ERC20PermitMetaData.ABI + +// ERC20Permit is an auto generated Go binding around an Ethereum contract. +type ERC20Permit struct { + ERC20PermitCaller // Read-only binding to the contract + ERC20PermitTransactor // Write-only binding to the contract + ERC20PermitFilterer // Log filterer for contract events +} + +// ERC20PermitCaller is an auto generated read-only Go binding around an Ethereum contract. +type ERC20PermitCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20PermitTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ERC20PermitTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20PermitFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ERC20PermitFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20PermitSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ERC20PermitSession struct { + Contract *ERC20Permit // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ERC20PermitCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ERC20PermitCallerSession struct { + Contract *ERC20PermitCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ERC20PermitTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ERC20PermitTransactorSession struct { + Contract *ERC20PermitTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ERC20PermitRaw is an auto generated low-level Go binding around an Ethereum contract. +type ERC20PermitRaw struct { + Contract *ERC20Permit // Generic contract binding to access the raw methods on +} + +// ERC20PermitCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ERC20PermitCallerRaw struct { + Contract *ERC20PermitCaller // Generic read-only contract binding to access the raw methods on +} + +// ERC20PermitTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ERC20PermitTransactorRaw struct { + Contract *ERC20PermitTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewERC20Permit creates a new instance of ERC20Permit, bound to a specific deployed contract. +func NewERC20Permit(address common.Address, backend bind.ContractBackend) (*ERC20Permit, error) { + contract, err := bindERC20Permit(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ERC20Permit{ERC20PermitCaller: ERC20PermitCaller{contract: contract}, ERC20PermitTransactor: ERC20PermitTransactor{contract: contract}, ERC20PermitFilterer: ERC20PermitFilterer{contract: contract}}, nil +} + +// NewERC20PermitCaller creates a new read-only instance of ERC20Permit, bound to a specific deployed contract. +func NewERC20PermitCaller(address common.Address, caller bind.ContractCaller) (*ERC20PermitCaller, error) { + contract, err := bindERC20Permit(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ERC20PermitCaller{contract: contract}, nil +} + +// NewERC20PermitTransactor creates a new write-only instance of ERC20Permit, bound to a specific deployed contract. +func NewERC20PermitTransactor(address common.Address, transactor bind.ContractTransactor) (*ERC20PermitTransactor, error) { + contract, err := bindERC20Permit(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ERC20PermitTransactor{contract: contract}, nil +} + +// NewERC20PermitFilterer creates a new log filterer instance of ERC20Permit, bound to a specific deployed contract. +func NewERC20PermitFilterer(address common.Address, filterer bind.ContractFilterer) (*ERC20PermitFilterer, error) { + contract, err := bindERC20Permit(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ERC20PermitFilterer{contract: contract}, nil +} + +// bindERC20Permit binds a generic wrapper to an already deployed contract. +func bindERC20Permit(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ERC20PermitMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ERC20Permit *ERC20PermitRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC20Permit.Contract.ERC20PermitCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC20Permit *ERC20PermitRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20Permit.Contract.ERC20PermitTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC20Permit *ERC20PermitRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC20Permit.Contract.ERC20PermitTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ERC20Permit *ERC20PermitCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC20Permit.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC20Permit *ERC20PermitTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20Permit.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC20Permit *ERC20PermitTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC20Permit.Contract.contract.Transact(opts, method, params...) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitSession) DEFAULTADMINROLE() ([32]byte, error) { + return _ERC20Permit.Contract.DEFAULTADMINROLE(&_ERC20Permit.CallOpts) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _ERC20Permit.Contract.DEFAULTADMINROLE(&_ERC20Permit.CallOpts) +} + +// DENYLISTERROLE is a free data retrieval call binding the contract method 0x35401b78. +// +// Solidity: function DENYLISTER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCaller) DENYLISTERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "DENYLISTER_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// DENYLISTERROLE is a free data retrieval call binding the contract method 0x35401b78. +// +// Solidity: function DENYLISTER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitSession) DENYLISTERROLE() ([32]byte, error) { + return _ERC20Permit.Contract.DENYLISTERROLE(&_ERC20Permit.CallOpts) +} + +// DENYLISTERROLE is a free data retrieval call binding the contract method 0x35401b78. +// +// Solidity: function DENYLISTER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCallerSession) DENYLISTERROLE() ([32]byte, error) { + return _ERC20Permit.Contract.DENYLISTERROLE(&_ERC20Permit.CallOpts) +} + +// DOMAINSEPARATOR is a free data retrieval call binding the contract method 0x3644e515. +// +// Solidity: function DOMAIN_SEPARATOR() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCaller) DOMAINSEPARATOR(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "DOMAIN_SEPARATOR") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// DOMAINSEPARATOR is a free data retrieval call binding the contract method 0x3644e515. +// +// Solidity: function DOMAIN_SEPARATOR() view returns(bytes32) +func (_ERC20Permit *ERC20PermitSession) DOMAINSEPARATOR() ([32]byte, error) { + return _ERC20Permit.Contract.DOMAINSEPARATOR(&_ERC20Permit.CallOpts) +} + +// DOMAINSEPARATOR is a free data retrieval call binding the contract method 0x3644e515. +// +// Solidity: function DOMAIN_SEPARATOR() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCallerSession) DOMAINSEPARATOR() ([32]byte, error) { + return _ERC20Permit.Contract.DOMAINSEPARATOR(&_ERC20Permit.CallOpts) +} + +// MINTERROLE is a free data retrieval call binding the contract method 0xd5391393. +// +// Solidity: function MINTER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCaller) MINTERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "MINTER_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// MINTERROLE is a free data retrieval call binding the contract method 0xd5391393. +// +// Solidity: function MINTER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitSession) MINTERROLE() ([32]byte, error) { + return _ERC20Permit.Contract.MINTERROLE(&_ERC20Permit.CallOpts) +} + +// MINTERROLE is a free data retrieval call binding the contract method 0xd5391393. +// +// Solidity: function MINTER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCallerSession) MINTERROLE() ([32]byte, error) { + return _ERC20Permit.Contract.MINTERROLE(&_ERC20Permit.CallOpts) +} + +// PAUSERROLE is a free data retrieval call binding the contract method 0xe63ab1e9. +// +// Solidity: function PAUSER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCaller) PAUSERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "PAUSER_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// PAUSERROLE is a free data retrieval call binding the contract method 0xe63ab1e9. +// +// Solidity: function PAUSER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitSession) PAUSERROLE() ([32]byte, error) { + return _ERC20Permit.Contract.PAUSERROLE(&_ERC20Permit.CallOpts) +} + +// PAUSERROLE is a free data retrieval call binding the contract method 0xe63ab1e9. +// +// Solidity: function PAUSER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCallerSession) PAUSERROLE() ([32]byte, error) { + return _ERC20Permit.Contract.PAUSERROLE(&_ERC20Permit.CallOpts) +} + +// UPGRADERROLE is a free data retrieval call binding the contract method 0xf72c0d8b. +// +// Solidity: function UPGRADER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCaller) UPGRADERROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "UPGRADER_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// UPGRADERROLE is a free data retrieval call binding the contract method 0xf72c0d8b. +// +// Solidity: function UPGRADER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitSession) UPGRADERROLE() ([32]byte, error) { + return _ERC20Permit.Contract.UPGRADERROLE(&_ERC20Permit.CallOpts) +} + +// UPGRADERROLE is a free data retrieval call binding the contract method 0xf72c0d8b. +// +// Solidity: function UPGRADER_ROLE() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCallerSession) UPGRADERROLE() ([32]byte, error) { + return _ERC20Permit.Contract.UPGRADERROLE(&_ERC20Permit.CallOpts) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_ERC20Permit *ERC20PermitCaller) Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "allowance", owner, spender) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_ERC20Permit *ERC20PermitSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { + return _ERC20Permit.Contract.Allowance(&_ERC20Permit.CallOpts, owner, spender) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address owner, address spender) view returns(uint256) +func (_ERC20Permit *ERC20PermitCallerSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { + return _ERC20Permit.Contract.Allowance(&_ERC20Permit.CallOpts, owner, spender) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_ERC20Permit *ERC20PermitCaller) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "balanceOf", account) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_ERC20Permit *ERC20PermitSession) BalanceOf(account common.Address) (*big.Int, error) { + return _ERC20Permit.Contract.BalanceOf(&_ERC20Permit.CallOpts, account) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address account) view returns(uint256) +func (_ERC20Permit *ERC20PermitCallerSession) BalanceOf(account common.Address) (*big.Int, error) { + return _ERC20Permit.Contract.BalanceOf(&_ERC20Permit.CallOpts, account) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_ERC20Permit *ERC20PermitCaller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "decimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_ERC20Permit *ERC20PermitSession) Decimals() (uint8, error) { + return _ERC20Permit.Contract.Decimals(&_ERC20Permit.CallOpts) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_ERC20Permit *ERC20PermitCallerSession) Decimals() (uint8, error) { + return _ERC20Permit.Contract.Decimals(&_ERC20Permit.CallOpts) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_ERC20Permit *ERC20PermitCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "getRoleAdmin", role) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_ERC20Permit *ERC20PermitSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _ERC20Permit.Contract.GetRoleAdmin(&_ERC20Permit.CallOpts, role) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_ERC20Permit *ERC20PermitCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _ERC20Permit.Contract.GetRoleAdmin(&_ERC20Permit.CallOpts, role) +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_ERC20Permit *ERC20PermitCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "hasRole", role, account) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_ERC20Permit *ERC20PermitSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _ERC20Permit.Contract.HasRole(&_ERC20Permit.CallOpts, role, account) +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_ERC20Permit *ERC20PermitCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _ERC20Permit.Contract.HasRole(&_ERC20Permit.CallOpts, role, account) +} + +// IsDenylisted is a free data retrieval call binding the contract method 0xe877a526. +// +// Solidity: function isDenylisted(address denylistee) view returns(bool) +func (_ERC20Permit *ERC20PermitCaller) IsDenylisted(opts *bind.CallOpts, denylistee common.Address) (bool, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "isDenylisted", denylistee) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsDenylisted is a free data retrieval call binding the contract method 0xe877a526. +// +// Solidity: function isDenylisted(address denylistee) view returns(bool) +func (_ERC20Permit *ERC20PermitSession) IsDenylisted(denylistee common.Address) (bool, error) { + return _ERC20Permit.Contract.IsDenylisted(&_ERC20Permit.CallOpts, denylistee) +} + +// IsDenylisted is a free data retrieval call binding the contract method 0xe877a526. +// +// Solidity: function isDenylisted(address denylistee) view returns(bool) +func (_ERC20Permit *ERC20PermitCallerSession) IsDenylisted(denylistee common.Address) (bool, error) { + return _ERC20Permit.Contract.IsDenylisted(&_ERC20Permit.CallOpts, denylistee) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_ERC20Permit *ERC20PermitCaller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_ERC20Permit *ERC20PermitSession) Name() (string, error) { + return _ERC20Permit.Contract.Name(&_ERC20Permit.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_ERC20Permit *ERC20PermitCallerSession) Name() (string, error) { + return _ERC20Permit.Contract.Name(&_ERC20Permit.CallOpts) +} + +// Nonces is a free data retrieval call binding the contract method 0x7ecebe00. +// +// Solidity: function nonces(address owner) view returns(uint256) +func (_ERC20Permit *ERC20PermitCaller) Nonces(opts *bind.CallOpts, owner common.Address) (*big.Int, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "nonces", owner) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Nonces is a free data retrieval call binding the contract method 0x7ecebe00. +// +// Solidity: function nonces(address owner) view returns(uint256) +func (_ERC20Permit *ERC20PermitSession) Nonces(owner common.Address) (*big.Int, error) { + return _ERC20Permit.Contract.Nonces(&_ERC20Permit.CallOpts, owner) +} + +// Nonces is a free data retrieval call binding the contract method 0x7ecebe00. +// +// Solidity: function nonces(address owner) view returns(uint256) +func (_ERC20Permit *ERC20PermitCallerSession) Nonces(owner common.Address) (*big.Int, error) { + return _ERC20Permit.Contract.Nonces(&_ERC20Permit.CallOpts, owner) +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_ERC20Permit *ERC20PermitCaller) Paused(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "paused") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_ERC20Permit *ERC20PermitSession) Paused() (bool, error) { + return _ERC20Permit.Contract.Paused(&_ERC20Permit.CallOpts) +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_ERC20Permit *ERC20PermitCallerSession) Paused() (bool, error) { + return _ERC20Permit.Contract.Paused(&_ERC20Permit.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCaller) ProxiableUUID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "proxiableUUID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_ERC20Permit *ERC20PermitSession) ProxiableUUID() ([32]byte, error) { + return _ERC20Permit.Contract.ProxiableUUID(&_ERC20Permit.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_ERC20Permit *ERC20PermitCallerSession) ProxiableUUID() ([32]byte, error) { + return _ERC20Permit.Contract.ProxiableUUID(&_ERC20Permit.CallOpts) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_ERC20Permit *ERC20PermitCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_ERC20Permit *ERC20PermitSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _ERC20Permit.Contract.SupportsInterface(&_ERC20Permit.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_ERC20Permit *ERC20PermitCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _ERC20Permit.Contract.SupportsInterface(&_ERC20Permit.CallOpts, interfaceId) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_ERC20Permit *ERC20PermitCaller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_ERC20Permit *ERC20PermitSession) Symbol() (string, error) { + return _ERC20Permit.Contract.Symbol(&_ERC20Permit.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_ERC20Permit *ERC20PermitCallerSession) Symbol() (string, error) { + return _ERC20Permit.Contract.Symbol(&_ERC20Permit.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_ERC20Permit *ERC20PermitCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _ERC20Permit.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_ERC20Permit *ERC20PermitSession) TotalSupply() (*big.Int, error) { + return _ERC20Permit.Contract.TotalSupply(&_ERC20Permit.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_ERC20Permit *ERC20PermitCallerSession) TotalSupply() (*big.Int, error) { + return _ERC20Permit.Contract.TotalSupply(&_ERC20Permit.CallOpts) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_ERC20Permit *ERC20PermitTransactor) Approve(opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "approve", spender, amount) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_ERC20Permit *ERC20PermitSession) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.Approve(&_ERC20Permit.TransactOpts, spender, amount) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 amount) returns(bool) +func (_ERC20Permit *ERC20PermitTransactorSession) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.Approve(&_ERC20Permit.TransactOpts, spender, amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x42966c68. +// +// Solidity: function burn(uint256 amount) returns() +func (_ERC20Permit *ERC20PermitTransactor) Burn(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "burn", amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x42966c68. +// +// Solidity: function burn(uint256 amount) returns() +func (_ERC20Permit *ERC20PermitSession) Burn(amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.Burn(&_ERC20Permit.TransactOpts, amount) +} + +// Burn is a paid mutator transaction binding the contract method 0x42966c68. +// +// Solidity: function burn(uint256 amount) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) Burn(amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.Burn(&_ERC20Permit.TransactOpts, amount) +} + +// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7. +// +// Solidity: function decreaseAllowance(address spender, uint256 subtractedValue) returns(bool) +func (_ERC20Permit *ERC20PermitTransactor) DecreaseAllowance(opts *bind.TransactOpts, spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "decreaseAllowance", spender, subtractedValue) +} + +// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7. +// +// Solidity: function decreaseAllowance(address spender, uint256 subtractedValue) returns(bool) +func (_ERC20Permit *ERC20PermitSession) DecreaseAllowance(spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.DecreaseAllowance(&_ERC20Permit.TransactOpts, spender, subtractedValue) +} + +// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7. +// +// Solidity: function decreaseAllowance(address spender, uint256 subtractedValue) returns(bool) +func (_ERC20Permit *ERC20PermitTransactorSession) DecreaseAllowance(spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.DecreaseAllowance(&_ERC20Permit.TransactOpts, spender, subtractedValue) +} + +// Denylist is a paid mutator transaction binding the contract method 0x3371bfff. +// +// Solidity: function denylist(address denylistee) returns() +func (_ERC20Permit *ERC20PermitTransactor) Denylist(opts *bind.TransactOpts, denylistee common.Address) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "denylist", denylistee) +} + +// Denylist is a paid mutator transaction binding the contract method 0x3371bfff. +// +// Solidity: function denylist(address denylistee) returns() +func (_ERC20Permit *ERC20PermitSession) Denylist(denylistee common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.Denylist(&_ERC20Permit.TransactOpts, denylistee) +} + +// Denylist is a paid mutator transaction binding the contract method 0x3371bfff. +// +// Solidity: function denylist(address denylistee) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) Denylist(denylistee common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.Denylist(&_ERC20Permit.TransactOpts, denylistee) +} + +// DestroyDenylistedFunds is a paid mutator transaction binding the contract method 0x305c807e. +// +// Solidity: function destroyDenylistedFunds(address denylistee) returns() +func (_ERC20Permit *ERC20PermitTransactor) DestroyDenylistedFunds(opts *bind.TransactOpts, denylistee common.Address) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "destroyDenylistedFunds", denylistee) +} + +// DestroyDenylistedFunds is a paid mutator transaction binding the contract method 0x305c807e. +// +// Solidity: function destroyDenylistedFunds(address denylistee) returns() +func (_ERC20Permit *ERC20PermitSession) DestroyDenylistedFunds(denylistee common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.DestroyDenylistedFunds(&_ERC20Permit.TransactOpts, denylistee) +} + +// DestroyDenylistedFunds is a paid mutator transaction binding the contract method 0x305c807e. +// +// Solidity: function destroyDenylistedFunds(address denylistee) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) DestroyDenylistedFunds(denylistee common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.DestroyDenylistedFunds(&_ERC20Permit.TransactOpts, denylistee) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_ERC20Permit *ERC20PermitTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "grantRole", role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_ERC20Permit *ERC20PermitSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.GrantRole(&_ERC20Permit.TransactOpts, role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.GrantRole(&_ERC20Permit.TransactOpts, role, account) +} + +// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351. +// +// Solidity: function increaseAllowance(address spender, uint256 addedValue) returns(bool) +func (_ERC20Permit *ERC20PermitTransactor) IncreaseAllowance(opts *bind.TransactOpts, spender common.Address, addedValue *big.Int) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "increaseAllowance", spender, addedValue) +} + +// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351. +// +// Solidity: function increaseAllowance(address spender, uint256 addedValue) returns(bool) +func (_ERC20Permit *ERC20PermitSession) IncreaseAllowance(spender common.Address, addedValue *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.IncreaseAllowance(&_ERC20Permit.TransactOpts, spender, addedValue) +} + +// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351. +// +// Solidity: function increaseAllowance(address spender, uint256 addedValue) returns(bool) +func (_ERC20Permit *ERC20PermitTransactorSession) IncreaseAllowance(spender common.Address, addedValue *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.IncreaseAllowance(&_ERC20Permit.TransactOpts, spender, addedValue) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8. +// +// Solidity: function initialize(address admin) returns() +func (_ERC20Permit *ERC20PermitTransactor) Initialize(opts *bind.TransactOpts, admin common.Address) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "initialize", admin) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8. +// +// Solidity: function initialize(address admin) returns() +func (_ERC20Permit *ERC20PermitSession) Initialize(admin common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.Initialize(&_ERC20Permit.TransactOpts, admin) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8. +// +// Solidity: function initialize(address admin) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) Initialize(admin common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.Initialize(&_ERC20Permit.TransactOpts, admin) +} + +// InitializeV3 is a paid mutator transaction binding the contract method 0x38e454b1. +// +// Solidity: function initializeV3() returns() +func (_ERC20Permit *ERC20PermitTransactor) InitializeV3(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "initializeV3") +} + +// InitializeV3 is a paid mutator transaction binding the contract method 0x38e454b1. +// +// Solidity: function initializeV3() returns() +func (_ERC20Permit *ERC20PermitSession) InitializeV3() (*types.Transaction, error) { + return _ERC20Permit.Contract.InitializeV3(&_ERC20Permit.TransactOpts) +} + +// InitializeV3 is a paid mutator transaction binding the contract method 0x38e454b1. +// +// Solidity: function initializeV3() returns() +func (_ERC20Permit *ERC20PermitTransactorSession) InitializeV3() (*types.Transaction, error) { + return _ERC20Permit.Contract.InitializeV3(&_ERC20Permit.TransactOpts) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address to, uint256 amount) returns() +func (_ERC20Permit *ERC20PermitTransactor) Mint(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "mint", to, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address to, uint256 amount) returns() +func (_ERC20Permit *ERC20PermitSession) Mint(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.Mint(&_ERC20Permit.TransactOpts, to, amount) +} + +// Mint is a paid mutator transaction binding the contract method 0x40c10f19. +// +// Solidity: function mint(address to, uint256 amount) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) Mint(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.Mint(&_ERC20Permit.TransactOpts, to, amount) +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_ERC20Permit *ERC20PermitTransactor) Pause(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "pause") +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_ERC20Permit *ERC20PermitSession) Pause() (*types.Transaction, error) { + return _ERC20Permit.Contract.Pause(&_ERC20Permit.TransactOpts) +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_ERC20Permit *ERC20PermitTransactorSession) Pause() (*types.Transaction, error) { + return _ERC20Permit.Contract.Pause(&_ERC20Permit.TransactOpts) +} + +// Permit is a paid mutator transaction binding the contract method 0xd505accf. +// +// Solidity: function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) returns() +func (_ERC20Permit *ERC20PermitTransactor) Permit(opts *bind.TransactOpts, owner common.Address, spender common.Address, value *big.Int, deadline *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "permit", owner, spender, value, deadline, v, r, s) +} + +// Permit is a paid mutator transaction binding the contract method 0xd505accf. +// +// Solidity: function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) returns() +func (_ERC20Permit *ERC20PermitSession) Permit(owner common.Address, spender common.Address, value *big.Int, deadline *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { + return _ERC20Permit.Contract.Permit(&_ERC20Permit.TransactOpts, owner, spender, value, deadline, v, r, s) +} + +// Permit is a paid mutator transaction binding the contract method 0xd505accf. +// +// Solidity: function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) Permit(owner common.Address, spender common.Address, value *big.Int, deadline *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { + return _ERC20Permit.Contract.Permit(&_ERC20Permit.TransactOpts, owner, spender, value, deadline, v, r, s) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address account) returns() +func (_ERC20Permit *ERC20PermitTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "renounceRole", role, account) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address account) returns() +func (_ERC20Permit *ERC20PermitSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.RenounceRole(&_ERC20Permit.TransactOpts, role, account) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address account) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.RenounceRole(&_ERC20Permit.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_ERC20Permit *ERC20PermitTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "revokeRole", role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_ERC20Permit *ERC20PermitSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.RevokeRole(&_ERC20Permit.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.RevokeRole(&_ERC20Permit.TransactOpts, role, account) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 amount) returns(bool) +func (_ERC20Permit *ERC20PermitTransactor) Transfer(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "transfer", to, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 amount) returns(bool) +func (_ERC20Permit *ERC20PermitSession) Transfer(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.Transfer(&_ERC20Permit.TransactOpts, to, amount) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 amount) returns(bool) +func (_ERC20Permit *ERC20PermitTransactorSession) Transfer(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.Transfer(&_ERC20Permit.TransactOpts, to, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 amount) returns(bool) +func (_ERC20Permit *ERC20PermitTransactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "transferFrom", from, to, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 amount) returns(bool) +func (_ERC20Permit *ERC20PermitSession) TransferFrom(from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.TransferFrom(&_ERC20Permit.TransactOpts, from, to, amount) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 amount) returns(bool) +func (_ERC20Permit *ERC20PermitTransactorSession) TransferFrom(from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _ERC20Permit.Contract.TransferFrom(&_ERC20Permit.TransactOpts, from, to, amount) +} + +// Undenylist is a paid mutator transaction binding the contract method 0xb3faaf69. +// +// Solidity: function undenylist(address denylistee) returns() +func (_ERC20Permit *ERC20PermitTransactor) Undenylist(opts *bind.TransactOpts, denylistee common.Address) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "undenylist", denylistee) +} + +// Undenylist is a paid mutator transaction binding the contract method 0xb3faaf69. +// +// Solidity: function undenylist(address denylistee) returns() +func (_ERC20Permit *ERC20PermitSession) Undenylist(denylistee common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.Undenylist(&_ERC20Permit.TransactOpts, denylistee) +} + +// Undenylist is a paid mutator transaction binding the contract method 0xb3faaf69. +// +// Solidity: function undenylist(address denylistee) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) Undenylist(denylistee common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.Undenylist(&_ERC20Permit.TransactOpts, denylistee) +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_ERC20Permit *ERC20PermitTransactor) Unpause(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "unpause") +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_ERC20Permit *ERC20PermitSession) Unpause() (*types.Transaction, error) { + return _ERC20Permit.Contract.Unpause(&_ERC20Permit.TransactOpts) +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_ERC20Permit *ERC20PermitTransactorSession) Unpause() (*types.Transaction, error) { + return _ERC20Permit.Contract.Unpause(&_ERC20Permit.TransactOpts) +} + +// UpgradeTo is a paid mutator transaction binding the contract method 0x3659cfe6. +// +// Solidity: function upgradeTo(address newImplementation) returns() +func (_ERC20Permit *ERC20PermitTransactor) UpgradeTo(opts *bind.TransactOpts, newImplementation common.Address) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "upgradeTo", newImplementation) +} + +// UpgradeTo is a paid mutator transaction binding the contract method 0x3659cfe6. +// +// Solidity: function upgradeTo(address newImplementation) returns() +func (_ERC20Permit *ERC20PermitSession) UpgradeTo(newImplementation common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.UpgradeTo(&_ERC20Permit.TransactOpts, newImplementation) +} + +// UpgradeTo is a paid mutator transaction binding the contract method 0x3659cfe6. +// +// Solidity: function upgradeTo(address newImplementation) returns() +func (_ERC20Permit *ERC20PermitTransactorSession) UpgradeTo(newImplementation common.Address) (*types.Transaction, error) { + return _ERC20Permit.Contract.UpgradeTo(&_ERC20Permit.TransactOpts, newImplementation) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_ERC20Permit *ERC20PermitTransactor) UpgradeToAndCall(opts *bind.TransactOpts, newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _ERC20Permit.contract.Transact(opts, "upgradeToAndCall", newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_ERC20Permit *ERC20PermitSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _ERC20Permit.Contract.UpgradeToAndCall(&_ERC20Permit.TransactOpts, newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_ERC20Permit *ERC20PermitTransactorSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _ERC20Permit.Contract.UpgradeToAndCall(&_ERC20Permit.TransactOpts, newImplementation, data) +} + +// ERC20PermitAdminChangedIterator is returned from FilterAdminChanged and is used to iterate over the raw logs and unpacked data for AdminChanged events raised by the ERC20Permit contract. +type ERC20PermitAdminChangedIterator struct { + Event *ERC20PermitAdminChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitAdminChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitAdminChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitAdminChanged represents a AdminChanged event raised by the ERC20Permit contract. +type ERC20PermitAdminChanged struct { + PreviousAdmin common.Address + NewAdmin common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAdminChanged is a free log retrieval operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f. +// +// Solidity: event AdminChanged(address previousAdmin, address newAdmin) +func (_ERC20Permit *ERC20PermitFilterer) FilterAdminChanged(opts *bind.FilterOpts) (*ERC20PermitAdminChangedIterator, error) { + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "AdminChanged") + if err != nil { + return nil, err + } + return &ERC20PermitAdminChangedIterator{contract: _ERC20Permit.contract, event: "AdminChanged", logs: logs, sub: sub}, nil +} + +// WatchAdminChanged is a free log subscription operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f. +// +// Solidity: event AdminChanged(address previousAdmin, address newAdmin) +func (_ERC20Permit *ERC20PermitFilterer) WatchAdminChanged(opts *bind.WatchOpts, sink chan<- *ERC20PermitAdminChanged) (event.Subscription, error) { + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "AdminChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitAdminChanged) + if err := _ERC20Permit.contract.UnpackLog(event, "AdminChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAdminChanged is a log parse operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f. +// +// Solidity: event AdminChanged(address previousAdmin, address newAdmin) +func (_ERC20Permit *ERC20PermitFilterer) ParseAdminChanged(log types.Log) (*ERC20PermitAdminChanged, error) { + event := new(ERC20PermitAdminChanged) + if err := _ERC20Permit.contract.UnpackLog(event, "AdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the ERC20Permit contract. +type ERC20PermitApprovalIterator struct { + Event *ERC20PermitApproval // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitApprovalIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitApproval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitApproval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitApprovalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitApproval represents a Approval event raised by the ERC20Permit contract. +type ERC20PermitApproval struct { + Owner common.Address + Spender common.Address + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_ERC20Permit *ERC20PermitFilterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*ERC20PermitApprovalIterator, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var spenderRule []interface{} + for _, spenderItem := range spender { + spenderRule = append(spenderRule, spenderItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "Approval", ownerRule, spenderRule) + if err != nil { + return nil, err + } + return &ERC20PermitApprovalIterator{contract: _ERC20Permit.contract, event: "Approval", logs: logs, sub: sub}, nil +} + +// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_ERC20Permit *ERC20PermitFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *ERC20PermitApproval, owner []common.Address, spender []common.Address) (event.Subscription, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var spenderRule []interface{} + for _, spenderItem := range spender { + spenderRule = append(spenderRule, spenderItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "Approval", ownerRule, spenderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitApproval) + if err := _ERC20Permit.contract.UnpackLog(event, "Approval", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) +func (_ERC20Permit *ERC20PermitFilterer) ParseApproval(log types.Log) (*ERC20PermitApproval, error) { + event := new(ERC20PermitApproval) + if err := _ERC20Permit.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitBeaconUpgradedIterator is returned from FilterBeaconUpgraded and is used to iterate over the raw logs and unpacked data for BeaconUpgraded events raised by the ERC20Permit contract. +type ERC20PermitBeaconUpgradedIterator struct { + Event *ERC20PermitBeaconUpgraded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitBeaconUpgradedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitBeaconUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitBeaconUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitBeaconUpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitBeaconUpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitBeaconUpgraded represents a BeaconUpgraded event raised by the ERC20Permit contract. +type ERC20PermitBeaconUpgraded struct { + Beacon common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBeaconUpgraded is a free log retrieval operation binding the contract event 0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e. +// +// Solidity: event BeaconUpgraded(address indexed beacon) +func (_ERC20Permit *ERC20PermitFilterer) FilterBeaconUpgraded(opts *bind.FilterOpts, beacon []common.Address) (*ERC20PermitBeaconUpgradedIterator, error) { + + var beaconRule []interface{} + for _, beaconItem := range beacon { + beaconRule = append(beaconRule, beaconItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "BeaconUpgraded", beaconRule) + if err != nil { + return nil, err + } + return &ERC20PermitBeaconUpgradedIterator{contract: _ERC20Permit.contract, event: "BeaconUpgraded", logs: logs, sub: sub}, nil +} + +// WatchBeaconUpgraded is a free log subscription operation binding the contract event 0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e. +// +// Solidity: event BeaconUpgraded(address indexed beacon) +func (_ERC20Permit *ERC20PermitFilterer) WatchBeaconUpgraded(opts *bind.WatchOpts, sink chan<- *ERC20PermitBeaconUpgraded, beacon []common.Address) (event.Subscription, error) { + + var beaconRule []interface{} + for _, beaconItem := range beacon { + beaconRule = append(beaconRule, beaconItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "BeaconUpgraded", beaconRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitBeaconUpgraded) + if err := _ERC20Permit.contract.UnpackLog(event, "BeaconUpgraded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseBeaconUpgraded is a log parse operation binding the contract event 0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e. +// +// Solidity: event BeaconUpgraded(address indexed beacon) +func (_ERC20Permit *ERC20PermitFilterer) ParseBeaconUpgraded(log types.Log) (*ERC20PermitBeaconUpgraded, error) { + event := new(ERC20PermitBeaconUpgraded) + if err := _ERC20Permit.contract.UnpackLog(event, "BeaconUpgraded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitBurnIterator is returned from FilterBurn and is used to iterate over the raw logs and unpacked data for Burn events raised by the ERC20Permit contract. +type ERC20PermitBurnIterator struct { + Event *ERC20PermitBurn // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitBurnIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitBurn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitBurn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitBurnIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitBurnIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitBurn represents a Burn event raised by the ERC20Permit contract. +type ERC20PermitBurn struct { + Burner common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBurn is a free log retrieval operation binding the contract event 0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5. +// +// Solidity: event Burn(address indexed burner, uint256 amount) +func (_ERC20Permit *ERC20PermitFilterer) FilterBurn(opts *bind.FilterOpts, burner []common.Address) (*ERC20PermitBurnIterator, error) { + + var burnerRule []interface{} + for _, burnerItem := range burner { + burnerRule = append(burnerRule, burnerItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "Burn", burnerRule) + if err != nil { + return nil, err + } + return &ERC20PermitBurnIterator{contract: _ERC20Permit.contract, event: "Burn", logs: logs, sub: sub}, nil +} + +// WatchBurn is a free log subscription operation binding the contract event 0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5. +// +// Solidity: event Burn(address indexed burner, uint256 amount) +func (_ERC20Permit *ERC20PermitFilterer) WatchBurn(opts *bind.WatchOpts, sink chan<- *ERC20PermitBurn, burner []common.Address) (event.Subscription, error) { + + var burnerRule []interface{} + for _, burnerItem := range burner { + burnerRule = append(burnerRule, burnerItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "Burn", burnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitBurn) + if err := _ERC20Permit.contract.UnpackLog(event, "Burn", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseBurn is a log parse operation binding the contract event 0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5. +// +// Solidity: event Burn(address indexed burner, uint256 amount) +func (_ERC20Permit *ERC20PermitFilterer) ParseBurn(log types.Log) (*ERC20PermitBurn, error) { + event := new(ERC20PermitBurn) + if err := _ERC20Permit.contract.UnpackLog(event, "Burn", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitDenylistIterator is returned from FilterDenylist and is used to iterate over the raw logs and unpacked data for Denylist events raised by the ERC20Permit contract. +type ERC20PermitDenylistIterator struct { + Event *ERC20PermitDenylist // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitDenylistIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitDenylist) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitDenylist) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitDenylistIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitDenylistIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitDenylist represents a Denylist event raised by the ERC20Permit contract. +type ERC20PermitDenylist struct { + Denylister common.Address + Denylistee common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDenylist is a free log retrieval operation binding the contract event 0xceb5b8e70f171110880eb48cd4c914d7a4380d50c5c6e7cbbe7f95b86b48033a. +// +// Solidity: event Denylist(address indexed denylister, address indexed denylistee) +func (_ERC20Permit *ERC20PermitFilterer) FilterDenylist(opts *bind.FilterOpts, denylister []common.Address, denylistee []common.Address) (*ERC20PermitDenylistIterator, error) { + + var denylisterRule []interface{} + for _, denylisterItem := range denylister { + denylisterRule = append(denylisterRule, denylisterItem) + } + var denylisteeRule []interface{} + for _, denylisteeItem := range denylistee { + denylisteeRule = append(denylisteeRule, denylisteeItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "Denylist", denylisterRule, denylisteeRule) + if err != nil { + return nil, err + } + return &ERC20PermitDenylistIterator{contract: _ERC20Permit.contract, event: "Denylist", logs: logs, sub: sub}, nil +} + +// WatchDenylist is a free log subscription operation binding the contract event 0xceb5b8e70f171110880eb48cd4c914d7a4380d50c5c6e7cbbe7f95b86b48033a. +// +// Solidity: event Denylist(address indexed denylister, address indexed denylistee) +func (_ERC20Permit *ERC20PermitFilterer) WatchDenylist(opts *bind.WatchOpts, sink chan<- *ERC20PermitDenylist, denylister []common.Address, denylistee []common.Address) (event.Subscription, error) { + + var denylisterRule []interface{} + for _, denylisterItem := range denylister { + denylisterRule = append(denylisterRule, denylisterItem) + } + var denylisteeRule []interface{} + for _, denylisteeItem := range denylistee { + denylisteeRule = append(denylisteeRule, denylisteeItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "Denylist", denylisterRule, denylisteeRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitDenylist) + if err := _ERC20Permit.contract.UnpackLog(event, "Denylist", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseDenylist is a log parse operation binding the contract event 0xceb5b8e70f171110880eb48cd4c914d7a4380d50c5c6e7cbbe7f95b86b48033a. +// +// Solidity: event Denylist(address indexed denylister, address indexed denylistee) +func (_ERC20Permit *ERC20PermitFilterer) ParseDenylist(log types.Log) (*ERC20PermitDenylist, error) { + event := new(ERC20PermitDenylist) + if err := _ERC20Permit.contract.UnpackLog(event, "Denylist", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitDestroyDenylistedFundsIterator is returned from FilterDestroyDenylistedFunds and is used to iterate over the raw logs and unpacked data for DestroyDenylistedFunds events raised by the ERC20Permit contract. +type ERC20PermitDestroyDenylistedFundsIterator struct { + Event *ERC20PermitDestroyDenylistedFunds // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitDestroyDenylistedFundsIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitDestroyDenylistedFunds) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitDestroyDenylistedFunds) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitDestroyDenylistedFundsIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitDestroyDenylistedFundsIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitDestroyDenylistedFunds represents a DestroyDenylistedFunds event raised by the ERC20Permit contract. +type ERC20PermitDestroyDenylistedFunds struct { + Denylister common.Address + Denylistee common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDestroyDenylistedFunds is a free log retrieval operation binding the contract event 0x20350697b4b2860e783224572f60de169c87baf104d6892f39a55611230a7a1e. +// +// Solidity: event DestroyDenylistedFunds(address indexed denylister, address indexed denylistee, uint256 indexed amount) +func (_ERC20Permit *ERC20PermitFilterer) FilterDestroyDenylistedFunds(opts *bind.FilterOpts, denylister []common.Address, denylistee []common.Address, amount []*big.Int) (*ERC20PermitDestroyDenylistedFundsIterator, error) { + + var denylisterRule []interface{} + for _, denylisterItem := range denylister { + denylisterRule = append(denylisterRule, denylisterItem) + } + var denylisteeRule []interface{} + for _, denylisteeItem := range denylistee { + denylisteeRule = append(denylisteeRule, denylisteeItem) + } + var amountRule []interface{} + for _, amountItem := range amount { + amountRule = append(amountRule, amountItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "DestroyDenylistedFunds", denylisterRule, denylisteeRule, amountRule) + if err != nil { + return nil, err + } + return &ERC20PermitDestroyDenylistedFundsIterator{contract: _ERC20Permit.contract, event: "DestroyDenylistedFunds", logs: logs, sub: sub}, nil +} + +// WatchDestroyDenylistedFunds is a free log subscription operation binding the contract event 0x20350697b4b2860e783224572f60de169c87baf104d6892f39a55611230a7a1e. +// +// Solidity: event DestroyDenylistedFunds(address indexed denylister, address indexed denylistee, uint256 indexed amount) +func (_ERC20Permit *ERC20PermitFilterer) WatchDestroyDenylistedFunds(opts *bind.WatchOpts, sink chan<- *ERC20PermitDestroyDenylistedFunds, denylister []common.Address, denylistee []common.Address, amount []*big.Int) (event.Subscription, error) { + + var denylisterRule []interface{} + for _, denylisterItem := range denylister { + denylisterRule = append(denylisterRule, denylisterItem) + } + var denylisteeRule []interface{} + for _, denylisteeItem := range denylistee { + denylisteeRule = append(denylisteeRule, denylisteeItem) + } + var amountRule []interface{} + for _, amountItem := range amount { + amountRule = append(amountRule, amountItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "DestroyDenylistedFunds", denylisterRule, denylisteeRule, amountRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitDestroyDenylistedFunds) + if err := _ERC20Permit.contract.UnpackLog(event, "DestroyDenylistedFunds", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseDestroyDenylistedFunds is a log parse operation binding the contract event 0x20350697b4b2860e783224572f60de169c87baf104d6892f39a55611230a7a1e. +// +// Solidity: event DestroyDenylistedFunds(address indexed denylister, address indexed denylistee, uint256 indexed amount) +func (_ERC20Permit *ERC20PermitFilterer) ParseDestroyDenylistedFunds(log types.Log) (*ERC20PermitDestroyDenylistedFunds, error) { + event := new(ERC20PermitDestroyDenylistedFunds) + if err := _ERC20Permit.contract.UnpackLog(event, "DestroyDenylistedFunds", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the ERC20Permit contract. +type ERC20PermitInitializedIterator struct { + Event *ERC20PermitInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitInitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitInitialized represents a Initialized event raised by the ERC20Permit contract. +type ERC20PermitInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_ERC20Permit *ERC20PermitFilterer) FilterInitialized(opts *bind.FilterOpts) (*ERC20PermitInitializedIterator, error) { + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &ERC20PermitInitializedIterator{contract: _ERC20Permit.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_ERC20Permit *ERC20PermitFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *ERC20PermitInitialized) (event.Subscription, error) { + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitInitialized) + if err := _ERC20Permit.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_ERC20Permit *ERC20PermitFilterer) ParseInitialized(log types.Log) (*ERC20PermitInitialized, error) { + event := new(ERC20PermitInitialized) + if err := _ERC20Permit.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitMintIterator is returned from FilterMint and is used to iterate over the raw logs and unpacked data for Mint events raised by the ERC20Permit contract. +type ERC20PermitMintIterator struct { + Event *ERC20PermitMint // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitMintIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitMint) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitMint) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitMintIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitMintIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitMint represents a Mint event raised by the ERC20Permit contract. +type ERC20PermitMint struct { + Minter common.Address + To common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMint is a free log retrieval operation binding the contract event 0xab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8. +// +// Solidity: event Mint(address indexed minter, address indexed to, uint256 amount) +func (_ERC20Permit *ERC20PermitFilterer) FilterMint(opts *bind.FilterOpts, minter []common.Address, to []common.Address) (*ERC20PermitMintIterator, error) { + + var minterRule []interface{} + for _, minterItem := range minter { + minterRule = append(minterRule, minterItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "Mint", minterRule, toRule) + if err != nil { + return nil, err + } + return &ERC20PermitMintIterator{contract: _ERC20Permit.contract, event: "Mint", logs: logs, sub: sub}, nil +} + +// WatchMint is a free log subscription operation binding the contract event 0xab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8. +// +// Solidity: event Mint(address indexed minter, address indexed to, uint256 amount) +func (_ERC20Permit *ERC20PermitFilterer) WatchMint(opts *bind.WatchOpts, sink chan<- *ERC20PermitMint, minter []common.Address, to []common.Address) (event.Subscription, error) { + + var minterRule []interface{} + for _, minterItem := range minter { + minterRule = append(minterRule, minterItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "Mint", minterRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitMint) + if err := _ERC20Permit.contract.UnpackLog(event, "Mint", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseMint is a log parse operation binding the contract event 0xab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8. +// +// Solidity: event Mint(address indexed minter, address indexed to, uint256 amount) +func (_ERC20Permit *ERC20PermitFilterer) ParseMint(log types.Log) (*ERC20PermitMint, error) { + event := new(ERC20PermitMint) + if err := _ERC20Permit.contract.UnpackLog(event, "Mint", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitPausedIterator is returned from FilterPaused and is used to iterate over the raw logs and unpacked data for Paused events raised by the ERC20Permit contract. +type ERC20PermitPausedIterator struct { + Event *ERC20PermitPaused // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitPausedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitPaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitPaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitPausedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitPausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitPaused represents a Paused event raised by the ERC20Permit contract. +type ERC20PermitPaused struct { + Account common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterPaused is a free log retrieval operation binding the contract event 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258. +// +// Solidity: event Paused(address account) +func (_ERC20Permit *ERC20PermitFilterer) FilterPaused(opts *bind.FilterOpts) (*ERC20PermitPausedIterator, error) { + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "Paused") + if err != nil { + return nil, err + } + return &ERC20PermitPausedIterator{contract: _ERC20Permit.contract, event: "Paused", logs: logs, sub: sub}, nil +} + +// WatchPaused is a free log subscription operation binding the contract event 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258. +// +// Solidity: event Paused(address account) +func (_ERC20Permit *ERC20PermitFilterer) WatchPaused(opts *bind.WatchOpts, sink chan<- *ERC20PermitPaused) (event.Subscription, error) { + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "Paused") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitPaused) + if err := _ERC20Permit.contract.UnpackLog(event, "Paused", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParsePaused is a log parse operation binding the contract event 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258. +// +// Solidity: event Paused(address account) +func (_ERC20Permit *ERC20PermitFilterer) ParsePaused(log types.Log) (*ERC20PermitPaused, error) { + event := new(ERC20PermitPaused) + if err := _ERC20Permit.contract.UnpackLog(event, "Paused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the ERC20Permit contract. +type ERC20PermitRoleAdminChangedIterator struct { + Event *ERC20PermitRoleAdminChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitRoleAdminChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitRoleAdminChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitRoleAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitRoleAdminChanged represents a RoleAdminChanged event raised by the ERC20Permit contract. +type ERC20PermitRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_ERC20Permit *ERC20PermitFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*ERC20PermitRoleAdminChangedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return &ERC20PermitRoleAdminChangedIterator{contract: _ERC20Permit.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil +} + +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_ERC20Permit *ERC20PermitFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *ERC20PermitRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitRoleAdminChanged) + if err := _ERC20Permit.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_ERC20Permit *ERC20PermitFilterer) ParseRoleAdminChanged(log types.Log) (*ERC20PermitRoleAdminChanged, error) { + event := new(ERC20PermitRoleAdminChanged) + if err := _ERC20Permit.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the ERC20Permit contract. +type ERC20PermitRoleGrantedIterator struct { + Event *ERC20PermitRoleGranted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitRoleGrantedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitRoleGrantedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitRoleGrantedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitRoleGranted represents a RoleGranted event raised by the ERC20Permit contract. +type ERC20PermitRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_ERC20Permit *ERC20PermitFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*ERC20PermitRoleGrantedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &ERC20PermitRoleGrantedIterator{contract: _ERC20Permit.contract, event: "RoleGranted", logs: logs, sub: sub}, nil +} + +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_ERC20Permit *ERC20PermitFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *ERC20PermitRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitRoleGranted) + if err := _ERC20Permit.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_ERC20Permit *ERC20PermitFilterer) ParseRoleGranted(log types.Log) (*ERC20PermitRoleGranted, error) { + event := new(ERC20PermitRoleGranted) + if err := _ERC20Permit.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the ERC20Permit contract. +type ERC20PermitRoleRevokedIterator struct { + Event *ERC20PermitRoleRevoked // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitRoleRevokedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitRoleRevokedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitRoleRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitRoleRevoked represents a RoleRevoked event raised by the ERC20Permit contract. +type ERC20PermitRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_ERC20Permit *ERC20PermitFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*ERC20PermitRoleRevokedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &ERC20PermitRoleRevokedIterator{contract: _ERC20Permit.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil +} + +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_ERC20Permit *ERC20PermitFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *ERC20PermitRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitRoleRevoked) + if err := _ERC20Permit.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_ERC20Permit *ERC20PermitFilterer) ParseRoleRevoked(log types.Log) (*ERC20PermitRoleRevoked, error) { + event := new(ERC20PermitRoleRevoked) + if err := _ERC20Permit.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the ERC20Permit contract. +type ERC20PermitTransferIterator struct { + Event *ERC20PermitTransfer // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitTransferIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitTransfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitTransfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitTransferIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitTransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitTransfer represents a Transfer event raised by the ERC20Permit contract. +type ERC20PermitTransfer struct { + From common.Address + To common.Address + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_ERC20Permit *ERC20PermitFilterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ERC20PermitTransferIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "Transfer", fromRule, toRule) + if err != nil { + return nil, err + } + return &ERC20PermitTransferIterator{contract: _ERC20Permit.contract, event: "Transfer", logs: logs, sub: sub}, nil +} + +// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_ERC20Permit *ERC20PermitFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *ERC20PermitTransfer, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "Transfer", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitTransfer) + if err := _ERC20Permit.contract.UnpackLog(event, "Transfer", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) +func (_ERC20Permit *ERC20PermitFilterer) ParseTransfer(log types.Log) (*ERC20PermitTransfer, error) { + event := new(ERC20PermitTransfer) + if err := _ERC20Permit.contract.UnpackLog(event, "Transfer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitUndenylistIterator is returned from FilterUndenylist and is used to iterate over the raw logs and unpacked data for Undenylist events raised by the ERC20Permit contract. +type ERC20PermitUndenylistIterator struct { + Event *ERC20PermitUndenylist // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitUndenylistIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitUndenylist) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitUndenylist) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitUndenylistIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitUndenylistIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitUndenylist represents a Undenylist event raised by the ERC20Permit contract. +type ERC20PermitUndenylist struct { + Denylister common.Address + Denylistee common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUndenylist is a free log retrieval operation binding the contract event 0x27821e555926d0ea38c2d580beffe8abdd21467de56f78939ce7ba8ce8de322e. +// +// Solidity: event Undenylist(address indexed denylister, address indexed denylistee) +func (_ERC20Permit *ERC20PermitFilterer) FilterUndenylist(opts *bind.FilterOpts, denylister []common.Address, denylistee []common.Address) (*ERC20PermitUndenylistIterator, error) { + + var denylisterRule []interface{} + for _, denylisterItem := range denylister { + denylisterRule = append(denylisterRule, denylisterItem) + } + var denylisteeRule []interface{} + for _, denylisteeItem := range denylistee { + denylisteeRule = append(denylisteeRule, denylisteeItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "Undenylist", denylisterRule, denylisteeRule) + if err != nil { + return nil, err + } + return &ERC20PermitUndenylistIterator{contract: _ERC20Permit.contract, event: "Undenylist", logs: logs, sub: sub}, nil +} + +// WatchUndenylist is a free log subscription operation binding the contract event 0x27821e555926d0ea38c2d580beffe8abdd21467de56f78939ce7ba8ce8de322e. +// +// Solidity: event Undenylist(address indexed denylister, address indexed denylistee) +func (_ERC20Permit *ERC20PermitFilterer) WatchUndenylist(opts *bind.WatchOpts, sink chan<- *ERC20PermitUndenylist, denylister []common.Address, denylistee []common.Address) (event.Subscription, error) { + + var denylisterRule []interface{} + for _, denylisterItem := range denylister { + denylisterRule = append(denylisterRule, denylisterItem) + } + var denylisteeRule []interface{} + for _, denylisteeItem := range denylistee { + denylisteeRule = append(denylisteeRule, denylisteeItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "Undenylist", denylisterRule, denylisteeRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitUndenylist) + if err := _ERC20Permit.contract.UnpackLog(event, "Undenylist", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUndenylist is a log parse operation binding the contract event 0x27821e555926d0ea38c2d580beffe8abdd21467de56f78939ce7ba8ce8de322e. +// +// Solidity: event Undenylist(address indexed denylister, address indexed denylistee) +func (_ERC20Permit *ERC20PermitFilterer) ParseUndenylist(log types.Log) (*ERC20PermitUndenylist, error) { + event := new(ERC20PermitUndenylist) + if err := _ERC20Permit.contract.UnpackLog(event, "Undenylist", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitUnpausedIterator is returned from FilterUnpaused and is used to iterate over the raw logs and unpacked data for Unpaused events raised by the ERC20Permit contract. +type ERC20PermitUnpausedIterator struct { + Event *ERC20PermitUnpaused // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitUnpausedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitUnpaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitUnpaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitUnpausedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitUnpausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitUnpaused represents a Unpaused event raised by the ERC20Permit contract. +type ERC20PermitUnpaused struct { + Account common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUnpaused is a free log retrieval operation binding the contract event 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa. +// +// Solidity: event Unpaused(address account) +func (_ERC20Permit *ERC20PermitFilterer) FilterUnpaused(opts *bind.FilterOpts) (*ERC20PermitUnpausedIterator, error) { + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "Unpaused") + if err != nil { + return nil, err + } + return &ERC20PermitUnpausedIterator{contract: _ERC20Permit.contract, event: "Unpaused", logs: logs, sub: sub}, nil +} + +// WatchUnpaused is a free log subscription operation binding the contract event 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa. +// +// Solidity: event Unpaused(address account) +func (_ERC20Permit *ERC20PermitFilterer) WatchUnpaused(opts *bind.WatchOpts, sink chan<- *ERC20PermitUnpaused) (event.Subscription, error) { + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "Unpaused") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitUnpaused) + if err := _ERC20Permit.contract.UnpackLog(event, "Unpaused", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUnpaused is a log parse operation binding the contract event 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa. +// +// Solidity: event Unpaused(address account) +func (_ERC20Permit *ERC20PermitFilterer) ParseUnpaused(log types.Log) (*ERC20PermitUnpaused, error) { + event := new(ERC20PermitUnpaused) + if err := _ERC20Permit.contract.UnpackLog(event, "Unpaused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ERC20PermitUpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the ERC20Permit contract. +type ERC20PermitUpgradedIterator struct { + Event *ERC20PermitUpgraded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20PermitUpgradedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20PermitUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20PermitUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20PermitUpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20PermitUpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20PermitUpgraded represents a Upgraded event raised by the ERC20Permit contract. +type ERC20PermitUpgraded struct { + Implementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_ERC20Permit *ERC20PermitFilterer) FilterUpgraded(opts *bind.FilterOpts, implementation []common.Address) (*ERC20PermitUpgradedIterator, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _ERC20Permit.contract.FilterLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return &ERC20PermitUpgradedIterator{contract: _ERC20Permit.contract, event: "Upgraded", logs: logs, sub: sub}, nil +} + +// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_ERC20Permit *ERC20PermitFilterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *ERC20PermitUpgraded, implementation []common.Address) (event.Subscription, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _ERC20Permit.contract.WatchLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20PermitUpgraded) + if err := _ERC20Permit.contract.UnpackLog(event, "Upgraded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_ERC20Permit *ERC20PermitFilterer) ParseUpgraded(log types.Log) (*ERC20PermitUpgraded, error) { + event := new(ERC20PermitUpgraded) + if err := _ERC20Permit.contract.UnpackLog(event, "Upgraded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/contracts/erc20_transfer_permit.go b/contracts/erc20_transfer_permit.go new file mode 100644 index 0000000..e59958a --- /dev/null +++ b/contracts/erc20_transfer_permit.go @@ -0,0 +1,428 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contracts + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// ERC20TransferWithPermitMetaData contains all meta data concerning the ERC20TransferWithPermit contract. +var ERC20TransferWithPermitMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeAmount_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline_\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v_\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r_\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s_\",\"type\":\"bytes32\"}],\"name\":\"transferWithPermit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// ERC20TransferWithPermitABI is the input ABI used to generate the binding from. +// Deprecated: Use ERC20TransferWithPermitMetaData.ABI instead. +var ERC20TransferWithPermitABI = ERC20TransferWithPermitMetaData.ABI + +// ERC20TransferWithPermit is an auto generated Go binding around an Ethereum contract. +type ERC20TransferWithPermit struct { + ERC20TransferWithPermitCaller // Read-only binding to the contract + ERC20TransferWithPermitTransactor // Write-only binding to the contract + ERC20TransferWithPermitFilterer // Log filterer for contract events +} + +// ERC20TransferWithPermitCaller is an auto generated read-only Go binding around an Ethereum contract. +type ERC20TransferWithPermitCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20TransferWithPermitTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ERC20TransferWithPermitTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20TransferWithPermitFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ERC20TransferWithPermitFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ERC20TransferWithPermitSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ERC20TransferWithPermitSession struct { + Contract *ERC20TransferWithPermit // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ERC20TransferWithPermitCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ERC20TransferWithPermitCallerSession struct { + Contract *ERC20TransferWithPermitCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ERC20TransferWithPermitTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ERC20TransferWithPermitTransactorSession struct { + Contract *ERC20TransferWithPermitTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ERC20TransferWithPermitRaw is an auto generated low-level Go binding around an Ethereum contract. +type ERC20TransferWithPermitRaw struct { + Contract *ERC20TransferWithPermit // Generic contract binding to access the raw methods on +} + +// ERC20TransferWithPermitCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ERC20TransferWithPermitCallerRaw struct { + Contract *ERC20TransferWithPermitCaller // Generic read-only contract binding to access the raw methods on +} + +// ERC20TransferWithPermitTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ERC20TransferWithPermitTransactorRaw struct { + Contract *ERC20TransferWithPermitTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewERC20TransferWithPermit creates a new instance of ERC20TransferWithPermit, bound to a specific deployed contract. +func NewERC20TransferWithPermit(address common.Address, backend bind.ContractBackend) (*ERC20TransferWithPermit, error) { + contract, err := bindERC20TransferWithPermit(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ERC20TransferWithPermit{ERC20TransferWithPermitCaller: ERC20TransferWithPermitCaller{contract: contract}, ERC20TransferWithPermitTransactor: ERC20TransferWithPermitTransactor{contract: contract}, ERC20TransferWithPermitFilterer: ERC20TransferWithPermitFilterer{contract: contract}}, nil +} + +// NewERC20TransferWithPermitCaller creates a new read-only instance of ERC20TransferWithPermit, bound to a specific deployed contract. +func NewERC20TransferWithPermitCaller(address common.Address, caller bind.ContractCaller) (*ERC20TransferWithPermitCaller, error) { + contract, err := bindERC20TransferWithPermit(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ERC20TransferWithPermitCaller{contract: contract}, nil +} + +// NewERC20TransferWithPermitTransactor creates a new write-only instance of ERC20TransferWithPermit, bound to a specific deployed contract. +func NewERC20TransferWithPermitTransactor(address common.Address, transactor bind.ContractTransactor) (*ERC20TransferWithPermitTransactor, error) { + contract, err := bindERC20TransferWithPermit(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ERC20TransferWithPermitTransactor{contract: contract}, nil +} + +// NewERC20TransferWithPermitFilterer creates a new log filterer instance of ERC20TransferWithPermit, bound to a specific deployed contract. +func NewERC20TransferWithPermitFilterer(address common.Address, filterer bind.ContractFilterer) (*ERC20TransferWithPermitFilterer, error) { + contract, err := bindERC20TransferWithPermit(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ERC20TransferWithPermitFilterer{contract: contract}, nil +} + +// bindERC20TransferWithPermit binds a generic wrapper to an already deployed contract. +func bindERC20TransferWithPermit(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ERC20TransferWithPermitMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ERC20TransferWithPermit *ERC20TransferWithPermitRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC20TransferWithPermit.Contract.ERC20TransferWithPermitCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC20TransferWithPermit *ERC20TransferWithPermitRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20TransferWithPermit.Contract.ERC20TransferWithPermitTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC20TransferWithPermit *ERC20TransferWithPermitRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC20TransferWithPermit.Contract.ERC20TransferWithPermitTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ERC20TransferWithPermit *ERC20TransferWithPermitCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ERC20TransferWithPermit.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ERC20TransferWithPermit *ERC20TransferWithPermitTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20TransferWithPermit.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ERC20TransferWithPermit *ERC20TransferWithPermitTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ERC20TransferWithPermit.Contract.contract.Transact(opts, method, params...) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_ERC20TransferWithPermit *ERC20TransferWithPermitCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _ERC20TransferWithPermit.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_ERC20TransferWithPermit *ERC20TransferWithPermitSession) Owner() (common.Address, error) { + return _ERC20TransferWithPermit.Contract.Owner(&_ERC20TransferWithPermit.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_ERC20TransferWithPermit *ERC20TransferWithPermitCallerSession) Owner() (common.Address, error) { + return _ERC20TransferWithPermit.Contract.Owner(&_ERC20TransferWithPermit.CallOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_ERC20TransferWithPermit *ERC20TransferWithPermitTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ERC20TransferWithPermit.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_ERC20TransferWithPermit *ERC20TransferWithPermitSession) RenounceOwnership() (*types.Transaction, error) { + return _ERC20TransferWithPermit.Contract.RenounceOwnership(&_ERC20TransferWithPermit.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_ERC20TransferWithPermit *ERC20TransferWithPermitTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _ERC20TransferWithPermit.Contract.RenounceOwnership(&_ERC20TransferWithPermit.TransactOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_ERC20TransferWithPermit *ERC20TransferWithPermitTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _ERC20TransferWithPermit.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_ERC20TransferWithPermit *ERC20TransferWithPermitSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _ERC20TransferWithPermit.Contract.TransferOwnership(&_ERC20TransferWithPermit.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_ERC20TransferWithPermit *ERC20TransferWithPermitTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _ERC20TransferWithPermit.Contract.TransferOwnership(&_ERC20TransferWithPermit.TransactOpts, newOwner) +} + +// TransferWithPermit is a paid mutator transaction binding the contract method 0xfdd95894. +// +// Solidity: function transferWithPermit(address token_, address owner_, address recipient_, uint256 amount_, uint256 feeAmount_, uint256 deadline_, uint8 v_, bytes32 r_, bytes32 s_) returns() +func (_ERC20TransferWithPermit *ERC20TransferWithPermitTransactor) TransferWithPermit(opts *bind.TransactOpts, token_ common.Address, owner_ common.Address, recipient_ common.Address, amount_ *big.Int, feeAmount_ *big.Int, deadline_ *big.Int, v_ uint8, r_ [32]byte, s_ [32]byte) (*types.Transaction, error) { + return _ERC20TransferWithPermit.contract.Transact(opts, "transferWithPermit", token_, owner_, recipient_, amount_, feeAmount_, deadline_, v_, r_, s_) +} + +// TransferWithPermit is a paid mutator transaction binding the contract method 0xfdd95894. +// +// Solidity: function transferWithPermit(address token_, address owner_, address recipient_, uint256 amount_, uint256 feeAmount_, uint256 deadline_, uint8 v_, bytes32 r_, bytes32 s_) returns() +func (_ERC20TransferWithPermit *ERC20TransferWithPermitSession) TransferWithPermit(token_ common.Address, owner_ common.Address, recipient_ common.Address, amount_ *big.Int, feeAmount_ *big.Int, deadline_ *big.Int, v_ uint8, r_ [32]byte, s_ [32]byte) (*types.Transaction, error) { + return _ERC20TransferWithPermit.Contract.TransferWithPermit(&_ERC20TransferWithPermit.TransactOpts, token_, owner_, recipient_, amount_, feeAmount_, deadline_, v_, r_, s_) +} + +// TransferWithPermit is a paid mutator transaction binding the contract method 0xfdd95894. +// +// Solidity: function transferWithPermit(address token_, address owner_, address recipient_, uint256 amount_, uint256 feeAmount_, uint256 deadline_, uint8 v_, bytes32 r_, bytes32 s_) returns() +func (_ERC20TransferWithPermit *ERC20TransferWithPermitTransactorSession) TransferWithPermit(token_ common.Address, owner_ common.Address, recipient_ common.Address, amount_ *big.Int, feeAmount_ *big.Int, deadline_ *big.Int, v_ uint8, r_ [32]byte, s_ [32]byte) (*types.Transaction, error) { + return _ERC20TransferWithPermit.Contract.TransferWithPermit(&_ERC20TransferWithPermit.TransactOpts, token_, owner_, recipient_, amount_, feeAmount_, deadline_, v_, r_, s_) +} + +// ERC20TransferWithPermitOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the ERC20TransferWithPermit contract. +type ERC20TransferWithPermitOwnershipTransferredIterator struct { + Event *ERC20TransferWithPermitOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ERC20TransferWithPermitOwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ERC20TransferWithPermitOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ERC20TransferWithPermitOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ERC20TransferWithPermitOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ERC20TransferWithPermitOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ERC20TransferWithPermitOwnershipTransferred represents a OwnershipTransferred event raised by the ERC20TransferWithPermit contract. +type ERC20TransferWithPermitOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_ERC20TransferWithPermit *ERC20TransferWithPermitFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*ERC20TransferWithPermitOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _ERC20TransferWithPermit.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &ERC20TransferWithPermitOwnershipTransferredIterator{contract: _ERC20TransferWithPermit.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_ERC20TransferWithPermit *ERC20TransferWithPermitFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *ERC20TransferWithPermitOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _ERC20TransferWithPermit.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ERC20TransferWithPermitOwnershipTransferred) + if err := _ERC20TransferWithPermit.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_ERC20TransferWithPermit *ERC20TransferWithPermitFilterer) ParseOwnershipTransferred(log types.Log) (*ERC20TransferWithPermitOwnershipTransferred, error) { + event := new(ERC20TransferWithPermitOwnershipTransferred) + if err := _ERC20TransferWithPermit.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} From 59f5e40140122f2358b6b86637999024bbf6761e Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Fri, 31 May 2024 20:00:21 +0300 Subject: [PATCH 04/14] update: fix typos, refactor folders structure --- internal/config/airdrop.go | 4 +- internal/config/broadcaster.go | 58 ++++++--- internal/service/api/ctx.go | 116 ++++++++++++++++++ .../{ => api}/handlers/create_airdrop.go | 22 ++-- .../api/handlers/get_airdrop_params.go | 13 ++ .../service/{ => api}/handlers/middleware.go | 3 +- .../{ => api}/requests/create_airdrop.go | 4 +- .../service/{ => api}/requests/get_airdrop.go | 0 .../service/{ => api}/requests/validation.go | 0 .../{ => service}/broadcaster/broadcaster.go | 2 +- internal/service/handlers/ctx.go | 71 ----------- internal/service/handlers/get_airdrop.go | 62 ---------- .../service/handlers/get_airdrop_params.go | 23 ---- 13 files changed, 187 insertions(+), 191 deletions(-) create mode 100644 internal/service/api/ctx.go rename internal/service/{ => api}/handlers/create_airdrop.go (64%) create mode 100644 internal/service/api/handlers/get_airdrop_params.go rename internal/service/{ => api}/handlers/middleware.go (88%) rename internal/service/{ => api}/requests/create_airdrop.go (88%) rename internal/service/{ => api}/requests/get_airdrop.go (100%) rename internal/service/{ => api}/requests/validation.go (100%) rename internal/{ => service}/broadcaster/broadcaster.go (99%) delete mode 100644 internal/service/handlers/ctx.go delete mode 100644 internal/service/handlers/get_airdrop.go delete mode 100644 internal/service/handlers/get_airdrop_params.go diff --git a/internal/config/airdrop.go b/internal/config/airdrop.go index 26837ef..b67f8eb 100644 --- a/internal/config/airdrop.go +++ b/internal/config/airdrop.go @@ -14,7 +14,7 @@ import ( const airdropYamlKey = "airdrop" type AirdropConfiger interface { - AridropConfig() AirdropConfig + AirdropConfig() AirdropConfig } type AirdropConfig struct { @@ -33,7 +33,7 @@ func NewAirdropConfiger(getter kv.Getter) AirdropConfiger { } } -func (v *airdrop) AridropConfig() AirdropConfig { +func (v *airdrop) AirdropConfig() AirdropConfig { return v.once.Do(func() interface{} { var result AirdropConfig diff --git a/internal/config/broadcaster.go b/internal/config/broadcaster.go index ed5f794..4fce113 100644 --- a/internal/config/broadcaster.go +++ b/internal/config/broadcaster.go @@ -19,14 +19,16 @@ import ( const broadcasterYamlKey = "broadcaster" type Broadcaster struct { - RPC *ethclient.Client - ChainID *big.Int - PrivateKey *ecdsa.PrivateKey - Address common.Address - QueryLimit uint64 - - nonce uint64 - mut *sync.Mutex + RPC *ethclient.Client + ChainID *big.Int + PrivateKey *ecdsa.PrivateKey + Address common.Address + QueryLimit uint64 + ERC20PermitTransfer common.Address + + gasMultiplier float64 + nonce uint64 + mut *sync.Mutex } type Broadcasterer interface { @@ -47,10 +49,12 @@ func NewBroadcaster(getter kv.Getter) Broadcasterer { func (b *broadcasterer) Broadcaster() Broadcaster { return b.once.Do(func() interface{} { var cfg struct { - RPC *ethclient.Client `fig:"rpc,required"` - ChainID *big.Int `fig:"chain_id,required"` - QueryLimit uint64 `fig:"query_limit"` - SenderPrivateKey *ecdsa.PrivateKey `fig:"sender_private_key"` + RPC *ethclient.Client `fig:"rpc,required"` + ChainID *big.Int `fig:"chain_id,required"` + QueryLimit uint64 `fig:"query_limit"` + SenderPrivateKey *ecdsa.PrivateKey `fig:"sender_private_key"` + ERC20PermitTransfer common.Address `fig:"erc20_permit_transfer,required"` + GasMultiplier float64 `fig:"gas_multiplier"` } err := figure. @@ -71,6 +75,11 @@ func (b *broadcasterer) Broadcaster() Broadcaster { queryLimit = cfg.QueryLimit } + gasMultiplier := float64(1) + if cfg.GasMultiplier > 0 { + gasMultiplier = cfg.GasMultiplier + } + address := crypto.PubkeyToAddress(cfg.SenderPrivateKey.PublicKey) nonce, err := cfg.RPC.NonceAt(context.Background(), address, nil) if err != nil { @@ -78,14 +87,16 @@ func (b *broadcasterer) Broadcaster() Broadcaster { } return Broadcaster{ - RPC: cfg.RPC, - PrivateKey: cfg.SenderPrivateKey, - Address: address, - ChainID: cfg.ChainID, - QueryLimit: queryLimit, - - nonce: nonce, - mut: &sync.Mutex{}, + RPC: cfg.RPC, + PrivateKey: cfg.SenderPrivateKey, + Address: address, + ChainID: cfg.ChainID, + QueryLimit: queryLimit, + ERC20PermitTransfer: cfg.ERC20PermitTransfer, + + gasMultiplier: gasMultiplier, + nonce: nonce, + mut: &sync.Mutex{}, } }).(Broadcaster) } @@ -128,3 +139,10 @@ func (n *Broadcaster) ResetNonce(client *ethclient.Client) error { n.nonce = nonce return nil } + +func (n *Broadcaster) MultiplyGasPrice(gasPrice *big.Int) *big.Int { + var ONE = 1000000000 // ONE - One GWEI + mult := big.NewFloat(0).Mul(big.NewFloat(n.gasMultiplier), big.NewFloat(float64(ONE))) + gas, _ := big.NewFloat(0).Mul(big.NewFloat(0).SetInt(gasPrice), mult).Int(nil) + return big.NewInt(0).Div(gas, big.NewInt(int64(ONE))) +} diff --git a/internal/service/api/ctx.go b/internal/service/api/ctx.go new file mode 100644 index 0000000..2da44f6 --- /dev/null +++ b/internal/service/api/ctx.go @@ -0,0 +1,116 @@ +package api + +import ( + "context" + "net/http" + + "github.com/rarimo/evm-airdrop-svc/contracts" + "github.com/rarimo/evm-airdrop-svc/internal/config" + "github.com/rarimo/evm-airdrop-svc/internal/data" + zk "github.com/rarimo/zkverifier-kit" + "gitlab.com/distributed_lab/logan/v3" +) + +type ctxKey int + +const ( + logCtxKey ctxKey = iota + airdropsQCtxKey + airdropConfigCtxKey + verifierCtxKey + airdropParamsCtxKey + broadcasterCtxKey + erc20PermitCtxKey + erc20PermitTransferCtxKey + priceApiConfigCtxKey +) + +func CtxLog(entry *logan.Entry) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, logCtxKey, entry) + } +} + +func Log(r *http.Request) *logan.Entry { + return r.Context().Value(logCtxKey).(*logan.Entry) +} + +func CtxAirdropsQ(q *data.AirdropsQ) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, airdropsQCtxKey, q) + } +} + +func AirdropsQ(r *http.Request) *data.AirdropsQ { + return r.Context().Value(airdropsQCtxKey).(*data.AirdropsQ).New() +} + +func CtxAirdropConfig(entry config.AirdropConfig) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, airdropConfigCtxKey, entry) + } +} + +func AirdropConfig(r *http.Request) config.AirdropConfig { + return r.Context().Value(airdropConfigCtxKey).(config.AirdropConfig) +} + +func CtxAirdropParams(params config.GlobalParams) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, airdropParamsCtxKey, params) + } +} + +func AirdropParams(r *http.Request) config.GlobalParams { + return r.Context().Value(airdropParamsCtxKey).(config.GlobalParams) +} + +func CtxVerifier(entry *zk.Verifier) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, verifierCtxKey, entry) + } +} + +func Verifier(r *http.Request) *zk.Verifier { + return r.Context().Value(verifierCtxKey).(*zk.Verifier) +} + +func Broadcaster(r *http.Request) config.Broadcaster { + return r.Context().Value(broadcasterCtxKey).(config.Broadcaster) +} + +func CtxBroadcaster(entry config.Broadcaster) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, broadcasterCtxKey, entry) + } +} + +func CtxERC20Permit(entry *contracts.ERC20Permit) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, erc20PermitCtxKey, entry) + } +} + +func ERC20Permit(r *http.Request) *contracts.ERC20Permit { + return r.Context().Value(erc20PermitCtxKey).(*contracts.ERC20Permit) +} + +func CtxERC20PermitTransfer(entry *contracts.ERC20TransferWithPermit) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, erc20PermitTransferCtxKey, entry) + } +} + +func ERC20PermitTransfer(r *http.Request) *contracts.ERC20TransferWithPermit { + return r.Context().Value(erc20PermitTransferCtxKey).(*contracts.ERC20TransferWithPermit) +} + +func CtxPriceApiConfig(entry config.PriceApiConfig) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, priceApiConfigCtxKey, entry) + } +} + +func PriceApiConfig(r *http.Request) config.PriceApiConfig { + return r.Context().Value(priceApiConfigCtxKey).(config.PriceApiConfig) +} diff --git a/internal/service/handlers/create_airdrop.go b/internal/service/api/handlers/create_airdrop.go similarity index 64% rename from internal/service/handlers/create_airdrop.go rename to internal/service/api/handlers/create_airdrop.go index 311fddc..992e3f1 100644 --- a/internal/service/handlers/create_airdrop.go +++ b/internal/service/api/handlers/create_airdrop.go @@ -5,7 +5,9 @@ import ( "net/http" "github.com/rarimo/evm-airdrop-svc/internal/data" - "github.com/rarimo/evm-airdrop-svc/internal/service/requests" + "github.com/rarimo/evm-airdrop-svc/internal/service/api" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/models" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/requests" zk "github.com/rarimo/zkverifier-kit" "github.com/rarimo/zkverifier-kit/identity" "gitlab.com/distributed_lab/ape" @@ -24,12 +26,12 @@ func CreateAirdrop(w http.ResponseWriter, r *http.Request) { nullifier := req.Data.Attributes.ZkProof.PubSignals[zk.Nullifier] - airdrop, err := AirdropsQ(r). + airdrop, err := api.AirdropsQ(r). FilterByNullifier(nullifier). FilterByStatuses(data.TxStatusCompleted, data.TxStatusPending, data.TxStatusInProgress). Get() if err != nil { - Log(r).WithError(err).Error("Failed to get airdrop by nullifier") + api.Log(r).WithError(err).Error("Failed to get airdrop by nullifier") ape.RenderErr(w, problems.InternalError()) return } @@ -38,31 +40,31 @@ func CreateAirdrop(w http.ResponseWriter, r *http.Request) { return } - err = Verifier(r).VerifyProof(req.Data.Attributes.ZkProof, zk.WithEthereumAddress(req.Data.Attributes.Address)) + err = api.Verifier(r).VerifyProof(req.Data.Attributes.ZkProof, zk.WithEthereumAddress(req.Data.Attributes.Address)) if err != nil { if errors.Is(err, identity.ErrContractCall) { - Log(r).WithError(err).Error("Failed to verify proof") + api.Log(r).WithError(err).Error("Failed to verify proof") ape.RenderErr(w, problems.InternalError()) return } - Log(r).WithError(err).Info("Invalid proof") + api.Log(r).WithError(err).Info("Invalid proof") ape.RenderErr(w, problems.BadRequest(err)...) return } - airdrop, err = AirdropsQ(r).Insert(data.Airdrop{ + airdrop, err = api.AirdropsQ(r).Insert(data.Airdrop{ Nullifier: nullifier, Address: req.Data.Attributes.Address, - Amount: AirdropAmount(r), + Amount: api.AirdropConfig(r).Amount.String(), Status: data.TxStatusPending, }) if err != nil { - Log(r).WithError(err).Errorf("Failed to insert airdrop") + api.Log(r).WithError(err).Errorf("Failed to insert airdrop") ape.RenderErr(w, problems.InternalError()) return } w.WriteHeader(http.StatusCreated) - ape.Render(w, toAirdropResponse(*airdrop)) + ape.Render(w, models.NewAirdropResponse(*airdrop)) } diff --git a/internal/service/api/handlers/get_airdrop_params.go b/internal/service/api/handlers/get_airdrop_params.go new file mode 100644 index 0000000..df8534a --- /dev/null +++ b/internal/service/api/handlers/get_airdrop_params.go @@ -0,0 +1,13 @@ +package handlers + +import ( + "net/http" + + "github.com/rarimo/evm-airdrop-svc/internal/service/api" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/models" + "gitlab.com/distributed_lab/ape" +) + +func GetAirdropParams(w http.ResponseWriter, r *http.Request) { + ape.Render(w, models.NewAirdropParams(api.AirdropParams(r))) +} diff --git a/internal/service/handlers/middleware.go b/internal/service/api/handlers/middleware.go similarity index 88% rename from internal/service/handlers/middleware.go rename to internal/service/api/handlers/middleware.go index 1d3591e..189995f 100644 --- a/internal/service/handlers/middleware.go +++ b/internal/service/api/handlers/middleware.go @@ -5,6 +5,7 @@ import ( "net/http" "github.com/rarimo/evm-airdrop-svc/internal/data" + "github.com/rarimo/evm-airdrop-svc/internal/service/api" "gitlab.com/distributed_lab/kit/pgdb" ) @@ -20,7 +21,7 @@ func DBCloneMiddleware(db *pgdb.DB) func(http.Handler) http.Handler { ctx := r.Context() extenders := []ctxExtender{ - CtxAirdropsQ(data.NewAirdropsQ(clone)), + api.CtxAirdropsQ(data.NewAirdropsQ(clone)), } for _, extender := range extenders { diff --git a/internal/service/requests/create_airdrop.go b/internal/service/api/requests/create_airdrop.go similarity index 88% rename from internal/service/requests/create_airdrop.go rename to internal/service/api/requests/create_airdrop.go index 06d08d9..64593c0 100644 --- a/internal/service/requests/create_airdrop.go +++ b/internal/service/api/requests/create_airdrop.go @@ -10,6 +10,8 @@ import ( "github.com/rarimo/evm-airdrop-svc/resources" ) +var ethAddrRegExp = regexp.MustCompile("^0x[0-9a-fA-F]{40}$") + func NewCreateAirdrop(r *http.Request) (req resources.CreateAirdropRequest, err error) { if err = json.NewDecoder(r.Body).Decode(&req); err != nil { return req, newDecodeError("body", err) @@ -21,7 +23,7 @@ func NewCreateAirdrop(r *http.Request) (req resources.CreateAirdropRequest, err "data/attributes/address": val.Validate( attr.Address, val.Required, - val.Match(regexp.MustCompile("^0x[0-9a-fA-F]{40}$")), + val.Match(ethAddrRegExp), ), }.Filter() } diff --git a/internal/service/requests/get_airdrop.go b/internal/service/api/requests/get_airdrop.go similarity index 100% rename from internal/service/requests/get_airdrop.go rename to internal/service/api/requests/get_airdrop.go diff --git a/internal/service/requests/validation.go b/internal/service/api/requests/validation.go similarity index 100% rename from internal/service/requests/validation.go rename to internal/service/api/requests/validation.go diff --git a/internal/broadcaster/broadcaster.go b/internal/service/broadcaster/broadcaster.go similarity index 99% rename from internal/broadcaster/broadcaster.go rename to internal/service/broadcaster/broadcaster.go index 039c670..a4a8586 100644 --- a/internal/broadcaster/broadcaster.go +++ b/internal/service/broadcaster/broadcaster.go @@ -39,7 +39,7 @@ func Run(ctx context.Context, cfg *config.Config) { log: log, q: data.NewAirdropsQ(cfg.DB().Clone()), Broadcaster: cfg.Broadcaster(), - AirdropConfig: cfg.AridropConfig(), + AirdropConfig: cfg.AirdropConfig(), } running.WithBackOff(ctx, r.log, "builtin-broadcaster", r.run, 5*time.Second, 5*time.Second, 5*time.Second) diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go deleted file mode 100644 index 51d4ae8..0000000 --- a/internal/service/handlers/ctx.go +++ /dev/null @@ -1,71 +0,0 @@ -package handlers - -import ( - "context" - "net/http" - - "github.com/rarimo/evm-airdrop-svc/internal/config" - "github.com/rarimo/evm-airdrop-svc/internal/data" - zk "github.com/rarimo/zkverifier-kit" - "gitlab.com/distributed_lab/logan/v3" -) - -type ctxKey int - -const ( - logCtxKey ctxKey = iota - airdropsQCtxKey - airdropAmountCtxKey - verifierCtxKey - airdropParamsCtxKey -) - -func CtxLog(entry *logan.Entry) func(context.Context) context.Context { - return func(ctx context.Context) context.Context { - return context.WithValue(ctx, logCtxKey, entry) - } -} - -func Log(r *http.Request) *logan.Entry { - return r.Context().Value(logCtxKey).(*logan.Entry) -} - -func CtxAirdropsQ(q *data.AirdropsQ) func(context.Context) context.Context { - return func(ctx context.Context) context.Context { - return context.WithValue(ctx, airdropsQCtxKey, q) - } -} - -func AirdropsQ(r *http.Request) *data.AirdropsQ { - return r.Context().Value(airdropsQCtxKey).(*data.AirdropsQ).New() -} - -func CtxAirdropAmount(amount string) func(context.Context) context.Context { - return func(ctx context.Context) context.Context { - return context.WithValue(ctx, airdropAmountCtxKey, amount) - } -} - -func AirdropAmount(r *http.Request) string { - return r.Context().Value(airdropAmountCtxKey).(string) -} - -func CtxAirdropParams(amount config.GlobalParams) func(context.Context) context.Context { - return func(ctx context.Context) context.Context { - return context.WithValue(ctx, airdropParamsCtxKey, amount) - } -} - -func AirdropParams(r *http.Request) config.GlobalParams { - return r.Context().Value(airdropParamsCtxKey).(config.GlobalParams) -} - -func CtxVerifier(entry *zk.Verifier) func(context.Context) context.Context { - return func(ctx context.Context) context.Context { - return context.WithValue(ctx, verifierCtxKey, entry) - } -} - -func Verifier(r *http.Request) *zk.Verifier { - return r.Context().Value(verifierCtxKey).(*zk.Verifier) -} diff --git a/internal/service/handlers/get_airdrop.go b/internal/service/handlers/get_airdrop.go deleted file mode 100644 index 41b5699..0000000 --- a/internal/service/handlers/get_airdrop.go +++ /dev/null @@ -1,62 +0,0 @@ -package handlers - -import ( - "net/http" - - "github.com/rarimo/evm-airdrop-svc/internal/data" - "github.com/rarimo/evm-airdrop-svc/internal/service/requests" - "github.com/rarimo/evm-airdrop-svc/resources" - "gitlab.com/distributed_lab/ape" - "gitlab.com/distributed_lab/ape/problems" -) - -func GetAirdrop(w http.ResponseWriter, r *http.Request) { - nullifier, err := requests.NewGetAirdrop(r) - if err != nil { - ape.RenderErr(w, problems.BadRequest(err)...) - return - } - - airdrops, err := AirdropsQ(r). - FilterByNullifier(nullifier). - Select() - if err != nil { - Log(r).WithError(err).Error("Failed to select airdrops by nullifier") - ape.RenderErr(w, problems.InternalError()) - return - } - if len(airdrops) == 0 { - ape.RenderErr(w, problems.NotFound()) - return - } - - airdrop := airdrops[0] - for _, a := range airdrops[1:] { - if a.Status == data.TxStatusCompleted { - airdrop = a - break - } - } - - ape.Render(w, toAirdropResponse(airdrop)) -} - -func toAirdropResponse(tx data.Airdrop) resources.AirdropResponse { - return resources.AirdropResponse{ - Data: resources.Airdrop{ - Key: resources.Key{ - ID: tx.ID, - Type: resources.AIRDROP, - }, - Attributes: resources.AirdropAttributes{ - Nullifier: tx.Nullifier, - Address: tx.Address, - TxHash: tx.TxHash, - Amount: tx.Amount, - Status: tx.Status, - CreatedAt: tx.CreatedAt, - UpdatedAt: tx.UpdatedAt, - }, - }, - } -} diff --git a/internal/service/handlers/get_airdrop_params.go b/internal/service/handlers/get_airdrop_params.go deleted file mode 100644 index 44990ef..0000000 --- a/internal/service/handlers/get_airdrop_params.go +++ /dev/null @@ -1,23 +0,0 @@ -package handlers - -import ( - "net/http" - - "github.com/rarimo/evm-airdrop-svc/resources" - "gitlab.com/distributed_lab/ape" -) - -func GetAirdropParams(w http.ResponseWriter, r *http.Request) { - ape.Render(w, resources.AirdropParamsResponse{ - Data: resources.AirdropParams{ - Key: resources.Key{ - Type: resources.AIRDROP, - }, - Attributes: resources.AirdropParamsAttributes{ - EventId: AirdropParams(r).EventID, - StartedAt: AirdropParams(r).AirdropStart, - QuerySelector: AirdropParams(r).QuerySelector, - }, - }, - }) -} From e9158f4c17f04364468081807f37010d62b82ff9 Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Fri, 31 May 2024 20:01:47 +0300 Subject: [PATCH 05/14] add: requests to estimate and transfer ERC20; update: configs with price api and contracts; --- config.yaml | 10 +- internal/cli/main.go | 2 +- internal/config/main.go | 2 + internal/config/price.go | 129 +++++++++++++++ internal/service/api/handlers/get_airdrop.go | 43 +++++ .../api/handlers/get_transfer_params.go | 150 +++++++++++++++++ .../service/api/handlers/send_transfer.go | 52 ++++++ .../service/api/requests/transfer_token.go | 154 ++++++++++++++++++ internal/service/router.go | 54 +++--- resources/model_resource_type.go | 1 + 10 files changed, 576 insertions(+), 21 deletions(-) create mode 100644 internal/config/price.go create mode 100644 internal/service/api/handlers/get_airdrop.go create mode 100644 internal/service/api/handlers/get_transfer_params.go create mode 100644 internal/service/api/handlers/send_transfer.go create mode 100644 internal/service/api/requests/transfer_token.go diff --git a/config.yaml b/config.yaml index bf92fb5..8d6cccc 100644 --- a/config.yaml +++ b/config.yaml @@ -17,11 +17,13 @@ broadcaster: chain_id: chain_id sender_private_key: priv_key query_limit: 10 + erc20_permit_transfer: contract_address + gas_multiplier: 1.1 verifier: verification_key_path: "./verification_key.json" allowed_age: 18 - allowed_citizenships: ["UKR"] + allowed_citizenships: [ "UKR" ] allowed_event_id: "event_id" allowed_query_selector: "query_selector" # at least one of these should be correct to pass: @@ -32,3 +34,9 @@ root_verifier: rpc: evm_rpc_url contract: registration_contract_address request_timeout: 10s + +price_api: + url: api_url #coinmarketcap + key: api_key + currency_id: 23888 + quote_tag: "ETH" \ No newline at end of file diff --git a/internal/cli/main.go b/internal/cli/main.go index 2791721..d16a46b 100644 --- a/internal/cli/main.go +++ b/internal/cli/main.go @@ -8,9 +8,9 @@ import ( "syscall" "github.com/alecthomas/kingpin" - "github.com/rarimo/evm-airdrop-svc/internal/broadcaster" "github.com/rarimo/evm-airdrop-svc/internal/config" "github.com/rarimo/evm-airdrop-svc/internal/service" + "github.com/rarimo/evm-airdrop-svc/internal/service/broadcaster" "gitlab.com/distributed_lab/kit/kv" "gitlab.com/distributed_lab/logan/v3" ) diff --git a/internal/config/main.go b/internal/config/main.go index 27a65f9..1115d3f 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -14,6 +14,7 @@ type Config struct { identity.VerifierProvider Broadcasterer AirdropConfiger + PriceApiConfiger airdrop comfig.Once verifier comfig.Once @@ -29,5 +30,6 @@ func New(getter kv.Getter) *Config { VerifierProvider: identity.NewVerifierProvider(getter), Broadcasterer: NewBroadcaster(getter), AirdropConfiger: NewAirdropConfiger(getter), + PriceApiConfiger: NewPriceApiConfiger(getter), } } diff --git a/internal/config/price.go b/internal/config/price.go new file mode 100644 index 0000000..a060349 --- /dev/null +++ b/internal/config/price.go @@ -0,0 +1,129 @@ +package config + +import ( + "encoding/json" + "io" + "math/big" + "net/http" + "net/url" + "time" + + "gitlab.com/distributed_lab/figure/v3" + "gitlab.com/distributed_lab/kit/comfig" + "gitlab.com/distributed_lab/kit/kv" + "gitlab.com/distributed_lab/logan/v3" + "gitlab.com/distributed_lab/logan/v3/errors" +) + +const priceApiYamlKey = "price_api" + +var ( + ErrPriceApiRequestFailed = errors.New("failed to fetch price api") + ErrEmptyPrice = errors.New("dollar price in ETH is empty") +) + +type PriceApiConfiger interface { + PriceApiConfig() PriceApiConfig +} + +type PriceApiConfig struct { + URL *url.URL `fig:"url,required"` + Key string `fig:"key,required"` + CurrencyId string `fig:"currency_id,required"` + QuoteTag string `fig:"quote_tag,required"` +} + +type priceApi struct { + once comfig.Once + getter kv.Getter +} + +func NewPriceApiConfiger(getter kv.Getter) PriceApiConfiger { + return &priceApi{ + getter: getter, + } +} + +func (v *priceApi) PriceApiConfig() PriceApiConfig { + return v.once.Do(func() interface{} { + var result PriceApiConfig + + err := figure. + Out(&result). + With(figure.BaseHooks). + From(kv.MustGetStringMap(v.getter, priceApiYamlKey)). + Please() + if err != nil { + panic(errors.Wrap(err, "failed to figure out config", logan.F{ + "yaml_key": priceApiYamlKey, + })) + } + + return result + }).(PriceApiConfig) +} + +type QuoteResponse struct { + Data map[string]Currency `json:"data"` +} + +type Currency struct { + Id int `json:"id"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Quote map[string]Quote `json:"quote"` +} + +type Quote struct { + Price float64 `json:"price"` + LastUpdated time.Time `json:"last_updated"` +} + +// ConvertPrice converts tokens price +func (cfg PriceApiConfig) ConvertPrice() (*big.Float, error) { + URL := cfg.URL.JoinPath("/v2/cryptocurrency/quotes/latest") + + query := URL.Query() + query.Set("id", cfg.CurrencyId) + query.Set("convert", cfg.QuoteTag) + + URL.RawQuery = query.Encode() + + request, err := http.NewRequest(http.MethodGet, URL.String(), nil) + if err != nil { + return nil, errors.Wrap(err, "failed to create request", logan.F{ + "url": URL, + }) + } + + request.Header.Set("X-CMC_PRO_API_KEY", cfg.Key) + + response, err := http.DefaultClient.Do(request) + if err != nil { + return nil, errors.Wrap(err, "failed to do request") + } + + if response.StatusCode != http.StatusOK { + body, err := io.ReadAll(response.Body) + if err != nil { + return nil, errors.Wrap(err, "failed to read response body") + } + + return nil, errors.From(ErrPriceApiRequestFailed, logan.F{ + "status": response.StatusCode, + "body": string(body), + }) + } + + var body QuoteResponse + if err = json.NewDecoder(response.Body).Decode(&body); err != nil { + return nil, errors.Wrap(err, "failed to decode response body") + } + + dollarInEth := big.NewFloat(body.Data[cfg.CurrencyId].Quote[cfg.QuoteTag].Price) + if dollarInEth.Cmp(big.NewFloat(0)) == 0 { + return nil, ErrEmptyPrice + } + + return dollarInEth, nil +} diff --git a/internal/service/api/handlers/get_airdrop.go b/internal/service/api/handlers/get_airdrop.go new file mode 100644 index 0000000..f3279fc --- /dev/null +++ b/internal/service/api/handlers/get_airdrop.go @@ -0,0 +1,43 @@ +package handlers + +import ( + "net/http" + + "github.com/rarimo/evm-airdrop-svc/internal/data" + "github.com/rarimo/evm-airdrop-svc/internal/service/api" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/models" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/requests" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" +) + +func GetAirdrop(w http.ResponseWriter, r *http.Request) { + nullifier, err := requests.NewGetAirdrop(r) + if err != nil { + ape.RenderErr(w, problems.BadRequest(err)...) + return + } + + airdrops, err := api.AirdropsQ(r). + FilterByNullifier(nullifier). + Select() + if err != nil { + api.Log(r).WithError(err).Error("Failed to select airdrops by nullifier") + ape.RenderErr(w, problems.InternalError()) + return + } + if len(airdrops) == 0 { + ape.RenderErr(w, problems.NotFound()) + return + } + + airdrop := airdrops[0] + for _, a := range airdrops[1:] { + if a.Status == data.TxStatusCompleted { + airdrop = a + break + } + } + + ape.Render(w, models.NewAirdropResponse(airdrop)) +} diff --git a/internal/service/api/handlers/get_transfer_params.go b/internal/service/api/handlers/get_transfer_params.go new file mode 100644 index 0000000..6ce0393 --- /dev/null +++ b/internal/service/api/handlers/get_transfer_params.go @@ -0,0 +1,150 @@ +package handlers + +import ( + "math/big" + "net/http" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + validation "github.com/go-ozzo/ozzo-validation/v4" + pkgErrors "github.com/pkg/errors" + "github.com/rarimo/evm-airdrop-svc/internal/service/api" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/models" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/requests" + "github.com/rarimo/evm-airdrop-svc/resources" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" + "gitlab.com/distributed_lab/logan/v3" + "gitlab.com/distributed_lab/logan/v3/errors" +) + +var ErrInsufficienciesAmount = errors.New("amount is insufficient to pay tx fee") + +type TransferTxParams struct { + amount *big.Int + fee *big.Int + gasPrice *big.Int + gasLimit uint64 + noSend bool +} + +func GetTransferParams(w http.ResponseWriter, r *http.Request) { + req, err := requests.NewTransferERC20Token(r) + if err != nil { + api.Log(r).WithError(err).Error("failed to parse request") + ape.RenderErr(w, problems.BadRequest(err)...) + return + } + + txParams, err := EstimateTransfer(r, req.Data.Attributes) + if err != nil { + api.Log(r).WithError(err).Error("failed to estimate transfer transaction") + if pkgErrors.Is(err, ErrInsufficienciesAmount) { + ape.RenderErr(w, problems.BadRequest(validation.Errors{ + "data/attributes/amount": errors.From(err, logan.F{ + "amount": txParams.amount, + "fee": txParams.fee, + }), + })...) + return + } + ape.RenderErr(w, problems.InternalError()) + return + } + + ape.Render(w, models.NewEstimateResponse(txParams.amount, txParams.fee)) +} + +func EstimateTransfer(r *http.Request, attr resources.TransferErc20TokenAttributes) (*TransferTxParams, error) { + halfAmount := new(big.Int).Div(attr.Amount, big.NewInt(2)) + + tx, err := MakeTransferWithPermitTx(r, attr, TransferTxParams{ + noSend: true, + fee: halfAmount, + amount: halfAmount, + }) + if err != nil { + return nil, errors.Wrap(err, "failed to build transfer tx") + } + + broadcaster := api.Broadcaster(r) + gasPrice := broadcaster.MultiplyGasPrice(tx.GasPrice()) + feeAmount, err := buildFeeTransferAmount(r, gasPrice, tx.Gas()) + if err != nil { + return nil, errors.Wrap(err, "failed to build fee transfer amount") + } + + amount := new(big.Int).Sub(attr.Amount, feeAmount) + + params := TransferTxParams{ + amount: amount, + fee: feeAmount, + gasPrice: gasPrice, + gasLimit: tx.Gas(), + } + + if amount.Cmp(new(big.Int)) != 1 { + return ¶ms, ErrInsufficienciesAmount + } + + return ¶ms, nil +} + +func MakeTransferWithPermitTx( + r *http.Request, + attr resources.TransferErc20TokenAttributes, + params TransferTxParams, +) (*types.Transaction, error) { + var ( + R [32]byte + S [32]byte + ) + + txOptions, err := bind.NewKeyedTransactorWithChainID(api.Broadcaster(r).PrivateKey, api.Broadcaster(r).ChainID) + if err != nil { + return nil, errors.Wrap(err, "failed to get tx options") + } + txOptions.NoSend = params.noSend + txOptions.GasPrice = params.gasPrice + txOptions.GasLimit = params.gasLimit + + copy(R[:], hexutil.MustDecode(attr.R)) + copy(S[:], hexutil.MustDecode(attr.S)) + + tx, err := api.ERC20PermitTransfer(r).TransferWithPermit( + txOptions, + api.AirdropConfig(r).TokenAddress, + attr.Sender, + attr.Receiver, + params.amount, + params.fee, + attr.Deadline, + attr.V, + R, + S, + ) + if err != nil { + return nil, errors.Wrap(err, "failed to build transfer with permit transaction") + } + + return tx, nil +} + +func buildFeeTransferAmount(r *http.Request, gweiGasPrice *big.Int, gasLimit uint64) (*big.Int, error) { + dollarInEth, err := api.PriceApiConfig(r).ConvertPrice() + if err != nil { + return nil, errors.Wrap(err, "failed to convert dollar price in eth") + } + + // Convert GWEI gas price to ETH gas price + ethGasPrice := new(big.Float).Quo(new(big.Float).SetInt(gweiGasPrice), big.NewFloat(1e18)) + // Convert ETH gas price to dollar correspondence + gasPriceInGlo := new(big.Float).Quo(ethGasPrice, dollarInEth) + + feeAmount := new(big.Float).Mul(new(big.Float).SetUint64(gasLimit), gasPriceInGlo) + + amount, _ := feeAmount.Int(nil) + + return amount, nil +} diff --git a/internal/service/api/handlers/send_transfer.go b/internal/service/api/handlers/send_transfer.go new file mode 100644 index 0000000..8826645 --- /dev/null +++ b/internal/service/api/handlers/send_transfer.go @@ -0,0 +1,52 @@ +package handlers + +import ( + "net/http" + + validation "github.com/go-ozzo/ozzo-validation/v4" + pkgErrors "github.com/pkg/errors" + "github.com/rarimo/evm-airdrop-svc/internal/service/api" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/models" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/requests" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" + "gitlab.com/distributed_lab/logan/v3" + "gitlab.com/distributed_lab/logan/v3/errors" +) + +func SendTransfer(w http.ResponseWriter, r *http.Request) { + req, err := requests.NewTransferERC20Token(r) + if err != nil { + api.Log(r).WithError(err).Error("failed to parse request") + ape.RenderErr(w, problems.BadRequest(err)...) + return + } + + txParams, err := EstimateTransfer(r, req.Data.Attributes) + if err != nil { + api.Log(r).WithError(err).Error("failed to estimate transfer transaction") + if pkgErrors.Is(err, ErrInsufficienciesAmount) { + ape.RenderErr(w, problems.BadRequest(validation.Errors{ + "data/attributes/amount": errors.From(err, logan.F{ + "amount": txParams.amount, + "fee": txParams.fee, + }), + })...) + return + } + ape.RenderErr(w, problems.InternalError()) + return + } + + txParams.noSend = false + tx, err := MakeTransferWithPermitTx(r, req.Data.Attributes, *txParams) + if err != nil { + api.Log(r).WithError(err).Error("failed to build transfer transaction", logan.F{ + "params": txParams, + }) + ape.RenderErr(w, problems.InternalError()) + return + } + + ape.Render(w, models.NewTxResponse(txParams.amount, txParams.fee, tx.Hash().Hex())) +} diff --git a/internal/service/api/requests/transfer_token.go b/internal/service/api/requests/transfer_token.go new file mode 100644 index 0000000..a51e4fd --- /dev/null +++ b/internal/service/api/requests/transfer_token.go @@ -0,0 +1,154 @@ +package requests + +import ( + "bytes" + "encoding/json" + "fmt" + "math/big" + "net/http" + "regexp" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/crypto" + val "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/evm-airdrop-svc/internal/service/api" + "github.com/rarimo/evm-airdrop-svc/resources" + "gitlab.com/distributed_lab/logan/v3" + "gitlab.com/distributed_lab/logan/v3/errors" +) + +var hexRegExp = regexp.MustCompile("0[xX][0-9a-fA-F]+") + +func NewTransferERC20Token(r *http.Request) (req resources.TransferErc20TokenRequest, err error) { + if err = json.NewDecoder(r.Body).Decode(&req); err != nil { + return req, newDecodeError("body", err) + } + + attr := req.Data.Attributes + + err = val.Errors{ + "data/type": val.Validate(req.Data.Type, val.Required, val.In(resources.TRANSFER_ERC20)), + "data/attributes/sender": val.Validate(attr.Sender.String(), val.Required, val.Match(ethAddrRegExp)), + "data/attributes/receiver": val.Validate(attr.Receiver.String(), val.Required, val.Match(ethAddrRegExp)), + "data/attributes/amount": val.Validate(attr.Amount.Int64(), val.Required, val.Min(0)), + "data/attributes/deadline": val.Validate(attr.Deadline.Int64(), val.Required, val.By(UnixTimestampRule)), + "data/attributes/R": val.Validate(attr.R, val.Required, val.Match(hexRegExp)), + "data/attributes/S": val.Validate(attr.S, val.Required, val.Match(hexRegExp)), + "data/attributes/V": val.Validate(attr.V, val.Required), + }.Filter() + if err != nil { + return req, err + } + + decimals := math.BigPow(1, 18) + attr.Amount = new(big.Int).Mul(req.Data.Attributes.Amount, decimals) + + if err = VerifyPermitSignature(r, attr); err != nil { + return req, val.Errors{ + "signature": errors.Wrap(err, "invalid permit signature"), + } + } + + req.Data.Attributes.Amount = new(big.Int).Mul(req.Data.Attributes.Amount, decimals) + + return req, nil +} + +func UnixTimestampRule(value interface{}) error { + parsedTimestamp, ok := value.(int64) + if !ok { + return errors.From(errors.New("must be a valid integer"), logan.F{ + "value": value, + }) + } + + timestamp := time.Unix(parsedTimestamp, 0) + if timestamp.IsZero() { + return errors.From(errors.New("timestamp is empty"), logan.F{ + "timestamp": timestamp, + }) + } + + return nil +} + +func VerifyPermitSignature(r *http.Request, attrs resources.TransferErc20TokenAttributes) error { + sigHash, err := buildMessage(r, attrs) + if err != nil { + return errors.Wrap(err, "failed to build hash message") + } + + rawSignature := make([]byte, 65) + copy(rawSignature[:32], hexutil.MustDecode(attrs.R)[:]) + copy(rawSignature[32:64], hexutil.MustDecode(attrs.S)[:]) + rawSignature[64] = attrs.V - 27 + + pubKey, err := crypto.SigToPub(sigHash, rawSignature) + if err != nil { + return errors.Wrap(err, "failed to recover public key from signature") + } + recoveredAddr := crypto.PubkeyToAddress(*pubKey) + + if bytes.Compare(recoveredAddr.Bytes(), attrs.Sender.Bytes()) != 0 { + fmt.Println(recoveredAddr.Hex()) + fmt.Println(attrs.Sender.Hex()) + return errors.New("recovered pubkey is invalid") + } + + return nil +} + +func buildMessage(r *http.Request, attrs resources.TransferErc20TokenAttributes) ([]byte, error) { + nonce, err := api.ERC20Permit(r).Nonces(&bind.CallOpts{}, attrs.Sender) + if err != nil { + return nil, errors.Wrap(err, "failed to get nonce", logan.F{"addr": attrs.Sender}) + } + + domainSeparator, err := api.ERC20Permit(r).DOMAINSEPARATOR(&bind.CallOpts{}) + if err != nil { + return nil, errors.Wrap(err, "failed to get domain separator") + } + + uint256Ty, _ := abi.NewType("uint256", "uint256", nil) + bytes32Ty, _ := abi.NewType("bytes32", "bytes32", nil) + addressTy, _ := abi.NewType("address", "address", nil) + + args := abi.Arguments{ + {Type: bytes32Ty}, + {Type: addressTy}, + {Type: addressTy}, + {Type: uint256Ty}, + {Type: uint256Ty}, + {Type: uint256Ty}, + } + + permitTypeHash := [32]byte{} + copy( + permitTypeHash[:], + crypto.Keccak256([]byte("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"))[:32], + ) + + packed, err := args.Pack( + permitTypeHash, + attrs.Sender, + api.Broadcaster(r).ERC20PermitTransfer, + attrs.Amount, + nonce, + attrs.Deadline, + ) + + structHash := crypto.Keccak256(packed) + + //keccak256(abi.encodePacked('x19x01', DOMAIN_SEPARATOR, hashed_args)) + hash := crypto.Keccak256( + []byte("\x19\x01"), + domainSeparator[:], + structHash, + ) + + return hash, nil +} diff --git a/internal/service/router.go b/internal/service/router.go index ca0e688..21412bd 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -3,42 +3,58 @@ package service import ( "context" - "github.com/cosmos/cosmos-sdk/types" "github.com/go-chi/chi" + "github.com/rarimo/evm-airdrop-svc/contracts" "github.com/rarimo/evm-airdrop-svc/internal/config" - "github.com/rarimo/evm-airdrop-svc/internal/service/handlers" + "github.com/rarimo/evm-airdrop-svc/internal/service/api" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/handlers" "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/logan/v3/errors" ) func Run(ctx context.Context, cfg *config.Config) { - setBech32Prefixes() r := chi.NewRouter() + erc20Permit, err := contracts.NewERC20Permit(cfg.AirdropConfig().TokenAddress, cfg.Broadcaster().RPC) + if err != nil { + panic(errors.Wrap(err, "failed to init erc20 permit transfer contract")) + } + + erc20PermitTransfer, err := contracts.NewERC20TransferWithPermit( + cfg.Broadcaster().ERC20PermitTransfer, cfg.Broadcaster().RPC, + ) + if err != nil { + panic(errors.Wrap(err, "failed to init erc20 permit transfer contract")) + } + r.Use( ape.RecoverMiddleware(cfg.Log()), ape.LoganMiddleware(cfg.Log()), ape.CtxMiddleware( - handlers.CtxLog(cfg.Log()), - handlers.CtxVerifier(cfg.Verifier().ZkVerifier), - handlers.CtxAirdropAmount(cfg.AridropConfig().Amount.String()), - handlers.CtxAirdropParams(cfg.Verifier().Params), + api.CtxLog(cfg.Log()), + api.CtxVerifier(cfg.Verifier().ZkVerifier), + api.CtxAirdropConfig(cfg.AirdropConfig()), + api.CtxAirdropParams(cfg.Verifier().Params), + api.CtxBroadcaster(cfg.Broadcaster()), + api.CtxPriceApiConfig(cfg.PriceApiConfig()), + api.CtxERC20Permit(erc20Permit), + api.CtxERC20PermitTransfer(erc20PermitTransfer), ), handlers.DBCloneMiddleware(cfg.DB()), ) - r.Route("/integrations/evm-airdrop-svc/airdrops", func(r chi.Router) { - r.Post("/", handlers.CreateAirdrop) - r.Get("/{nullifier}", handlers.GetAirdrop) - r.Get("/params", handlers.GetAirdropParams) + r.Route("/integrations/evm-airdrop-svc", func(r chi.Router) { + r.Route("/airdrops", func(r chi.Router) { + r.Post("/", handlers.CreateAirdrop) + r.Get("/{nullifier}", handlers.GetAirdrop) + r.Get("/params", handlers.GetAirdropParams) + }) + + r.Route("/transfer", func(r chi.Router) { + r.Post("/", handlers.SendTransfer) + r.Get("/", handlers.GetTransferParams) + }) }) cfg.Log().Info("Service started") ape.Serve(ctx, r, cfg, ape.ServeOpts{}) } - -func setBech32Prefixes() { - c := types.GetConfig() - c.SetBech32PrefixForAccount("rarimo", "rarimopub") - c.SetBech32PrefixForValidator("rarimovaloper", "rarimovaloperpub") - c.SetBech32PrefixForConsensusNode("rarimovalcons", "rarimovalconspub") - c.Seal() -} diff --git a/resources/model_resource_type.go b/resources/model_resource_type.go index badfc92..3c98861 100644 --- a/resources/model_resource_type.go +++ b/resources/model_resource_type.go @@ -10,4 +10,5 @@ type ResourceType string const ( AIRDROP ResourceType = "airdrop" CREATE_AIRDROP ResourceType = "create_airdrop" + TRANSFER_ERC20 ResourceType = "transfer_erc20" ) From c98e49988a91494c9afcbfa76d070b85fedca835 Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Fri, 31 May 2024 20:22:11 +0300 Subject: [PATCH 06/14] update: linter fixes, typos, optimization --- internal/config/main.go | 4 +-- internal/config/price.go | 26 +++++++++---------- internal/service/api/ctx.go | 6 ++--- .../service/api/requests/transfer_token.go | 5 +++- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/internal/config/main.go b/internal/config/main.go index 1115d3f..13f69fe 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -14,7 +14,7 @@ type Config struct { identity.VerifierProvider Broadcasterer AirdropConfiger - PriceApiConfiger + PriceAPIConfiger airdrop comfig.Once verifier comfig.Once @@ -30,6 +30,6 @@ func New(getter kv.Getter) *Config { VerifierProvider: identity.NewVerifierProvider(getter), Broadcasterer: NewBroadcaster(getter), AirdropConfiger: NewAirdropConfiger(getter), - PriceApiConfiger: NewPriceApiConfiger(getter), + PriceAPIConfiger: NewPriceApiConfiger(getter), } } diff --git a/internal/config/price.go b/internal/config/price.go index a060349..93dc62b 100644 --- a/internal/config/price.go +++ b/internal/config/price.go @@ -15,47 +15,47 @@ import ( "gitlab.com/distributed_lab/logan/v3/errors" ) -const priceApiYamlKey = "price_api" +const priceAPIYamlKey = "price_api" var ( - ErrPriceApiRequestFailed = errors.New("failed to fetch price api") + ErrPriceAPIRequestFailed = errors.New("failed to fetch price api") ErrEmptyPrice = errors.New("dollar price in ETH is empty") ) -type PriceApiConfiger interface { +type PriceAPIConfiger interface { PriceApiConfig() PriceApiConfig } type PriceApiConfig struct { URL *url.URL `fig:"url,required"` Key string `fig:"key,required"` - CurrencyId string `fig:"currency_id,required"` + CurrencyID string `fig:"currency_id,required"` QuoteTag string `fig:"quote_tag,required"` } -type priceApi struct { +type priceAPI struct { once comfig.Once getter kv.Getter } -func NewPriceApiConfiger(getter kv.Getter) PriceApiConfiger { - return &priceApi{ +func NewPriceApiConfiger(getter kv.Getter) PriceAPIConfiger { + return &priceAPI{ getter: getter, } } -func (v *priceApi) PriceApiConfig() PriceApiConfig { +func (v *priceAPI) PriceApiConfig() PriceApiConfig { return v.once.Do(func() interface{} { var result PriceApiConfig err := figure. Out(&result). With(figure.BaseHooks). - From(kv.MustGetStringMap(v.getter, priceApiYamlKey)). + From(kv.MustGetStringMap(v.getter, priceAPIYamlKey)). Please() if err != nil { panic(errors.Wrap(err, "failed to figure out config", logan.F{ - "yaml_key": priceApiYamlKey, + "yaml_key": priceAPIYamlKey, })) } @@ -84,7 +84,7 @@ func (cfg PriceApiConfig) ConvertPrice() (*big.Float, error) { URL := cfg.URL.JoinPath("/v2/cryptocurrency/quotes/latest") query := URL.Query() - query.Set("id", cfg.CurrencyId) + query.Set("id", cfg.CurrencyID) query.Set("convert", cfg.QuoteTag) URL.RawQuery = query.Encode() @@ -109,7 +109,7 @@ func (cfg PriceApiConfig) ConvertPrice() (*big.Float, error) { return nil, errors.Wrap(err, "failed to read response body") } - return nil, errors.From(ErrPriceApiRequestFailed, logan.F{ + return nil, errors.From(ErrPriceAPIRequestFailed, logan.F{ "status": response.StatusCode, "body": string(body), }) @@ -120,7 +120,7 @@ func (cfg PriceApiConfig) ConvertPrice() (*big.Float, error) { return nil, errors.Wrap(err, "failed to decode response body") } - dollarInEth := big.NewFloat(body.Data[cfg.CurrencyId].Quote[cfg.QuoteTag].Price) + dollarInEth := big.NewFloat(body.Data[cfg.CurrencyID].Quote[cfg.QuoteTag].Price) if dollarInEth.Cmp(big.NewFloat(0)) == 0 { return nil, ErrEmptyPrice } diff --git a/internal/service/api/ctx.go b/internal/service/api/ctx.go index 2da44f6..6839d02 100644 --- a/internal/service/api/ctx.go +++ b/internal/service/api/ctx.go @@ -22,7 +22,7 @@ const ( broadcasterCtxKey erc20PermitCtxKey erc20PermitTransferCtxKey - priceApiConfigCtxKey + priceAPIConfigCtxKey ) func CtxLog(entry *logan.Entry) func(context.Context) context.Context { @@ -107,10 +107,10 @@ func ERC20PermitTransfer(r *http.Request) *contracts.ERC20TransferWithPermit { func CtxPriceApiConfig(entry config.PriceApiConfig) func(context.Context) context.Context { return func(ctx context.Context) context.Context { - return context.WithValue(ctx, priceApiConfigCtxKey, entry) + return context.WithValue(ctx, priceAPIConfigCtxKey, entry) } } func PriceApiConfig(r *http.Request) config.PriceApiConfig { - return r.Context().Value(priceApiConfigCtxKey).(config.PriceApiConfig) + return r.Context().Value(priceAPIConfigCtxKey).(config.PriceApiConfig) } diff --git a/internal/service/api/requests/transfer_token.go b/internal/service/api/requests/transfer_token.go index a51e4fd..01cdf6c 100644 --- a/internal/service/api/requests/transfer_token.go +++ b/internal/service/api/requests/transfer_token.go @@ -93,7 +93,7 @@ func VerifyPermitSignature(r *http.Request, attrs resources.TransferErc20TokenAt } recoveredAddr := crypto.PubkeyToAddress(*pubKey) - if bytes.Compare(recoveredAddr.Bytes(), attrs.Sender.Bytes()) != 0 { + if !bytes.Equal(recoveredAddr.Bytes(), attrs.Sender.Bytes()) { fmt.Println(recoveredAddr.Hex()) fmt.Println(attrs.Sender.Hex()) return errors.New("recovered pubkey is invalid") @@ -140,6 +140,9 @@ func buildMessage(r *http.Request, attrs resources.TransferErc20TokenAttributes) nonce, attrs.Deadline, ) + if err != nil { + return nil, errors.Wrap(err, "failed to pack permit args") + } structHash := crypto.Keccak256(packed) From d7c6eab68dcdfd92f550766f7601e834f9bc48f1 Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Fri, 31 May 2024 20:25:39 +0300 Subject: [PATCH 07/14] update: linter typos --- internal/config/main.go | 2 +- internal/config/price.go | 14 +++++++------- internal/service/api/ctx.go | 6 +++--- .../service/api/handlers/get_transfer_params.go | 2 +- internal/service/router.go | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/internal/config/main.go b/internal/config/main.go index 13f69fe..5d60d80 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -30,6 +30,6 @@ func New(getter kv.Getter) *Config { VerifierProvider: identity.NewVerifierProvider(getter), Broadcasterer: NewBroadcaster(getter), AirdropConfiger: NewAirdropConfiger(getter), - PriceAPIConfiger: NewPriceApiConfiger(getter), + PriceAPIConfiger: NewPriceAPIConfiger(getter), } } diff --git a/internal/config/price.go b/internal/config/price.go index 93dc62b..4ce68f9 100644 --- a/internal/config/price.go +++ b/internal/config/price.go @@ -23,10 +23,10 @@ var ( ) type PriceAPIConfiger interface { - PriceApiConfig() PriceApiConfig + PriceAPIConfig() PriceAPIConfig } -type PriceApiConfig struct { +type PriceAPIConfig struct { URL *url.URL `fig:"url,required"` Key string `fig:"key,required"` CurrencyID string `fig:"currency_id,required"` @@ -38,15 +38,15 @@ type priceAPI struct { getter kv.Getter } -func NewPriceApiConfiger(getter kv.Getter) PriceAPIConfiger { +func NewPriceAPIConfiger(getter kv.Getter) PriceAPIConfiger { return &priceAPI{ getter: getter, } } -func (v *priceAPI) PriceApiConfig() PriceApiConfig { +func (v *priceAPI) PriceAPIConfig() PriceAPIConfig { return v.once.Do(func() interface{} { - var result PriceApiConfig + var result PriceAPIConfig err := figure. Out(&result). @@ -60,7 +60,7 @@ func (v *priceAPI) PriceApiConfig() PriceApiConfig { } return result - }).(PriceApiConfig) + }).(PriceAPIConfig) } type QuoteResponse struct { @@ -80,7 +80,7 @@ type Quote struct { } // ConvertPrice converts tokens price -func (cfg PriceApiConfig) ConvertPrice() (*big.Float, error) { +func (cfg PriceAPIConfig) ConvertPrice() (*big.Float, error) { URL := cfg.URL.JoinPath("/v2/cryptocurrency/quotes/latest") query := URL.Query() diff --git a/internal/service/api/ctx.go b/internal/service/api/ctx.go index 6839d02..d9b28fe 100644 --- a/internal/service/api/ctx.go +++ b/internal/service/api/ctx.go @@ -105,12 +105,12 @@ func ERC20PermitTransfer(r *http.Request) *contracts.ERC20TransferWithPermit { return r.Context().Value(erc20PermitTransferCtxKey).(*contracts.ERC20TransferWithPermit) } -func CtxPriceApiConfig(entry config.PriceApiConfig) func(context.Context) context.Context { +func CtxPriceAPIConfig(entry config.PriceAPIConfig) func(context.Context) context.Context { return func(ctx context.Context) context.Context { return context.WithValue(ctx, priceAPIConfigCtxKey, entry) } } -func PriceApiConfig(r *http.Request) config.PriceApiConfig { - return r.Context().Value(priceAPIConfigCtxKey).(config.PriceApiConfig) +func PriceAPIConfig(r *http.Request) config.PriceAPIConfig { + return r.Context().Value(priceAPIConfigCtxKey).(config.PriceAPIConfig) } diff --git a/internal/service/api/handlers/get_transfer_params.go b/internal/service/api/handlers/get_transfer_params.go index 6ce0393..f0b81d2 100644 --- a/internal/service/api/handlers/get_transfer_params.go +++ b/internal/service/api/handlers/get_transfer_params.go @@ -132,7 +132,7 @@ func MakeTransferWithPermitTx( } func buildFeeTransferAmount(r *http.Request, gweiGasPrice *big.Int, gasLimit uint64) (*big.Int, error) { - dollarInEth, err := api.PriceApiConfig(r).ConvertPrice() + dollarInEth, err := api.PriceAPIConfig(r).ConvertPrice() if err != nil { return nil, errors.Wrap(err, "failed to convert dollar price in eth") } diff --git a/internal/service/router.go b/internal/service/router.go index 21412bd..49e84f9 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -36,7 +36,7 @@ func Run(ctx context.Context, cfg *config.Config) { api.CtxAirdropConfig(cfg.AirdropConfig()), api.CtxAirdropParams(cfg.Verifier().Params), api.CtxBroadcaster(cfg.Broadcaster()), - api.CtxPriceApiConfig(cfg.PriceApiConfig()), + api.CtxPriceAPIConfig(cfg.PriceAPIConfig()), api.CtxERC20Permit(erc20Permit), api.CtxERC20PermitTransfer(erc20PermitTransfer), ), From 2be4a12a65d0bf961a4b1a9d5c3ab105da610609 Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Fri, 31 May 2024 20:27:56 +0300 Subject: [PATCH 08/14] fix: close body; update: naming --- internal/config/price.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/config/price.go b/internal/config/price.go index 4ce68f9..1521504 100644 --- a/internal/config/price.go +++ b/internal/config/price.go @@ -68,7 +68,7 @@ type QuoteResponse struct { } type Currency struct { - Id int `json:"id"` + ID int `json:"id"` Name string `json:"name"` Symbol string `json:"symbol"` Quote map[string]Quote `json:"quote"` @@ -102,6 +102,7 @@ func (cfg PriceAPIConfig) ConvertPrice() (*big.Float, error) { if err != nil { return nil, errors.Wrap(err, "failed to do request") } + defer response.Body.Close() if response.StatusCode != http.StatusOK { body, err := io.ReadAll(response.Body) From d6edbd6522dde0b12570c4ca1916b196fb23a2e6 Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Tue, 4 Jun 2024 15:43:26 +0300 Subject: [PATCH 09/14] update: take decimals part from the contract and multiple with amount --- config.yaml | 2 +- .../service/api/handlers/create_airdrop.go | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/config.yaml b/config.yaml index 8d6cccc..340c229 100644 --- a/config.yaml +++ b/config.yaml @@ -9,7 +9,7 @@ listener: addr: :8000 airdrop: - amount: amount + amount: amount # amount in natural numbers (1, 2, 10 etc.) decimals part is taken directly from the contract token_address: erc20_token_address broadcaster: diff --git a/internal/service/api/handlers/create_airdrop.go b/internal/service/api/handlers/create_airdrop.go index 992e3f1..692c0f7 100644 --- a/internal/service/api/handlers/create_airdrop.go +++ b/internal/service/api/handlers/create_airdrop.go @@ -1,9 +1,12 @@ package handlers import ( - "errors" + stdErrors "errors" + "math/big" "net/http" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common/math" "github.com/rarimo/evm-airdrop-svc/internal/data" "github.com/rarimo/evm-airdrop-svc/internal/service/api" "github.com/rarimo/evm-airdrop-svc/internal/service/api/models" @@ -12,6 +15,7 @@ import ( "github.com/rarimo/zkverifier-kit/identity" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" + "gitlab.com/distributed_lab/logan/v3" ) // Full list of the OpenSSL signature algorithms and hash-functions is provided here: @@ -42,7 +46,7 @@ func CreateAirdrop(w http.ResponseWriter, r *http.Request) { err = api.Verifier(r).VerifyProof(req.Data.Attributes.ZkProof, zk.WithEthereumAddress(req.Data.Attributes.Address)) if err != nil { - if errors.Is(err, identity.ErrContractCall) { + if stdErrors.Is(err, identity.ErrContractCall) { api.Log(r).WithError(err).Error("Failed to verify proof") ape.RenderErr(w, problems.InternalError()) return @@ -53,10 +57,19 @@ func CreateAirdrop(w http.ResponseWriter, r *http.Request) { return } + tokenDecimals, err := api.ERC20Permit(r).Decimals(&bind.CallOpts{}) + if err != nil { + api.Log(r).WithError(err).WithFields(logan.F{ + "address": api.AirdropConfig(r).TokenAddress, + }).Error("failed to get token decimals") + ape.RenderErr(w, problems.InternalError()) + return + } + airdrop, err = api.AirdropsQ(r).Insert(data.Airdrop{ Nullifier: nullifier, Address: req.Data.Attributes.Address, - Amount: api.AirdropConfig(r).Amount.String(), + Amount: new(big.Int).Mul(api.AirdropConfig(r).Amount, math.BigPow(10, int64(tokenDecimals))).String(), Status: data.TxStatusPending, }) if err != nil { From b15f39834812cb3472c7262394d71940ace2bf0a Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Thu, 6 Jun 2024 12:04:23 +0300 Subject: [PATCH 10/14] add: models for permit hash --- resources/model_build_permit_hash.go | 43 +++++++++++++++++++ .../model_build_permit_hash_attributes.go | 20 +++++++++ resources/model_permit_hash.go | 43 +++++++++++++++++++ resources/model_permit_hash_attributes.go | 10 +++++ 4 files changed, 116 insertions(+) create mode 100644 resources/model_build_permit_hash.go create mode 100644 resources/model_build_permit_hash_attributes.go create mode 100644 resources/model_permit_hash.go create mode 100644 resources/model_permit_hash_attributes.go diff --git a/resources/model_build_permit_hash.go b/resources/model_build_permit_hash.go new file mode 100644 index 0000000..6530583 --- /dev/null +++ b/resources/model_build_permit_hash.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type BuildPermitHash struct { + Key + Attributes BuildPermitHashAttributes `json:"attributes"` +} +type BuildPermitHashRequest struct { + Data BuildPermitHash `json:"data"` + Included Included `json:"included"` +} + +type BuildPermitHashListRequest struct { + Data []BuildPermitHash `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *BuildPermitHashListRequest) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *BuildPermitHashListRequest) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustBuildPermitHash - returns BuildPermitHash from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustBuildPermitHash(key Key) *BuildPermitHash { + var buildPermitHash BuildPermitHash + if c.tryFindEntry(key, &buildPermitHash) { + return &buildPermitHash + } + return nil +} diff --git a/resources/model_build_permit_hash_attributes.go b/resources/model_build_permit_hash_attributes.go new file mode 100644 index 0000000..7dba9cb --- /dev/null +++ b/resources/model_build_permit_hash_attributes.go @@ -0,0 +1,20 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +type BuildPermitHashAttributes struct { + // Transferred amount of tokens. + Amount *big.Int `json:"amount"` + // UNIX UTC timestamp in the future till which permit signature may be used. + Deadline *big.Int `json:"deadline"` + // EVM address FROM which tokens are transferred. + Sender common.Address `json:"sender"` +} diff --git a/resources/model_permit_hash.go b/resources/model_permit_hash.go new file mode 100644 index 0000000..10f5826 --- /dev/null +++ b/resources/model_permit_hash.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type PermitHash struct { + Key + Attributes PermitHashAttributes `json:"attributes"` +} +type PermitHashResponse struct { + Data PermitHash `json:"data"` + Included Included `json:"included"` +} + +type PermitHashListResponse struct { + Data []PermitHash `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *PermitHashListResponse) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *PermitHashListResponse) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustPermitHash - returns PermitHash from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustPermitHash(key Key) *PermitHash { + var permitHash PermitHash + if c.tryFindEntry(key, &permitHash) { + return &permitHash + } + return nil +} diff --git a/resources/model_permit_hash_attributes.go b/resources/model_permit_hash_attributes.go new file mode 100644 index 0000000..3b3ffda --- /dev/null +++ b/resources/model_permit_hash_attributes.go @@ -0,0 +1,10 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type PermitHashAttributes struct { + // Permit message hash built by ERC-2612 standard that has to be signed by token owner. + Hash string `json:"hash"` +} From 8d96dcfb039f80026636df0972a6ac89f1137e25 Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Thu, 6 Jun 2024 12:12:08 +0300 Subject: [PATCH 11/14] add: permit hash yaml docs --- .../components/schemas/BuildPermitHash.yaml | 29 +++++++++++++++++++ docs/spec/components/schemas/PermitHash.yaml | 15 ++++++++++ 2 files changed, 44 insertions(+) create mode 100644 docs/spec/components/schemas/BuildPermitHash.yaml create mode 100644 docs/spec/components/schemas/PermitHash.yaml diff --git a/docs/spec/components/schemas/BuildPermitHash.yaml b/docs/spec/components/schemas/BuildPermitHash.yaml new file mode 100644 index 0000000..eae18e8 --- /dev/null +++ b/docs/spec/components/schemas/BuildPermitHash.yaml @@ -0,0 +1,29 @@ +allOf: + - $ref: '#/components/schemas/TransferKey' + - type: object + x-go-is-request: true + required: + - attributes + properties: + attributes: + type: object + required: + - sender + - amount + - deadline + properties: + sender: + type: string + format: common.Address + description: EVM address FROM which tokens are transferred. + example: "0x9E65b5Fac5aD50B7daf51a0F8D8234Cd5658ef17" + amount: + type: integer + format: "*big.Int" + description: Transferred amount of tokens. + example: 8 + deadline: + type: integer + format: "*big.Int" + description: UNIX UTC timestamp in the future till which permit signature may be used. + example: 1717015161 diff --git a/docs/spec/components/schemas/PermitHash.yaml b/docs/spec/components/schemas/PermitHash.yaml new file mode 100644 index 0000000..900133c --- /dev/null +++ b/docs/spec/components/schemas/PermitHash.yaml @@ -0,0 +1,15 @@ +allOf: + - $ref: '#/components/schemas/TransferKey' + - type: object + required: + - attributes + properties: + attributes: + type: object + required: + - hash + properties: + hash: + type: string + description: Permit message hash built by ERC-2612 standard that has to be signed by token owner. + example: "0x3f77218a74501051ac9f069e73523519e6a6cf34783811515da5a178e86634ca" From 67a9784cf76a99cfe45b5512be78daacc9ae37e1 Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Thu, 6 Jun 2024 12:15:47 +0300 Subject: [PATCH 12/14] add: building permit hash endpoint --- .../service/api/handlers/build_permit_hash.go | 107 ++++++++++++++++++ internal/service/api/models/permit.go | 16 +++ .../service/api/requests/build_permit_hash.go | 29 +++++ internal/service/router.go | 3 + 4 files changed, 155 insertions(+) create mode 100644 internal/service/api/handlers/build_permit_hash.go create mode 100644 internal/service/api/models/permit.go create mode 100644 internal/service/api/requests/build_permit_hash.go diff --git a/internal/service/api/handlers/build_permit_hash.go b/internal/service/api/handlers/build_permit_hash.go new file mode 100644 index 0000000..20e00f4 --- /dev/null +++ b/internal/service/api/handlers/build_permit_hash.go @@ -0,0 +1,107 @@ +package handlers + +import ( + "math/big" + "net/http" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/rarimo/evm-airdrop-svc/internal/service/api" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/models" + "github.com/rarimo/evm-airdrop-svc/internal/service/api/requests" + "github.com/rarimo/evm-airdrop-svc/resources" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" + "gitlab.com/distributed_lab/logan/v3" + "gitlab.com/distributed_lab/logan/v3/errors" +) + +func BuildPermitHash(w http.ResponseWriter, r *http.Request) { + req, err := requests.NewBuildPermitHashRequest(r) + if err != nil { + api.Log(r).WithError(err).Error("failed to parse request") + ape.RenderErr(w, problems.BadRequest(err)...) + return + } + + nonce, err := api.ERC20Permit(r).Nonces(&bind.CallOpts{}, req.Data.Attributes.Sender) + if err != nil { + api.Log(r).WithFields(logan.F{ + "sender": req.Data.Attributes.Sender, + }).WithError(err).Error("failed to get nonce") + ape.RenderErr(w, problems.InternalError()) + return + } + + domainSeparator, err := api.ERC20Permit(r).DOMAINSEPARATOR(&bind.CallOpts{}) + if err != nil { + api.Log(r).WithError(err).Error("failed to get domain separator") + ape.RenderErr(w, problems.InternalError()) + return + } + + rawMsgHash, err := buildMessageHash( + nonce, + api.Broadcaster(r).ERC20PermitTransfer, + domainSeparator, + req.Data.Attributes, + ) + if err != nil { + api.Log(r).WithError(err).Error("failed to get build permit message hash") + ape.RenderErr(w, problems.InternalError()) + return + } + + ape.Render(w, models.NewPermitHashResponse(hexutil.Encode(rawMsgHash))) +} + +func buildMessageHash( + nonce *big.Int, + spender common.Address, + domainSeparator [32]byte, + attr resources.BuildPermitHashAttributes, +) ([]byte, error) { + uint256Ty, _ := abi.NewType("uint256", "uint256", nil) + bytes32Ty, _ := abi.NewType("bytes32", "bytes32", nil) + addressTy, _ := abi.NewType("address", "address", nil) + + args := abi.Arguments{ + {Type: bytes32Ty}, + {Type: addressTy}, + {Type: addressTy}, + {Type: uint256Ty}, + {Type: uint256Ty}, + {Type: uint256Ty}, + } + + rawPermitTypeHash := crypto.Keccak256([]byte("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")) + permitTypeHash := [32]byte{} + copy(permitTypeHash[:], rawPermitTypeHash[:32]) + + //abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline) + packed, err := args.Pack( + permitTypeHash, + attr.Sender, + spender, + attr.Amount, + nonce, + attr.Deadline, + ) + if err != nil { + return nil, errors.Wrap(err, "failed to pack permit signature") + } + + structHash := crypto.Keccak256(packed) + + //keccak256(abi.encodePacked('x19x01', DOMAIN_SEPARATOR, hashed_args)) + msgHash := crypto.Keccak256( + []byte("\x19\x01"), + domainSeparator[:], + structHash, + ) + + return msgHash, nil +} diff --git a/internal/service/api/models/permit.go b/internal/service/api/models/permit.go new file mode 100644 index 0000000..a08b0fd --- /dev/null +++ b/internal/service/api/models/permit.go @@ -0,0 +1,16 @@ +package models + +import "github.com/rarimo/evm-airdrop-svc/resources" + +func NewPermitHashResponse(hash string) resources.PermitHashResponse { + return resources.PermitHashResponse{ + Data: resources.PermitHash{ + Key: resources.Key{ + Type: resources.TRANSFER_ERC20, + }, + Attributes: resources.PermitHashAttributes{ + Hash: hash, + }, + }, + } +} diff --git a/internal/service/api/requests/build_permit_hash.go b/internal/service/api/requests/build_permit_hash.go new file mode 100644 index 0000000..5da791f --- /dev/null +++ b/internal/service/api/requests/build_permit_hash.go @@ -0,0 +1,29 @@ +package requests + +import ( + "encoding/json" + "net/http" + + val "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/evm-airdrop-svc/resources" +) + +func NewBuildPermitHashRequest(r *http.Request) (req resources.BuildPermitHashRequest, err error) { + if err = json.NewDecoder(r.Body).Decode(&req); err != nil { + return req, newDecodeError("body", err) + } + + attr := req.Data.Attributes + + err = val.Errors{ + "data/type": val.Validate(req.Data.Type, val.Required, val.In(resources.TRANSFER_ERC20)), + "data/attributes/sender": val.Validate(attr.Sender.String(), val.Required, val.Match(ethAddrRegExp)), + "data/attributes/amount": val.Validate(attr.Amount.Int64(), val.Required, val.Min(0)), + "data/attributes/deadline": val.Validate(attr.Deadline.Int64(), val.Required, val.By(UnixTimestampRule)), + }.Filter() + if err != nil { + return req, err + } + + return req, nil +} diff --git a/internal/service/router.go b/internal/service/router.go index 49e84f9..4ef8e15 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -42,6 +42,7 @@ func Run(ctx context.Context, cfg *config.Config) { ), handlers.DBCloneMiddleware(cfg.DB()), ) + r.Route("/integrations/evm-airdrop-svc", func(r chi.Router) { r.Route("/airdrops", func(r chi.Router) { r.Post("/", handlers.CreateAirdrop) @@ -52,6 +53,8 @@ func Run(ctx context.Context, cfg *config.Config) { r.Route("/transfer", func(r chi.Router) { r.Post("/", handlers.SendTransfer) r.Get("/", handlers.GetTransferParams) + + r.Post("/permit-hash", handlers.BuildPermitHash) }) }) From 9641ac2bc1db63bd29ee9c31a09819b74f7d44b9 Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Thu, 6 Jun 2024 12:16:35 +0300 Subject: [PATCH 13/14] remove: redundant amount multiplication --- internal/service/api/requests/transfer_token.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/internal/service/api/requests/transfer_token.go b/internal/service/api/requests/transfer_token.go index 01cdf6c..096cd66 100644 --- a/internal/service/api/requests/transfer_token.go +++ b/internal/service/api/requests/transfer_token.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "fmt" - "math/big" "net/http" "regexp" "time" @@ -12,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" val "github.com/go-ozzo/ozzo-validation/v4" "github.com/rarimo/evm-airdrop-svc/internal/service/api" @@ -44,17 +42,12 @@ func NewTransferERC20Token(r *http.Request) (req resources.TransferErc20TokenReq return req, err } - decimals := math.BigPow(1, 18) - attr.Amount = new(big.Int).Mul(req.Data.Attributes.Amount, decimals) - if err = VerifyPermitSignature(r, attr); err != nil { return req, val.Errors{ "signature": errors.Wrap(err, "invalid permit signature"), } } - req.Data.Attributes.Amount = new(big.Int).Mul(req.Data.Attributes.Amount, decimals) - return req, nil } From 86653cbbc375b29f1e661ff5dc912e966f7c6e4a Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Thu, 6 Jun 2024 14:11:28 +0300 Subject: [PATCH 14/14] add: path docs for building permit hash --- ...@evm-airdrop-svc@transfer@permit-hash.yaml | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 docs/spec/paths/integrations@evm-airdrop-svc@transfer@permit-hash.yaml diff --git a/docs/spec/paths/integrations@evm-airdrop-svc@transfer@permit-hash.yaml b/docs/spec/paths/integrations@evm-airdrop-svc@transfer@permit-hash.yaml new file mode 100644 index 0000000..f86bccf --- /dev/null +++ b/docs/spec/paths/integrations@evm-airdrop-svc@transfer@permit-hash.yaml @@ -0,0 +1,67 @@ +post: + tags: + - Transfer + summary: Build Permit hash + description: "Endpoint that build message hash for permit transfer, that has to be signer by token owner to permit + transfer. This message is built according to the ERC-2612 standard." + operationId: SendTransfer + requestBody: + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BuildPermitHash' + responses: + 200: + description: Created permit hash + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/PermitHash' + 400: + $ref: '#/components/responses/invalidParameter' + 500: + $ref: '#/components/responses/internalError' + +get: + tags: + - Transfer + summary: Get transfer params + description: "Returns ERC20 transfer with multicall parameters. Takes all requried parameters for permit and transfer, + simulates transaction and returns the calculated values" + operationId: GetTransferParams + requestBody: + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/TransferERC20Token' + responses: + 200: + description: Transaction was done successfully, all parameters were calculated. + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Estimate' + 400: + $ref: '#/components/responses/invalidParameter' + 500: + $ref: '#/components/responses/internalError'