diff --git a/Makefile b/Makefile index 00fb2d5..5981d51 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,10 @@ generate-contracts: cd scripts/generate-contracts && ./execute.sh && cd ../.. run-tests-on-eth-based-chain: - go test -v -skip='^.*_NonEthBasedChain_.*$\' ./test ./utils + go test -v -skip='^.*_NonEthBasedChain_.*$\' ./test ./accounts ./utils run-tests-on-non-eth-based-chain: - go test -v -skip='^.*_EthBasedChain_.*$\' ./test ./utils + go test -v -skip='^.*_EthBasedChain_.*$\' ./test ./accounts ./utils check-format: cd scripts/ && ./check-format.sh && cd ../.. diff --git a/accounts/signer.go b/accounts/signer.go index 934492b..807103e 100644 --- a/accounts/signer.go +++ b/accounts/signer.go @@ -134,6 +134,8 @@ func (s *BaseSigner) SignTypedData(domain *eip712.Domain, data eip712.TypedData) if err != nil { return nil, fmt.Errorf("failed to sign hash of typed data: %w", err) } + // crypto.Sign uses the traditional implementation where v is either 0 or 1, + // while Ethereum uses newer implementation where v is either 27 or 28. if sig[64] < 27 { sig[64] += 27 } diff --git a/accounts/smart_account.go b/accounts/smart_account.go new file mode 100644 index 0000000..d5959af --- /dev/null +++ b/accounts/smart_account.go @@ -0,0 +1,378 @@ +package accounts + +import ( + "context" + "errors" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/signer/core/apitypes" + "github.com/zksync-sdk/zksync2-go/clients" + "github.com/zksync-sdk/zksync2-go/contracts/erc20" + "github.com/zksync-sdk/zksync2-go/contracts/ethtoken" + "github.com/zksync-sdk/zksync2-go/contracts/l2bridge" + "github.com/zksync-sdk/zksync2-go/contracts/nonceholder" + "github.com/zksync-sdk/zksync2-go/eip712" + zkTypes "github.com/zksync-sdk/zksync2-go/types" + "github.com/zksync-sdk/zksync2-go/utils" + "math/big" +) + +// SmartAccount is a signer which can be configured to sign various payloads using a provided secret. +// The secret can be in any form, allowing for flexibility when working with different account implementations. +// The SmartAccount is bound to a specific address and provides the ability to define custom method for populating transactions +// and custom signing method used for signing messages, typed data, and transactions. +type SmartAccount struct { + address common.Address + secret interface{} + client *clients.BaseClient + payloadSigner PayloadSigner + transactionBuilder TransactionBuilder + + baseToken common.Address + sharedL2BridgeAddress common.Address + chainId *big.Int +} + +// NewSmartAccount creates a new SmartAccount instance. +// By default, it uses SignPayloadWithECDSA as a signer and PopulateTransactionECDSA as a builder +// and requires private key in hex format to be provided. +func NewSmartAccount( + address common.Address, + secret interface{}, + signer *PayloadSigner, + builder *TransactionBuilder, + client *clients.BaseClient) *SmartAccount { + if signer == nil { + signer = &SignPayloadWithECDSA + } + if builder == nil { + builder = &PopulateTransactionECDSA + } + + return &SmartAccount{ + address: address, + secret: secret, + client: client, + payloadSigner: *signer, + transactionBuilder: *builder, + } +} + +// Connect creates a new instance of SmartAccount connected to a client or +// detached from any provider if nil is provided. +func (a *SmartAccount) Connect(client *clients.BaseClient) *SmartAccount { + return NewSmartAccount( + a.address, + a.secret, + &a.payloadSigner, + &a.transactionBuilder, + client) +} + +// Address returns the address of the associated account. +func (a *SmartAccount) Address() common.Address { + return a.address +} + +// Balance returns the balance of the specified token that can be either ETH or any ERC20 token. +// The block number can be nil, in which case the balance is taken from the latest known block. +func (a *SmartAccount) Balance(ctx context.Context, token common.Address, at *big.Int) (*big.Int, error) { + err := a.cacheData(ctx) + if err != nil { + return nil, err + } + if token == utils.LegacyEthAddress || token == a.baseToken { + return a.client.BalanceAt(ensureContext(ctx), a.Address(), at) + } + erc20Token, err := erc20.NewIERC20(token, a.client) + if err != nil { + return nil, err + } + return erc20Token.BalanceOf(&bind.CallOpts{ + From: a.Address(), + BlockNumber: at, + Context: ensureContext(ctx), + }, a.Address()) +} + +// AllBalances returns all balances for confirmed tokens given by an associated account. +func (a *SmartAccount) AllBalances(ctx context.Context) (map[common.Address]*big.Int, error) { + return a.client.AllAccountBalances(ensureContext(ctx), a.Address()) +} + +// Nonce returns the account nonce of the associated account. +// The block number can be nil, in which case the nonce is taken from the latest known block. +func (a *SmartAccount) Nonce(ctx context.Context, blockNumber *big.Int) (uint64, error) { + return a.client.NonceAt(ctx, a.Address(), blockNumber) +} + +// DeploymentNonce returns the deployment nonce of the account. +func (a *SmartAccount) DeploymentNonce(opts *CallOpts) (*big.Int, error) { + callOpts := ensureCallOpts(opts).ToCallOpts(a.Address()) + nonceHolder, err := nonceholder.NewINonceHolder(utils.NonceHolderAddress, a.client) + if err != nil { + return nil, err + } + return nonceHolder.GetDeploymentNonce(callOpts, a.Address()) +} + +// PopulateTransaction populates the transaction tx using the provided TransactionBuilder function. +// If tx.From is not set, it sets the value from the Address method which can +// be utilized in the TransactionBuilder function. +func (a *SmartAccount) PopulateTransaction(ctx context.Context, tx *zkTypes.Transaction712) error { + if tx.From == nil { + from := a.Address() + tx.From = &from + } + return a.transactionBuilder(ensureContext(ctx), tx, a.secret, a.client) +} + +// SignTransaction returns a signed transaction that is ready to be broadcast to +// the network. The PopulateTransaction method is called first to ensure that all +// necessary properties for the transaction to be valid have been populated. +func (a *SmartAccount) SignTransaction(ctx context.Context, tx *zkTypes.Transaction712) ([]byte, error) { + err := a.cacheData(ensureContext(ctx)) + if err != nil { + return nil, err + } + + err = a.PopulateTransaction(ensureContext(ctx), tx) + if err != nil { + return nil, err + } + + domain := eip712.ZkSyncEraEIP712Domain(a.chainId.Int64()) + + eip712Msg, err := tx.EIP712Message() + if err != nil { + return nil, err + } + + signature, err := a.SignTypedData(ctx, apitypes.TypedData{ + Types: apitypes.Types{ + tx.EIP712Type(): tx.EIP712Types(), + domain.EIP712Type(): domain.EIP712Types(), + }, + PrimaryType: tx.EIP712Type(), + Domain: domain.EIP712Domain(), + Message: eip712Msg, + }) + if err != nil { + return nil, err + } + return tx.RLPValues(signature) +} + +// SendTransaction injects a transaction into the pending pool for execution. +// The SignTransaction is called first to ensure transaction is properly signed. +func (a *SmartAccount) SendTransaction(ctx context.Context, tx *zkTypes.Transaction712) (common.Hash, error) { + rawTx, err := a.SignTransaction(ensureContext(ctx), tx) + if err != nil { + return common.Hash{}, err + } + return a.client.SendRawTransaction(context.Background(), rawTx) +} + +// SignMessage signs a message using the provided PayloadSigner function. +func (a *SmartAccount) SignMessage(ctx context.Context, message []byte) ([]byte, error) { + return a.payloadSigner(ensureContext(ctx), accounts.TextHash(message), a.secret, a.client) +} + +// SignTypedData signs a typed data using the provided PayloadSigner function. +func (a *SmartAccount) SignTypedData(ctx context.Context, typedData apitypes.TypedData) ([]byte, error) { + hash, _, err := apitypes.TypedDataAndHash(typedData) + if err != nil { + return nil, err + } + signature, err := a.payloadSigner(ctx, hash, a.secret, a.client) + if err != nil { + return nil, err + } + return signature, nil +} + +// Withdraw initiates the withdrawal process which withdraws ETH or any ERC20 +// token from the associated account on L2 network to the target account on L1 +// network. +func (a *SmartAccount) Withdraw(auth *TransactOpts, tx WithdrawalTransaction) (common.Hash, error) { + from := a.Address() + + opts := ensureTransactOpts(auth) + a.insertGasPrice(opts) + err := a.cacheData(opts.Context) + if err != nil { + return common.Hash{}, err + } + + if tx.Token == utils.LegacyEthAddress { + tx.Token = utils.EthAddressInContracts + if opts.Value != nil && opts.Value != tx.Amount { + return common.Hash{}, errors.New("the tx.value is not equal to the value withdrawn") + } else { + opts.Value = tx.Amount + } + + abi, abiErr := ethtoken.IEthTokenMetaData.GetAbi() + if abiErr != nil { + return common.Hash{}, abiErr + } + + data, packErr := abi.Pack("withdraw", tx.To) + if packErr != nil { + return common.Hash{}, packErr + } + + return a.SendTransaction(opts.Context, &zkTypes.Transaction712{ + Nonce: opts.Nonce, + GasTipCap: opts.GasTipCap, + GasFeeCap: opts.GasFeeCap, + Gas: new(big.Int).SetUint64(opts.GasLimit), + To: &utils.L2BaseTokenAddress, + Value: opts.Value, + Data: data, + From: &from, + ChainID: a.chainId, + Meta: &zkTypes.Eip712Meta{ + GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()), + PaymasterParams: tx.PaymasterParams, + }, + }) + } + + if tx.BridgeAddress == nil { + tx.BridgeAddress = &a.sharedL2BridgeAddress + } + + abi, abiErr := l2bridge.IL2BridgeMetaData.GetAbi() + if abiErr != nil { + return common.Hash{}, abiErr + } + + data, abiPack := abi.Pack("withdraw", tx.To, tx.Token, tx.Amount) + if abiPack != nil { + return common.Hash{}, abiPack + } + + return a.SendTransaction(opts.Context, &zkTypes.Transaction712{ + Nonce: opts.Nonce, + GasTipCap: opts.GasTipCap, + GasFeeCap: opts.GasFeeCap, + Gas: new(big.Int).SetUint64(opts.GasLimit), + To: tx.BridgeAddress, + Value: opts.Value, + Data: data, + ChainID: a.chainId, + From: &from, + Meta: &zkTypes.Eip712Meta{ + GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()), + PaymasterParams: tx.PaymasterParams, + }, + }) +} + +// Transfer moves the ETH or any ERC20 token from the associated account to the target account. +func (a *SmartAccount) Transfer(auth *TransactOpts, tx TransferTransaction) (common.Hash, error) { + from := a.Address() + + opts := ensureTransactOpts(auth) + a.insertGasPrice(opts) + err := a.cacheData(opts.Context) + if err != nil { + return common.Hash{}, err + } + + if isBaseToken, baseTokenErr := a.isBaseToken(opts.Context, tx.Token); tx.Token == utils.LegacyEthAddress || isBaseToken { + return a.SendTransaction(opts.Context, &zkTypes.Transaction712{ + Nonce: opts.Nonce, + GasTipCap: opts.GasTipCap, + GasFeeCap: opts.GasFeeCap, + Gas: new(big.Int).SetUint64(opts.GasLimit), + To: &tx.To, + Value: tx.Amount, + ChainID: a.chainId, + From: &from, + Meta: &zkTypes.Eip712Meta{ + GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()), + PaymasterParams: tx.PaymasterParams, + }, + }) + } else if baseTokenErr != nil { + return common.Hash{}, baseTokenErr + } + + abi, err := erc20.IERC20MetaData.GetAbi() + if err != nil { + return common.Hash{}, err + } + + data, err := abi.Pack("transfer", tx.To, tx.Amount) + if err != nil { + return common.Hash{}, err + } + + return a.SendTransaction(opts.Context, &zkTypes.Transaction712{ + Nonce: opts.Nonce, + GasTipCap: opts.GasTipCap, + GasFeeCap: opts.GasFeeCap, + Gas: new(big.Int).SetUint64(opts.GasLimit), + To: &tx.Token, + Value: big.NewInt(0), + Data: data, + ChainID: a.chainId, + From: &from, + Meta: &zkTypes.Eip712Meta{ + GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()), + PaymasterParams: tx.PaymasterParams, + }, + }) +} + +func (a *SmartAccount) cacheData(ctx context.Context) error { + var err error + if a.chainId == nil { + a.chainId, err = a.client.ChainID(ensureContext(ctx)) + if err != nil { + return err + } + } + + if a.baseToken == (common.Address{}) { + a.baseToken, err = a.client.BaseTokenContractAddress(ctx) + if err != nil { + return err + } + } + + if a.sharedL2BridgeAddress == (common.Address{}) { + bridges, bridgeErr := a.client.BridgeContracts(ctx) + if err != nil { + return bridgeErr + } + a.sharedL2BridgeAddress = bridges.L2SharedBridge + } + return nil +} + +func (a *SmartAccount) insertGasPrice(opts *TransactOpts) { + if opts.GasPrice != nil { + opts.GasFeeCap = opts.GasPrice + opts.GasTipCap = nil + opts.GasPrice = nil + } +} + +func (a *SmartAccount) isBaseToken(ctx context.Context, token common.Address) (bool, error) { + return a.client.IsBaseToken(ensureContext(ctx), token) +} + +// NewECDSASmartAccount creates a SmartAccount instance that uses single ECDSA key for signing payload. +func NewECDSASmartAccount(address common.Address, privateKey string, client *clients.BaseClient) *SmartAccount { + return NewSmartAccount(address, privateKey, &SignPayloadWithECDSA, &PopulateTransactionECDSA, client) +} + +// NewMultisigECDSASmartAccount creates a SmartAccount instance that uses multiple ECDSA keys for signing payloads. +// The signature is generated by concatenating signatures created by signing with each key individually. +func NewMultisigECDSASmartAccount(address common.Address, privateKeys []string, client *clients.BaseClient) *SmartAccount { + return NewSmartAccount(address, privateKeys, &SignPayloadWithMultipleECDSA, &PopulateTransactionMultipleECDSA, client) +} diff --git a/accounts/smart_account_utils.go b/accounts/smart_account_utils.go new file mode 100644 index 0000000..e2bdc4d --- /dev/null +++ b/accounts/smart_account_utils.go @@ -0,0 +1,169 @@ +package accounts + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/zksync-sdk/zksync2-go/clients" + zkTypes "github.com/zksync-sdk/zksync2-go/types" + "github.com/zksync-sdk/zksync2-go/utils" + "math/big" +) + +// SignPayloadWithECDSA signs the payload using an ECDSA private key. +var SignPayloadWithECDSA PayloadSigner = func(ctx context.Context, payload []byte, secret interface{}, client *clients.BaseClient) ([]byte, error) { + privateKeyHex, ok := (secret).(string) + if !ok { + return nil, errors.New("secret should be hex of ECDSA private key") + } + privateKey, err := crypto.HexToECDSA(privateKeyHex) + if err != nil { + return nil, err + } + signature, err := crypto.Sign(payload, privateKey) + if err != nil { + return nil, err + } + // crypto.Sign uses the traditional implementation where v is either 0 or 1, + // while Ethereum uses newer implementation where v is either 27 or 28. + if signature[64] < 27 { + signature[64] += 27 + } + return signature, nil +} + +// SignPayloadWithMultipleECDSA signs the payload using multiple ECDSA private keys. +// The signature is generated by concatenating signatures created by signing with each key individually. +// The length of the resulting signature is len(secret) * 65. +var SignPayloadWithMultipleECDSA PayloadSigner = func(ctx context.Context, payload []byte, secret interface{}, client *clients.BaseClient) ([]byte, error) { + privateKeys, ok := (secret).([]string) + if !ok { + return nil, errors.New("secret should be a slice of ECDSA private keys") + } + if len(privateKeys) < 2 { + return nil, errors.New("secret should be a slice of ECDSA private keys") + } + multiSig := make([]byte, len(privateKeys)*65) + for i, privateKeyHex := range privateKeys { + privateKey, err := crypto.HexToECDSA(privateKeyHex) + if err != nil { + return nil, err + } + signature, err := crypto.Sign(payload, privateKey) + if err != nil { + return nil, err + } + // crypto.Sign uses the traditional implementation where v is either 0 or 1, + // while Ethereum uses newer implementation where v is either 27 or 28. + if signature[64] < 27 { + signature[64] += 27 + } + copy(multiSig[i*65:(i+1)*65], signature) + } + return multiSig, nil +} + +// PopulateTransactionECDSA Populates missing properties meant for signing using an ECDSA private key: +// +// - Populates tx.From using the address derived from the ECDSA private key. +// - Populates tx.Nonce via client.NonceAt(). +// - Populates tx.Gas via client.EstimateGasL2(). If tx.From is not EOA, the estimation is done with address +// derived from the ECDSA private key. +// - Populates tx.GasFeeCap via client.SuggestGasPrice(). +// - Populates tx.GasTipCap with 0 if is not set. +// - Populates tx.ChainID via client.ChainID(). +// - Populates tx.Data with "0x". +// - Populates tx.Meta.GasPerPubdata with utils.DefaultGasPerPubdataLimit. +// +// Expects the secret to be ECDSA private in hex format. +var PopulateTransactionECDSA TransactionBuilder = func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error { + var err error + if client == nil { + return errors.New("client is required but is not provided") + } + + if tx.ChainID == nil { + if tx.ChainID, err = client.ChainID(ensureContext(ctx)); err != nil { + return err + } + } + if tx.Nonce == nil { + nonce, err := client.NonceAt(ensureContext(ctx), *tx.From, nil) + if err != nil { + return fmt.Errorf("failed to get nonce: %w", err) + } + tx.Nonce = new(big.Int).SetUint64(nonce) + } + if tx.GasFeeCap == nil { + if tx.GasFeeCap, err = client.SuggestGasPrice(ensureContext(ctx)); err != nil { + return fmt.Errorf("failed to SuggestGasPrice: %w", err) + } + } + if tx.GasTipCap == nil { + tx.GasTipCap = big.NewInt(0) + } + if tx.Meta == nil { + tx.Meta = &zkTypes.Eip712Meta{GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64())} + } else if tx.Meta.GasPerPubdata == nil { + tx.Meta.GasPerPubdata = utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()) + } + if tx.Gas == nil || tx.Gas.Uint64() == 0 { + from := *tx.From + // Gas estimation does not work when initiator is contract account (works only with EOA). + // In order to estimation gas, the transaction's from value is replaced with signer's address. + if bytecode, err := client.CodeAt(ensureContext(ctx), *tx.From, nil); len(bytecode) > 0 { + privateKeyHex, ok := (secret).(string) + if !ok { + return errors.New("secret should be hex of ECDSA private key") + } + privateKey, err := crypto.HexToECDSA(privateKeyHex) + if err != nil { + return err + } + publicKey := privateKey.Public().(*ecdsa.PublicKey) + from = crypto.PubkeyToAddress(*publicKey) + } else if err != nil { + return err + } + + gas, err := client.EstimateGasL2(ensureContext(ctx), zkTypes.CallMsg{ + CallMsg: ethereum.CallMsg{ + From: from, + To: tx.To, + GasFeeCap: tx.GasFeeCap, + GasTipCap: tx.GasTipCap, + Value: tx.Value, + Data: tx.Data, + }, + Meta: tx.Meta, + }) + if err != nil { + return fmt.Errorf("failed to EstimateGasL2: %w", err) + } + tx.Gas = new(big.Int).SetUint64(gas) + + } + if tx.Data == nil { + tx.Data = hexutil.Bytes{} + } + return nil +} + +// PopulateTransactionMultipleECDSA populates missing properties meant for signing using multiple ECDSA private keys. +// It uses PopulateTransactionECDSA, where the address of the first ECDSA key is set as the secret argument. +// Expects the secret to be a slice of ECDSA private in hex format. +var PopulateTransactionMultipleECDSA TransactionBuilder = func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error { + privateKeys, ok := (secret).([]string) + if !ok { + return errors.New("secret should be a slice of ECDSA private keys") + } + if len(privateKeys) < 2 { + return errors.New("secret should be a slice of ECDSA private keys") + } + // estimates gas accepts only one address, so the first signer is chosen. + return PopulateTransactionECDSA(ctx, tx, privateKeys[0], client) +} diff --git a/accounts/smart_account_utils_test.go b/accounts/smart_account_utils_test.go new file mode 100644 index 0000000..6ccdff1 --- /dev/null +++ b/accounts/smart_account_utils_test.go @@ -0,0 +1,186 @@ +package accounts + +import ( + "context" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/signer/core/apitypes" + "github.com/stretchr/testify/assert" + "github.com/zksync-sdk/zksync2-go/eip712" + zkTypes "github.com/zksync-sdk/zksync2-go/types" + "github.com/zksync-sdk/zksync2-go/utils" + "math/big" + "testing" +) + +const PrivateKey1 = "7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110" +const PrivateKey2 = "ac1e735be8536c6534bb4f17f06f6afc73b2b5ba84ac2cfb12f7461b20c0bbe3" + +var Address1 = common.HexToAddress("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049") +var Address2 = common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618") + +func TestSignPayloadWithECDSASignTransaction(t *testing.T) { + signature := "0x475e207d1e5da85721e37118cea54b2a3ac8e5dcd79cd7935c59bdd5cbc71e9824d4ab9dbaa5f8542e51588f4187c406fc4311c2ce9a9aa2a269f14298e5777d1b" + + tx := zkTypes.Transaction712{ + Nonce: big.NewInt(0), + GasTipCap: big.NewInt(0), + GasFeeCap: big.NewInt(1_000_000_000), + Gas: big.NewInt(1_000_000_000), + To: &Address2, + Value: big.NewInt(7_000_000_000), + Data: hexutil.Bytes{}, + ChainID: big.NewInt(270), + From: &Address1, + Meta: &zkTypes.Eip712Meta{ + GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()), + }, + } + + domain := eip712.ZkSyncEraEIP712Domain(270) + + eip712Msg, err := tx.EIP712Message() + assert.NoError(t, err, "EIP712Message should not return an error") + + hash, _, err := apitypes.TypedDataAndHash(apitypes.TypedData{ + Types: apitypes.Types{ + tx.EIP712Type(): tx.EIP712Types(), + domain.EIP712Type(): domain.EIP712Types(), + }, + PrimaryType: tx.EIP712Type(), + Domain: domain.EIP712Domain(), + Message: eip712Msg, + }) + assert.NoError(t, err, "TypedDataAndHash should not return an error") + + sig, err := SignPayloadWithECDSA(context.Background(), hash, PrivateKey1, nil) + assert.NoError(t, err, "SignPayloadWithECDSA should not return an error") + assert.Equal(t, signature, hexutil.Encode(sig), "Signatures must be the same") +} + +func TestSignPayloadWithECDSASignMessage(t *testing.T) { + signature := "0x7c15eb760c394b0ca49496e71d841378d8bfd4f9fb67e930eb5531485329ab7c67068d1f8ef4b480ec327214ee6ed203687e3fbe74b92367b259281e340d16fd1c" + + sig, err := SignPayloadWithECDSA(context.Background(), accounts.TextHash([]byte("Hello World!")), PrivateKey1, nil) + assert.NoError(t, err, "SignPayloadWithECDSA should not return an error") + assert.Equal(t, signature, hexutil.Encode(sig), "Signatures must be the same") +} + +func TestSignPayloadWithECDSASignTypedData(t *testing.T) { + signature := "0xbcaf0673c0c2b0e120165d207d42281d0c6e85f0a7f6b8044b0578a91cf5bda66b4aeb62aca4ae17012a38d71c9943e27285792fa7d788d848f849e3ea2e614b1b" + + hash, _, err := apitypes.TypedDataAndHash(apitypes.TypedData{ + Domain: apitypes.TypedDataDomain{ + Name: "Example", + Version: "1", + ChainId: math.NewHexOrDecimal256(270), + }, + Types: apitypes.Types{ + "Person": []apitypes.Type{ + {Name: "name", Type: "string"}, + {Name: "age", Type: "uint8"}, + }, + "EIP712Domain": []apitypes.Type{ + {Name: "name", Type: "string"}, + {Name: "version", Type: "string"}, + {Name: "chainId", Type: "uint256"}, + }, + }, + PrimaryType: "Person", + Message: apitypes.TypedDataMessage{ + "name": "John", + "age": hexutil.EncodeUint64(30), + }, + }) + assert.NoError(t, err, "TypedDataAndHash should not return an error") + + sig, err := SignPayloadWithECDSA(context.Background(), hash, PrivateKey1, nil) + assert.NoError(t, err, "SignPayloadWithECDSA should not return an error") + assert.Equal(t, signature, hexutil.Encode(sig), "Signatures must be the same") +} + +func TestSignPayloadWithMultipleECDSASignTransaction(t *testing.T) { + signature := "0x475e207d1e5da85721e37118cea54b2a3ac8e5dcd79cd7935c59bdd5cbc71e9824d4ab9dbaa5f8542e51588f4187c406fc4311c2ce9a9aa2a269f14298e5777d1b4ff4f280885d2dd0b2234d82cacec8ba94bd6659b64b1d516668b4ca79faf58a58c469fd95590e2541ca01866e312e56c7e38a74b4a8b72fdb07a69a3b34c19f1c" + + tx := zkTypes.Transaction712{ + Nonce: big.NewInt(0), + GasTipCap: big.NewInt(0), + GasFeeCap: big.NewInt(1_000_000_000), + Gas: big.NewInt(1_000_000_000), + To: &Address2, + Value: big.NewInt(7_000_000_000), + Data: hexutil.Bytes{}, + ChainID: big.NewInt(270), + From: &Address1, + Meta: &zkTypes.Eip712Meta{ + GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()), + }, + } + + domain := eip712.ZkSyncEraEIP712Domain(270) + + eip712Msg, err := tx.EIP712Message() + assert.NoError(t, err, "EIP712Message should not return an error") + + hash, _, err := apitypes.TypedDataAndHash(apitypes.TypedData{ + Types: apitypes.Types{ + tx.EIP712Type(): tx.EIP712Types(), + domain.EIP712Type(): domain.EIP712Types(), + }, + PrimaryType: tx.EIP712Type(), + Domain: domain.EIP712Domain(), + Message: eip712Msg, + }) + assert.NoError(t, err, "TypedDataAndHash should not return an error") + + sig, err := SignPayloadWithMultipleECDSA(context.Background(), hash, []string{PrivateKey1, PrivateKey2}, nil) + assert.NoError(t, err, "SignPayloadWithMultipleECDSA should not return an error") + assert.Equal(t, signature, hexutil.Encode(sig), "Signatures must be the same") +} + +func TestSignPayloadWithMultipleECDSASignMessage(t *testing.T) { + signature := "0x7c15eb760c394b0ca49496e71d841378d8bfd4f9fb67e930eb5531485329ab7c67068d1f8ef4b480ec327214ee6ed203687e3fbe74b92367b259281e340d16fd1c2f2f4a312d23de1bcadff9c547fe670a9e21beae16a7c9688fc10b97ba2e286574de339c2b70bd3f02bd021c270a1405942cc3e1268bf3f7a7a419a1c7aea2db1c" + + sig, err := SignPayloadWithMultipleECDSA( + context.Background(), + accounts.TextHash([]byte("Hello World!")), + []string{PrivateKey1, PrivateKey2}, + nil) + assert.NoError(t, err, "SignPayloadWithMultipleECDSA should not return an error") + assert.Equal(t, signature, hexutil.Encode(sig), "Signatures must be the same") +} + +func TestSignPayloadWithMultipleECDSASignTypedData(t *testing.T) { + signature := "0xbcaf0673c0c2b0e120165d207d42281d0c6e85f0a7f6b8044b0578a91cf5bda66b4aeb62aca4ae17012a38d71c9943e27285792fa7d788d848f849e3ea2e614b1b8231ec20acfc86483b908e8f1e88c917b244465c7e73202b6f2643377a6e54f5640f0d3e2f5902695faec96668b2e998148c49a4de613bb7bc4325a3c855cf6a1b" + + hash, _, err := apitypes.TypedDataAndHash(apitypes.TypedData{ + Domain: apitypes.TypedDataDomain{ + Name: "Example", + Version: "1", + ChainId: math.NewHexOrDecimal256(270), + }, + Types: apitypes.Types{ + "Person": []apitypes.Type{ + {Name: "name", Type: "string"}, + {Name: "age", Type: "uint8"}, + }, + "EIP712Domain": []apitypes.Type{ + {Name: "name", Type: "string"}, + {Name: "version", Type: "string"}, + {Name: "chainId", Type: "uint256"}, + }, + }, + PrimaryType: "Person", + Message: apitypes.TypedDataMessage{ + "name": "John", + "age": hexutil.EncodeUint64(30), + }, + }) + assert.NoError(t, err, "TypedDataAndHash should not return an error") + + sig, err := SignPayloadWithMultipleECDSA(context.Background(), hash, []string{PrivateKey1, PrivateKey2}, nil) + assert.NoError(t, err, "SignPayloadWithMultipleECDSA should not return an error") + assert.Equal(t, signature, hexutil.Encode(sig), "Signatures must be the same") +} diff --git a/accounts/types.go b/accounts/types.go index 065735e..085f67e 100644 --- a/accounts/types.go +++ b/accounts/types.go @@ -796,3 +796,12 @@ type AllowanceParams struct { Token common.Address // Token address Allowance *big.Int // Allowance amount } + +// PayloadSigner signs various types of payloads, optionally using a some kind of secret. +// Returns the serialized signature. +// The client is used to fetch data from the network if it is required for signing. +type PayloadSigner func(ctx context.Context, payload []byte, secret interface{}, client *clients.BaseClient) ([]byte, error) + +// TransactionBuilder populates missing fields in a tx with default values. +// The client is used to fetch data from the network if it is required. +type TransactionBuilder func(ctx context.Context, tx *zkTypes.Transaction712, secret interface{}, client *clients.BaseClient) error diff --git a/accounts/wallet_l2.go b/accounts/wallet_l2.go index b4a256f..fcd7bd0 100644 --- a/accounts/wallet_l2.go +++ b/accounts/wallet_l2.go @@ -272,7 +272,6 @@ func (a *WalletL2) PopulateTransaction(ctx context.Context, tx Transaction) (*zk if tx.Data == nil { tx.Data = hexutil.Bytes{} } - return tx.ToTransaction712(a.auth.From), nil } @@ -319,7 +318,7 @@ func (a *WalletL2) SendTransaction(ctx context.Context, tx *Transaction) (common if err != nil { return common.Hash{}, err } - return (*a.client).SendRawTransaction(context.Background(), rawTx) + return (*a.client).SendRawTransaction(ensureContext(ctx), rawTx) } func (a *WalletL2) transferETH(auth *TransactOpts, tx TransferTransaction) (*types.Transaction, error) { diff --git a/clients/base_client.go b/clients/base_client.go index c4f4466..ea5544b 100644 --- a/clients/base_client.go +++ b/clients/base_client.go @@ -903,17 +903,17 @@ func (c *BaseClient) EstimateGasL1(ctx context.Context, msg zkTypes.CallMsg) (ui // EstimateGasTransfer estimates the amount of gas required for a transfer transaction. func (c *BaseClient) EstimateGasTransfer(ctx context.Context, msg TransferCallMsg) (uint64, error) { - callMsg, err := msg.ToCallMsg() + callMsg, err := msg.ToZkCallMsg() if err != nil { return 0, err } - return c.EstimateGas(ctx, *callMsg) + return c.EstimateGasL2(ctx, *callMsg) } // EstimateGasWithdraw estimates the amount of gas required for a withdrawal transaction. func (c *BaseClient) EstimateGasWithdraw(ctx context.Context, msg WithdrawalCallMsg) (uint64, error) { var ( - callMsg *ethereum.CallMsg + callMsg *zkTypes.CallMsg err error ) if msg.Token == utils.LegacyEthAddress { @@ -925,14 +925,14 @@ func (c *BaseClient) EstimateGasWithdraw(ctx context.Context, msg WithdrawalCall if errBridge != nil { return 0, fmt.Errorf("failed to getBridgeContracts: %w", errBridge) } - callMsg, err = msg.ToCallMsg(&contracts.L2SharedBridge) + callMsg, err = msg.ToZkCallMsg(&contracts.L2SharedBridge) } else { - callMsg, err = msg.ToCallMsg(nil) + callMsg, err = msg.ToZkCallMsg(nil) if err != nil { return 0, err } } - return c.EstimateGas(ctx, *callMsg) + return c.EstimateGasL2(ctx, *callMsg) } // EstimateL1ToL2Execute estimates the amount of gas required for an L1 to L2 execute operation. diff --git a/clients/types.go b/clients/types.go index 0e87f40..2914b08 100644 --- a/clients/types.go +++ b/clients/types.go @@ -28,6 +28,8 @@ type TransferCallMsg struct { GasTipCap *big.Int // EIP-1559 tip per gas. AccessList types.AccessList // EIP-2930 access list. + + PaymasterParams *zkTypes.PaymasterParams // The paymaster parameters. } func (m *TransferCallMsg) ToCallMsg() (*ethereum.CallMsg, error) { @@ -66,6 +68,52 @@ func (m *TransferCallMsg) ToCallMsg() (*ethereum.CallMsg, error) { }, nil } +func (m *TransferCallMsg) ToZkCallMsg() (*zkTypes.CallMsg, error) { + var ( + value *big.Int + data []byte + to *common.Address + meta *zkTypes.Eip712Meta + ) + + if m.Token == utils.LegacyEthAddress { + value = m.Amount + to = &m.To + } else { + value = big.NewInt(0) + to = &m.Token + + erc20abi, err := erc20.IERC20MetaData.GetAbi() + if err != nil { + return nil, fmt.Errorf("failed to load erc20abi: %w", err) + } + data, err = erc20abi.Pack("transfer", m.To, m.Amount) + if err != nil { + return nil, fmt.Errorf("failed to pack transfer function: %w", err) + } + } + if m.PaymasterParams != nil { + meta = &zkTypes.Eip712Meta{ + GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()), + PaymasterParams: m.PaymasterParams, + } + } + + return &zkTypes.CallMsg{ + CallMsg: ethereum.CallMsg{ + From: m.From, + To: to, + Gas: m.Gas, + GasPrice: m.GasPrice, + GasFeeCap: m.GasFeeCap, + GasTipCap: m.GasTipCap, + Value: value, + Data: data, + }, + Meta: meta, + }, nil +} + // WithdrawalCallMsg contains parameters for withdrawal call. type WithdrawalCallMsg struct { To common.Address // The address of the recipient on L1. @@ -80,6 +128,8 @@ type WithdrawalCallMsg struct { GasTipCap *big.Int // EIP-1559 tip per gas. AccessList types.AccessList // EIP-2930 access list. + + PaymasterParams *zkTypes.PaymasterParams // The paymaster parameters. } func (m *WithdrawalCallMsg) ToCallMsg(defaultL2Bridge *common.Address) (*ethereum.CallMsg, error) { @@ -130,6 +180,26 @@ func (m *WithdrawalCallMsg) ToCallMsg(defaultL2Bridge *common.Address) (*ethereu } } +func (m *WithdrawalCallMsg) ToZkCallMsg(defaultL2Bridge *common.Address) (*zkTypes.CallMsg, error) { + var meta *zkTypes.Eip712Meta + + msg, err := m.ToCallMsg(defaultL2Bridge) + if err != nil { + return nil, err + } + if m.PaymasterParams != nil { + meta = &zkTypes.Eip712Meta{ + GasPerPubdata: utils.NewBig(utils.DefaultGasPerPubdataLimit.Int64()), + PaymasterParams: m.PaymasterParams, + } + } + + return &zkTypes.CallMsg{ + CallMsg: *msg, + Meta: meta, + }, nil +} + type blockMarshaling struct { ParentHash common.Hash `json:"parentHash" gencodec:"required"` UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` diff --git a/test/account_abstraction_test.go b/test/account_abstraction_test.go index b97b2c8..34fe84e 100644 --- a/test/account_abstraction_test.go +++ b/test/account_abstraction_test.go @@ -22,7 +22,7 @@ func TestIntegration_ApprovalPaymaster(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") // ====== Deploy Token ====== diff --git a/test/base_client_test.go b/test/base_client_test.go index 6ba79c0..d425e6f 100644 --- a/test/base_client_test.go +++ b/test/base_client_test.go @@ -160,10 +160,10 @@ func TestIntegrationBaseClient_TransactionInBlock(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - block, err := client.BlockByNumber(context.Background(), nil) + tx, _, err := client.TransactionByHash(context.Background(), L2DepositTx) assert.NoError(t, err, "BlockByNumber should not return an error") - tx, err := client.TransactionInBlock(context.Background(), block.Hash, 0) + tx, err = client.TransactionInBlock(context.Background(), *tx.BlockHash, uint(tx.TransactionIndex)) assert.NoError(t, err, "TransactionInBlock should not return an error") assert.NotNil(t, tx, "TransactionInBlock should return a non-nil transaction") @@ -174,10 +174,7 @@ func TestIntegrationBaseClient_TransactionReceipt(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - block, err := client.BlockByNumber(context.Background(), nil) - assert.NoError(t, err, "BlockByNumber should not return an error") - - txReceipt, err := client.TransactionReceipt(context.Background(), block.Transactions[0].Hash) + txReceipt, err := client.TransactionReceipt(context.Background(), L2DepositTx) assert.NoError(t, err, "TransactionReceipt should not return an error") assert.NotNil(t, txReceipt, "TransactionReceipt should return a non-nil transaction receipt") @@ -233,7 +230,7 @@ func TestIntegrationBaseClient_BalanceAt(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - balance, err := client.BalanceAt(context.Background(), Address, nil) + balance, err := client.BalanceAt(context.Background(), Address1, nil) assert.NoError(t, err, "BalanceAt should not return an error") assert.NotNil(t, balance, "BalanceAt should return a non-nil balance") @@ -266,7 +263,7 @@ func TestIntegrationBaseClient_NonceAt(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - nonce, err := client.NonceAt(context.Background(), Address, nil) + nonce, err := client.NonceAt(context.Background(), Address1, nil) assert.NoError(t, err, "NonceAt should not return an error") assert.NotNil(t, nonce, "NonceAt should return a non-nil nonce") @@ -314,7 +311,7 @@ func TestIntegrationBaseClient_FilterLogsL2(t *testing.T) { // sub, err := client.SubscribeFilterLogs(context.Background(), ethereum.FilterQuery{ // FromBlock: big.NewInt(0), // ToBlock: big.NewInt(1000), -// Addresses: []common.Address{common.HexToAddress(token.L2Address)}, +// Addresses: []common.Address1{common.HexToAddress(token.L2Address)}, // }, filterLogs) // if err != nil { // log.Panic(err) @@ -326,7 +323,7 @@ func TestIntegrationBaseClient_FilterLogsL2(t *testing.T) { // case err := <-sub.Err(): // log.Fatal(err) // case l := <-filterLogs: -// fmt.Println("Address: ", l.Address) +// fmt.Println("Address1: ", l.Address1) // fmt.Println("Data", l.Data) // } // } @@ -343,7 +340,7 @@ func TestIntegrationBaseClient_FilterLogsL2(t *testing.T) { // sub, err := client.SubscribeFilterLogsL2(context.Background(), ethereum.FilterQuery{ // FromBlock: big.NewInt(0), // ToBlock: big.NewInt(1000), -// Addresses: []common.Address{common.HexToAddress(token.L2Address)}, +// Addresses: []common.Address1{common.HexToAddress(token.L2Address)}, // }, filterLogs) // if err != nil { // log.Panic(err) @@ -355,7 +352,7 @@ func TestIntegrationBaseClient_FilterLogsL2(t *testing.T) { // case err := <-sub.Err(): // log.Fatal(err) // case l := <-filterLogs: -// fmt.Println("Address: ", l.Address) +// fmt.Println("Address1: ", l.Address1) // fmt.Println("Data", l.Data) // } // } @@ -366,7 +363,7 @@ func TestIntegrationBaseClient_PendingBalanceAt(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - balance, err := client.PendingBalanceAt(context.Background(), Address) + balance, err := client.PendingBalanceAt(context.Background(), Address1) assert.NoError(t, err, "PendingBalanceAt should not return an error") assert.NotNil(t, balance, "PendingBalanceAt should return a non-nil balance") @@ -399,7 +396,7 @@ func TestIntegrationBaseClient_PendingNonceAt(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - nonce, err := client.PendingNonceAt(context.Background(), Address) + nonce, err := client.PendingNonceAt(context.Background(), Address1) assert.NoError(t, err, "PendingNonceAt should not return an error") assert.NotNil(t, nonce, "PendingNonceAt should return a non-nil nonce") @@ -606,11 +603,11 @@ func TestIntegrationBaseClient_EstimateGas(t *testing.T) { tokenAbi, err := erc20.IERC20MetaData.GetAbi() assert.NoError(t, err, "bind.GetAbi should not return an error") - approveTokenCalldata, err := tokenAbi.Pack("approve", Receiver, big.NewInt(1)) + approveTokenCalldata, err := tokenAbi.Pack("approve", Address2, big.NewInt(1)) assert.NoError(t, err, "abi.Pack should not return an error") gas, err := client.EstimateGas(context.Background(), ethereum.CallMsg{ - From: Address, + From: Address1, To: &L2Dai, Data: approveTokenCalldata, }) @@ -627,12 +624,12 @@ func TestIntegrationBaseClient_EstimateGasL2(t *testing.T) { tokenAbi, err := erc20.IERC20MetaData.GetAbi() assert.NoError(t, err, "bind.GetAbi should not return an error") - approveTokenCalldata, err := tokenAbi.Pack("approve", Receiver, big.NewInt(1)) + approveTokenCalldata, err := tokenAbi.Pack("approve", Address2, big.NewInt(1)) assert.NoError(t, err, "abi.Pack should not return an error") gas, err := client.EstimateGasL2(context.Background(), zkTypes.CallMsg{ CallMsg: ethereum.CallMsg{ - From: Address, + From: Address1, To: &L2Dai, Data: approveTokenCalldata, }, @@ -647,24 +644,24 @@ func TestIntegrationBaseClient_SendTransaction(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - privateKey, err := crypto.HexToECDSA(PrivateKey) + privateKey, err := crypto.HexToECDSA(PrivateKey1) assert.NoError(t, err, "crypto.HexToECDSA should not return an error") tokenAbi, err := erc20.IERC20MetaData.GetAbi() assert.NoError(t, err, "bind.GetAbi should not return an error") - approveTokenCalldata, err := tokenAbi.Pack("approve", Receiver, big.NewInt(1)) + approveTokenCalldata, err := tokenAbi.Pack("approve", Address2, big.NewInt(1)) assert.NoError(t, err, "abi.Pack should not return an error") chainID, err := client.ChainID(context.Background()) assert.NoError(t, err, "ChainID should not return an error") - nonce, err := client.NonceAt(context.Background(), Address, nil) + nonce, err := client.NonceAt(context.Background(), Address1, nil) assert.NoError(t, err, "NonceAt should not return an error") gas, err := client.EstimateGasL2(context.Background(), zkTypes.CallMsg{ CallMsg: ethereum.CallMsg{ - From: Address, + From: Address1, To: &L2Dai, Data: approveTokenCalldata, }, @@ -700,13 +697,13 @@ func TestIntegrationBaseClient_SendRawTransaction(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - w, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + w, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") tokenAbi, err := erc20.IERC20MetaData.GetAbi() assert.NoError(t, err, "bind.GetAbi should not return an error") - approveTokenCalldata, err := tokenAbi.Pack("approve", Receiver, big.NewInt(1)) + approveTokenCalldata, err := tokenAbi.Pack("approve", Address2, big.NewInt(1)) assert.NoError(t, err, "abi.Pack should not return an error") tx, err := w.PopulateTransaction(context.Background(), accounts.Transaction{ @@ -732,11 +729,11 @@ func TestIntegrationBaseClient_WaitMined(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - w, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + w, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") tx, err := w.Transfer(nil, accounts.TransferTransaction{ - To: Receiver, + To: Address2, Amount: big.NewInt(7_000_000_000), Token: utils.LegacyEthAddress, }) @@ -753,11 +750,11 @@ func TestIntegrationBaseClient_WaitFinalized(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - w, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + w, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") tx, err := w.Transfer(nil, accounts.TransferTransaction{ - To: Receiver, + To: Address2, Amount: big.NewInt(7_000_000_000), Token: utils.LegacyEthAddress, }) @@ -1003,7 +1000,7 @@ func TestIntegration_EthBasedChain_BaseClient_AllAccountBalances(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - balances, err := client.AllAccountBalances(context.Background(), Address) + balances, err := client.AllAccountBalances(context.Background(), Address1) assert.NoError(t, err, "AllAccountBalances should not return an error") assert.Len(t, balances, 2, "Should have ETH and DAI balance") @@ -1014,7 +1011,7 @@ func TestIntegration_NonEthBasedChain_BaseClient_AllAccountBalances(t *testing.T defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - balances, err := client.AllAccountBalances(context.Background(), Address) + balances, err := client.AllAccountBalances(context.Background(), Address1) assert.NoError(t, err, "AllAccountBalances should not return an error") assert.Len(t, balances, 3, "Should have ETH and DAI balance") @@ -1027,8 +1024,8 @@ func TestIntegrationBaseClient_EstimateFee(t *testing.T) { fee, err := client.EstimateFee(context.Background(), zkTypes.CallMsg{ CallMsg: ethereum.CallMsg{ - From: Address, - To: &Receiver, + From: Address1, + To: &Address2, Value: big.NewInt(7_000_000_000), }, }) @@ -1044,8 +1041,8 @@ func TestIntegrationBaseClient_EstimateGasL1(t *testing.T) { gas, err := client.EstimateGasL1(context.Background(), zkTypes.CallMsg{ CallMsg: ethereum.CallMsg{ - From: Address, - To: &Receiver, + From: Address1, + To: &Address2, Value: big.NewInt(7_000_000_000), }, Meta: &zkTypes.Eip712Meta{ @@ -1063,8 +1060,8 @@ func TestIntegrationBaseClient_EstimateGasTransfer(t *testing.T) { assert.NoError(t, err, "clients.Dial should not return an error") gas, err := client.EstimateGasTransfer(context.Background(), clients.TransferCallMsg{ - From: Address, - To: Receiver, + From: Address1, + To: Address2, Amount: big.NewInt(7_000_000_000), }) @@ -1078,8 +1075,8 @@ func TestIntegrationBaseClient_EstimateGasWithdraw(t *testing.T) { assert.NoError(t, err, "clients.Dial should not return an error") gas, err := client.EstimateGasWithdraw(context.Background(), clients.WithdrawalCallMsg{ - From: Address, - To: Receiver, + From: Address1, + To: Address2, Amount: big.NewInt(7_000_000_000), }) @@ -1097,7 +1094,7 @@ func TestIntegrationBaseClient_EstimateL1ToL2Execute(t *testing.T) { gas, err := client.EstimateL1ToL2Execute(context.Background(), zkTypes.CallMsg{ CallMsg: ethereum.CallMsg{ - From: Address, + From: Address1, To: &mainContractAddress, Value: big.NewInt(7_000_000_000), }, @@ -1115,7 +1112,7 @@ func TestIntegrationBaseClient_EstimateL1ToL2Execute(t *testing.T) { // baseClient, ok := client.(*clients.BaseClient) // assert.True(t, ok, "Casting should not return error") // -// addressPadded := common.LeftPadBytes(Address.Bytes(), 32) +// addressPadded := common.LeftPadBytes(Address1.Bytes(), 32) // // // Convert the slot number to a hex string and pad it to 32 bytes // slotBytes := common.Hex2Bytes("0x00") // slot with index 0 diff --git a/test/const.go b/test/const.go index bd85e93..c367612 100644 --- a/test/const.go +++ b/test/const.go @@ -7,10 +7,23 @@ import ( const EthereumProvider = "http://localhost:8545" const ZkSyncEraProvider = "http://localhost:3050" -const PrivateKey = "7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110" +const PrivateKey1 = "7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110" +const PrivateKey2 = "ac1e735be8536c6534bb4f17f06f6afc73b2b5ba84ac2cfb12f7461b20c0bbe3" -var Address = common.HexToAddress("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049") -var Receiver = common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618") +var Address1 = common.HexToAddress("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049") +var Address2 = common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618") + +var Salt = common.Hex2Bytes("0x293328ad84b118194c65a0dc0defdb6483740d3163fd99b260907e15f2e2f642") + +// ApprovalToken is deployed using create2 and Salt +var ApprovalToken = common.HexToAddress("0x834FF28392Ab0460f13286c389fEF4E3980e28F6") + +// Paymaster is an approval based paymaster for approval token deployed using create2 and Salt +var Paymaster = common.HexToAddress("0xe1438081bF20c4C910266aa1229930473446b283") + +// MultisigAccount is an account that signs transaction using PrivateKey1 and PrivateKey2 +// and is deployed using create2 and Salt +var MultisigAccount = common.HexToAddress("0x60222D60b22D3e2A6F459Dc7264aEbf9f8735363") var L1Tokens []TokenData var L2Dai common.Address diff --git a/test/setup_test.go b/test/setup_test.go index ee74b04..4a33296 100644 --- a/test/setup_test.go +++ b/test/setup_test.go @@ -23,8 +23,7 @@ const TokenPath = "./testdata/tokens.json" func readTokens() []TokenData { file, err := os.Open(TokenPath) if err != nil { - log.Printf("Could not find tokens.json") - return nil + log.Fatal("Could not find tokens.json") } var tokens []TokenData @@ -35,6 +34,177 @@ func readTokens() []TokenData { return tokens } +func deployMultisigAccount(wallet *accounts.Wallet, client clients.Client) { + _, abi, bytecode, err := utils.ReadStandardJson("./testdata/TwoUserMultisig.json") + if err != nil { + log.Fatal(err) + } + + constructor, err := abi.Pack("", Address1, Address2) + if err != nil { + log.Fatal(err) + } + + hash, err := wallet.DeployAccount(nil, accounts.Create2Transaction{ + Bytecode: bytecode, + Calldata: constructor, + Salt: Salt, + }) + if err != nil { + log.Fatal(err) + } + + receipt, err := client.WaitMined(context.Background(), hash) + if err != nil { + log.Fatal(err) + } + multisigAccountAddress := receipt.ContractAddress + if multisigAccountAddress != MultisigAccount { + log.Fatal("multisig account addresses mismatch") + } + + // transfer ETH to multisig account + transferTx, err := wallet.Transfer(nil, accounts.TransferTransaction{ + To: multisigAccountAddress, + Amount: big.NewInt(2_000_000_000_000_000_000), + Token: utils.LegacyEthAddress, + }) + if err != nil { + log.Fatal(err) + } + + _, err = client.WaitMined(context.Background(), transferTx.Hash()) + if err != nil { + log.Fatal(err) + } + + // transfer token to multisig account + transferTx, err = wallet.Transfer(nil, accounts.TransferTransaction{ + To: multisigAccountAddress, + Amount: big.NewInt(20), + Token: L2Dai, + }) + if err != nil { + log.Fatal(err) + } + + _, err = client.WaitMined(context.Background(), transferTx.Hash()) + if err != nil { + log.Fatal(err) + } + + // transfer approval token to multisig account + transferTx, err = wallet.Transfer(nil, accounts.TransferTransaction{ + To: multisigAccountAddress, + Amount: big.NewInt(5), + Token: ApprovalToken, + }) + if err != nil { + log.Fatal(err) + } + + _, err = client.WaitMined(context.Background(), transferTx.Hash()) + if err != nil { + log.Fatal(err) + } +} + +func deployPaymasterAndToken(wallet *accounts.Wallet, client clients.Client) { + tokenAbi, err := TokenMetaData.GetAbi() + if err != nil { + log.Fatal(err) + } + + constructor, err := tokenAbi.Pack("", "Crown", "Crown", uint8(18)) + if err != nil { + log.Fatal(err) + } + + hash, err := wallet.Deploy(nil, accounts.Create2Transaction{ + Bytecode: common.FromHex(TokenMetaData.Bin), + Calldata: constructor, + Salt: Salt, + }) + if err != nil { + log.Fatal(err) + } + + receipt, err := client.WaitMined(context.Background(), hash) + if err != nil { + log.Fatal(err) + } + tokenAddress := receipt.ContractAddress + if tokenAddress != ApprovalToken { + log.Fatal("token addresses mismatch") + } + + // mint tokens to wallet + token, err := NewToken(tokenAddress, client) + if err != nil { + log.Fatal(err) + } + + opts, err := bind.NewKeyedTransactorWithChainID(wallet.Signer().PrivateKey(), wallet.Signer().Domain().ChainId) + if err != nil { + log.Fatal(err) + } + + mint, err := token.Mint(opts, wallet.Address(), big.NewInt(50)) + if err != nil { + log.Fatal(err) + } + + _, err = client.WaitMined(context.Background(), mint.Hash()) + if err != nil { + log.Fatal(err) + } + + // deploy paymaster + _, paymasterAbi, bytecode, err := utils.ReadStandardJson("./testdata/Paymaster.json") + if err != nil { + log.Fatal(err) + } + + constructor, err = paymasterAbi.Pack("", tokenAddress) + if err != nil { + log.Fatal(err) + } + + hash, err = wallet.DeployAccount(nil, accounts.Create2Transaction{ + Bytecode: bytecode, + Calldata: constructor, + Salt: Salt, + }) + if err != nil { + log.Fatal(err) + } + + receipt, err = client.WaitMined(context.Background(), hash) + if err != nil { + log.Fatal(err) + } + paymasterAddress := receipt.ContractAddress + if paymasterAddress != Paymaster { + log.Fatal("paymaster addresses mismatch") + } + + // transfer ETH to paymaster so it could pay fee + transferTx, err := wallet.Transfer(nil, accounts.TransferTransaction{ + To: paymasterAddress, + Amount: big.NewInt(2_000_000_000_000_000_000), + Token: utils.LegacyEthAddress, + }) + if err != nil { + log.Fatal(err) + } + + _, err = client.WaitMined(context.Background(), transferTx.Hash()) + if err != nil { + log.Fatal(err) + } + +} + func mintTokenOnL1(wallet *accounts.Wallet, ethClient *ethclient.Client, l1Token common.Address) { chainID, err := ethClient.ChainID(context.Background()) if err != nil { @@ -153,7 +323,7 @@ func prepare() { log.Fatal(err) } - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) if err != nil { log.Fatal(err) } @@ -246,6 +416,18 @@ func prepare() { fmt.Println("DAI L2: ", L2Dai) fmt.Println("L1 DAI balance: ", l1DaiTokenBalance) fmt.Println("L2 DAI balance: ", l2DaiTokenBalance) + + if approvalTokenBytecode, bytecodeErr := client.CodeAt(context.Background(), ApprovalToken, nil); len(approvalTokenBytecode) == 0 { + deployPaymasterAndToken(wallet, client) + } else if bytecodeErr != nil { + log.Fatal(bytecodeErr) + } + + if multisigAccountBytecode, bytecodeErr := client.CodeAt(context.Background(), MultisigAccount, nil); len(multisigAccountBytecode) == 0 { + deployMultisigAccount(wallet, client) + } else if bytecodeErr != nil { + log.Fatal(bytecodeErr) + } } func TestMain(m *testing.M) { diff --git a/test/smart_account_test.go b/test/smart_account_test.go new file mode 100644 index 0000000..a20a069 --- /dev/null +++ b/test/smart_account_test.go @@ -0,0 +1,1190 @@ +package test + +import ( + "context" + "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/common/math" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/signer/core/apitypes" + "github.com/stretchr/testify/assert" + "github.com/zksync-sdk/zksync2-go/accounts" + "github.com/zksync-sdk/zksync2-go/clients" + "github.com/zksync-sdk/zksync2-go/contracts/erc20" + zkTypes "github.com/zksync-sdk/zksync2-go/types" + "github.com/zksync-sdk/zksync2-go/utils" + "math/big" + "testing" +) + +func TestIntegration_NewSmartAccount(t *testing.T) { + account := accounts.NewSmartAccount( + Address1, + PrivateKey1, + &accounts.SignPayloadWithECDSA, + &accounts.PopulateTransactionECDSA, + nil) + assert.NotNil(t, account, "Account should not be nil") +} + +func TestIntegrationSmartAccount_Connect(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, nil) + + account = account.Connect(client) + assert.NotNil(t, account, "Connect should return non-nil value") +} + +func TestIntegrationSmartAccount_Address(t *testing.T) { + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, nil) + assert.Equal(t, Address1, account.Address()) +} + +func TestIntegrationSmartAccount_BalanceETH(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + balance, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + + assert.NoError(t, err, "Balance should not return an error") + assert.True(t, balance.Cmp(big.NewInt(0)) >= 0, "Balance should return a non-negative number") +} + +func TestIntegrationSmartAccount_BalanceToken(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + balance, err := account.Balance(context.Background(), L2Dai, nil) + + assert.NoError(t, err, "Balance should not return an error") + assert.True(t, balance.Cmp(big.NewInt(0)) >= 0, "Balance should return a non-negative number") +} + +func TestIntegration_EthBasedChain_SmartAccount_AllBalances(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + balances, err := account.AllBalances(context.Background()) + + assert.NoError(t, err, "AllBalances should not return an error") + assert.Len(t, balances, 2, "Should have ETH and DAI balance") +} + +func TestIntegration_NonEthBasedChain_SmartAccount_AllBalances(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + balances, err := account.AllBalances(context.Background()) + + assert.NoError(t, err, "AllBalances should not return an error") + assert.Len(t, balances, 3, "Should have ETH and DAI balance") +} + +func TestIntegrationSmartAccount_Nonce(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + nonce, err := account.Nonce(context.Background(), nil) + + assert.NoError(t, err, "Nonce should not return an error") + assert.True(t, nonce >= 0, "Nonce should be non-negative number") +} + +func TestIntegrationSmartAccount_DeploymentNonce(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + deploymentNonce, err := account.DeploymentNonce(nil) + + assert.NoError(t, err, "DeploymentNonce should not return an error") + assert.True(t, deploymentNonce.Cmp(big.NewInt(0)) >= 0, "Deployment nonce should be non-negative number") +} + +func TestIntegrationSmartAccount_Withdraw(t *testing.T) { + amount := big.NewInt(7_000_000_000) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + ethClient, err := ethclient.Dial(EthereumProvider) + assert.NoError(t, err, "ethclient.Dial should not return an error") + defer ethClient.Close() + + c := clients.Client(client) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &c, ethClient) + assert.NoError(t, err, "NewWallet should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + l2BalanceBeforeWithdrawal, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + withdrawHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ + To: account.Address(), + Amount: amount, + Token: utils.LegacyEthAddress, + }) + assert.NoError(t, err, "Withdraw should not return an error") + + withdrawReceipt, err := client.WaitFinalized(context.Background(), withdrawHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, withdrawReceipt.BlockHash, "Withdraw transaction should be mined") + + finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawHash, 0) + assert.NoError(t, err, "FinalizeWithdraw should not return an error") + + finalizeWithdrawReceipt, err := bind.WaitMined(context.Background(), ethClient, finalizeWithdrawTx) + assert.NoError(t, err, "bind.WaitMined should not return an error") + assert.NotNil(t, finalizeWithdrawReceipt.BlockHash, "Finalize withdraw transaction should be mined") + + l2BalanceAfterWithdrawal, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + assert.True(t, new(big.Int).Sub(l2BalanceBeforeWithdrawal, l2BalanceAfterWithdrawal).Cmp(amount) >= 0, "Balance on L2 should be decreased") +} + +func TestIntegrationSmartAccount_WithdrawUsingPaymaster(t *testing.T) { + amount := big.NewInt(7_000_000_000) + minimalAllowance := big.NewInt(1) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + ethClient, err := ethclient.Dial(EthereumProvider) + assert.NoError(t, err, "ethclient.Dial should not return an error") + defer ethClient.Close() + + c := clients.Client(client) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &c, ethClient) + assert.NoError(t, err, "NewWallet should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + approvalToken, err := erc20.NewIERC20(ApprovalToken, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + l2BalanceBeforeWithdrawal, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceBeforeWithdrawal, err := approvalToken.BalanceOf(nil, Address1) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceBeforeWithdrawalPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceBeforeWithdrawalPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + paymasterParams, err := utils.GetPaymasterParams( + Paymaster, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: ApprovalToken, + MinimalAllowance: minimalAllowance, + InnerInput: []byte{}, + }) + assert.NoError(t, err, "GetPaymasterParams should not return an error") + + withdrawHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ + To: account.Address(), + Amount: amount, + Token: utils.LegacyEthAddress, + PaymasterParams: paymasterParams, + }) + assert.NoError(t, err, "Withdraw should not return an error") + + withdrawReceipt, err := client.WaitFinalized(context.Background(), withdrawHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, withdrawReceipt.BlockHash, "Withdraw transaction should be mined") + + finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawHash, 0) + assert.NoError(t, err, "FinalizeWithdraw should not return an error") + + finalizeWithdrawReceipt, err := bind.WaitMined(context.Background(), ethClient, finalizeWithdrawTx) + assert.NoError(t, err, "bind.WaitMined should not return an error") + assert.NotNil(t, finalizeWithdrawReceipt.BlockHash, "Finalize withdraw transaction should be mined") + + l2BalanceAfterWithdrawal, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceAfterWithdrawal, err := approvalToken.BalanceOf(nil, Address1) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceAfterWithdrawalPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceAfterWithdrawalPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + assert.True(t, balanceBeforeWithdrawalPaymaster.Cmp(balanceAfterWithdrawalPaymaster) >= 0, "Paymaster balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceAfterWithdrawalPaymaster, approvalTokenBalanceBeforeWithdrawalPaymaster).Cmp(minimalAllowance) == 0, "Paymaster approval token balance should be increased") + + assert.True(t, new(big.Int).Sub(l2BalanceBeforeWithdrawal, l2BalanceAfterWithdrawal).Cmp(amount) >= 0, "Balance on L2 should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceBeforeWithdrawal, minimalAllowance).Cmp(approvalTokenBalanceAfterWithdrawal) == 0, "Sender approval token balance should be decreased") +} + +func TestIntegrationSmartAccount_WithdrawToken(t *testing.T) { + amount := big.NewInt(5) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + ethClient, err := ethclient.Dial(EthereumProvider) + assert.NoError(t, err, "ethclient.Dial should not return an error") + defer ethClient.Close() + + c := clients.Client(client) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &c, ethClient) + assert.NoError(t, err, "NewWallet should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + l2BalanceBeforeWithdrawal, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + withdrawHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ + To: account.Address(), + Amount: amount, + Token: L2Dai, + }) + assert.NoError(t, err, "Withdraw should not return an error") + + withdrawReceipt, err := client.WaitFinalized(context.Background(), withdrawHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, withdrawReceipt.BlockHash, "Withdraw transaction should be mined") + + finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawHash, 0) + assert.NoError(t, err, "FinalizeWithdraw should not return an error") + + finalizeWithdrawReceipt, err := bind.WaitMined(context.Background(), ethClient, finalizeWithdrawTx) + assert.NoError(t, err, "bind.WaitMined should not return an error") + assert.NotNil(t, finalizeWithdrawReceipt.BlockHash, "Finalize withdraw transaction should be mined") + + l2BalanceAfterWithdrawal, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + assert.True(t, new(big.Int).Sub(l2BalanceBeforeWithdrawal, l2BalanceAfterWithdrawal).Cmp(amount) >= 0, "Balance on L2 should be decreased") +} + +func TestIntegrationSmartAccount_WithdrawTokenUsingPaymaster(t *testing.T) { + amount := big.NewInt(5) + minimalAllowance := big.NewInt(1) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + ethClient, err := ethclient.Dial(EthereumProvider) + assert.NoError(t, err, "ethclient.Dial should not return an error") + defer ethClient.Close() + + c := clients.Client(client) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &c, ethClient) + assert.NoError(t, err, "NewWallet should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + approvalToken, err := erc20.NewIERC20(ApprovalToken, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + l2BalanceBeforeWithdrawal, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceBeforeWithdrawal, err := approvalToken.BalanceOf(nil, Address1) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceBeforeWithdrawalPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceBeforeWithdrawalPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + paymasterParams, err := utils.GetPaymasterParams( + Paymaster, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: ApprovalToken, + MinimalAllowance: minimalAllowance, + InnerInput: []byte{}, + }) + assert.NoError(t, err, "GetPaymasterParams should not return an error") + + withdrawHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ + To: account.Address(), + Amount: amount, + Token: L2Dai, + PaymasterParams: paymasterParams, + }) + assert.NoError(t, err, "Withdraw should not return an error") + + withdrawReceipt, err := client.WaitFinalized(context.Background(), withdrawHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, withdrawReceipt.BlockHash, "Withdraw transaction should be mined") + + finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawHash, 0) + assert.NoError(t, err, "FinalizeWithdraw should not return an error") + + finalizeWithdrawReceipt, err := bind.WaitMined(context.Background(), ethClient, finalizeWithdrawTx) + assert.NoError(t, err, "bind.WaitMined should not return an error") + assert.NotNil(t, finalizeWithdrawReceipt.BlockHash, "Finalize withdraw transaction should be mined") + + l2BalanceAfterWithdrawal, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceAfterWithdrawal, err := approvalToken.BalanceOf(nil, Address1) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceAfterWithdrawalPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceAfterWithdrawalPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + assert.True(t, balanceBeforeWithdrawalPaymaster.Cmp(balanceAfterWithdrawalPaymaster) >= 0, "Paymaster balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceAfterWithdrawalPaymaster, approvalTokenBalanceBeforeWithdrawalPaymaster).Cmp(minimalAllowance) == 0, "Paymaster approval token balance should be increased") + + assert.True(t, new(big.Int).Sub(l2BalanceBeforeWithdrawal, l2BalanceAfterWithdrawal).Cmp(amount) >= 0, "Balance on L2 should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceBeforeWithdrawal, minimalAllowance).Cmp(approvalTokenBalanceAfterWithdrawal) == 0, "Sender approval token balance should be decreased") +} + +func TestIntegrationSmartAccount_Transfer(t *testing.T) { + amount := big.NewInt(7_000_000_000) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + balanceBeforeTransferSender, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + balanceBeforeTransferReceiver, err := client.BalanceAt(context.Background(), Address2, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + txHash, err := account.Transfer(nil, accounts.TransferTransaction{ + To: Address2, + Amount: amount, + Token: utils.LegacyEthAddress, + }) + assert.NoError(t, err, "Transfer should not return an error") + + receipt, err := client.WaitMined(context.Background(), txHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, receipt.BlockHash, "Transaction should be mined") + + balanceAfterTransferSender, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + balanceAfterTransferReceiver, err := client.BalanceAt(context.Background(), Address2, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + assert.True(t, new(big.Int).Sub(balanceBeforeTransferSender, balanceAfterTransferSender).Cmp(amount) >= 0, "Sender balance should be decreased") + assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Address2 balance should be increased") +} + +func TestIntegrationSmartAccount_TransferUsingPaymaster(t *testing.T) { + amount := big.NewInt(7_000_000_000) + minimalAllowance := big.NewInt(1) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + approvalToken, err := erc20.NewIERC20(ApprovalToken, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + balanceBeforeTransferSender, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceBeforeTransferSender, err := approvalToken.BalanceOf(nil, Address1) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceBeforeTransferReceiver, err := client.BalanceAt(context.Background(), Address2, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + balanceBeforeTransferPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceBeforeTransferPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + paymasterParams, err := utils.GetPaymasterParams( + Paymaster, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: ApprovalToken, + MinimalAllowance: minimalAllowance, + InnerInput: []byte{}, + }) + assert.NoError(t, err, "GetPaymasterParams should not return an error") + + txHash, err := account.Transfer(nil, accounts.TransferTransaction{ + To: Address2, + Amount: amount, + Token: utils.LegacyEthAddress, + PaymasterParams: paymasterParams, + }) + assert.NoError(t, err, "Transfer should not return an error") + + receipt, err := client.WaitMined(context.Background(), txHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, receipt.BlockHash, "Transaction should be mined") + + balanceAfterTransferSender, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceAfterTransferSender, err := approvalToken.BalanceOf(nil, Address1) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceAfterTransferReceiver, err := client.BalanceAt(context.Background(), Address2, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + balanceAfterTransferPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceAfterTransferPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + assert.True(t, balanceBeforeTransferPaymaster.Cmp(balanceAfterTransferPaymaster) >= 0, "Paymaster balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceAfterTransferPaymaster, approvalTokenBalanceBeforeTransferPaymaster).Cmp(minimalAllowance) == 0, "Paymaster approval token balance should be increased") + + assert.True(t, new(big.Int).Sub(balanceBeforeTransferSender, balanceAfterTransferSender).Cmp(amount) >= 0, "Sender balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceBeforeTransferSender, minimalAllowance).Cmp(approvalTokenBalanceAfterTransferSender) == 0, "Sender approval token balance should be decreased") + + assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Address2 balance should be increased") +} + +func TestIntegrationSmartAccount_TransferToken(t *testing.T) { + amount := big.NewInt(5) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + token, err := erc20.NewIERC20(L2Dai, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + balanceBeforeTransferSender, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + balanceBeforeTransferReceiver, err := token.BalanceOf(nil, Address2) + assert.NoError(t, err, "BalanceOf should not return an error") + + txHash, err := account.Transfer(nil, accounts.TransferTransaction{ + To: Address2, + Amount: amount, + Token: L2Dai, + }) + assert.NoError(t, err, "Transfer should not return an error") + + receipt, err := client.WaitMined(context.Background(), txHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, receipt.BlockHash, "Transaction should be mined") + + balanceAfterTransferSender, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + balanceAfterTransferReceiver, err := token.BalanceOf(nil, Address2) + assert.NoError(t, err, "BalanceOf should not return an error") + + assert.True(t, new(big.Int).Sub(balanceBeforeTransferSender, balanceAfterTransferSender).Cmp(amount) >= 0, "Sender balance should be decreased") + assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Address2 balance should be increased") +} + +func TestIntegrationSmartAccount_TransferTokenUsingPaymaster(t *testing.T) { + amount := big.NewInt(5) + minimalAllowance := big.NewInt(1) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + ethClient, err := ethclient.Dial(EthereumProvider) + assert.NoError(t, err, "ethclient.Dial should not return an error") + defer ethClient.Close() + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + tokenContract, err := erc20.NewIERC20(L2Dai, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + approvalToken, err := erc20.NewIERC20(ApprovalToken, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + balanceBeforeTransferSender, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceBeforeTransferSender, err := approvalToken.BalanceOf(nil, Address1) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceBeforeTransferReceiver, err := tokenContract.BalanceOf(nil, Address2) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceBeforeTransferPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceBeforeTransferPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + paymasterParams, err := utils.GetPaymasterParams( + Paymaster, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: ApprovalToken, + MinimalAllowance: minimalAllowance, + InnerInput: []byte{}, + }) + assert.NoError(t, err, "GetPaymasterParams should not return an error") + + txHash, err := account.Transfer(nil, accounts.TransferTransaction{ + To: Address2, + Amount: amount, + Token: L2Dai, + PaymasterParams: paymasterParams, + }) + assert.NoError(t, err, "Transfer should not return an error") + + receipt, err := client.WaitMined(context.Background(), txHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, receipt.BlockHash, "Transaction should be mined") + + balanceAfterTransferSender, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceAfterTransferSender, err := approvalToken.BalanceOf(nil, Address1) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceAfterTransferReceiver, err := tokenContract.BalanceOf(nil, Address2) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceAfterTransferPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceAfterTransferPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + assert.True(t, balanceBeforeTransferPaymaster.Cmp(balanceAfterTransferPaymaster) >= 0, "Paymaster balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceAfterTransferPaymaster, approvalTokenBalanceBeforeTransferPaymaster).Cmp(minimalAllowance) == 0, "Paymaster approval token balance should be increased") + + assert.True(t, new(big.Int).Sub(balanceBeforeTransferSender, balanceAfterTransferSender).Cmp(amount) >= 0, "Sender balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceBeforeTransferSender, minimalAllowance).Cmp(approvalTokenBalanceAfterTransferSender) == 0, "Sender approval token balance should be decreased") + + assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Address2 balance should be increased") +} + +func TestIntegrationSmartAccount_PopulateTransaction(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + tx := &zkTypes.Transaction712{ + To: &Address2, + Value: big.NewInt(7_000_000_000), + From: &Address1, + } + + err = account.PopulateTransaction(context.Background(), tx) + + assert.NoError(t, err, "PopulateTransaction should not return an error") + assert.Equal(t, tx.To, &Address2, "To addresses must be the same") + assert.Equal(t, tx.From, &Address1, "From addresses must be the same") + assert.Equal(t, tx.ChainID, big.NewInt(270), "Chain IDs must be the same") + assert.Equal(t, tx.Value, big.NewInt(7_000_000_000), "Values must be the same") + assert.NotNil(t, tx.Data, "Data must not be nil") + assert.NotNil(t, tx.Gas, "Gas must not be nil") + assert.NotNil(t, tx.GasFeeCap, "GasFeeCap must not be nil") + assert.NotNil(t, tx.GasTipCap, "GasTipCap must not be nil") + assert.NotNil(t, tx.Meta, "Meta must not be nil") +} + +func TestIntegrationSmartAccount_SignTransaction(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + signedTx, err := account.SignTransaction(context.Background(), &zkTypes.Transaction712{ + To: &Address2, + Value: big.NewInt(1_000_000_000_000_000_000), // 1ETH + }) + + assert.NoError(t, err, "SignTransaction should not return an error") + assert.NotNil(t, signedTx, "Transaction should not be nil") +} + +func TestIntegrationSmartAccount_SignMessage(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + signature, err := account.SignMessage(context.Background(), []byte("Hello World!")) + + assert.NoError(t, err, "SignMessage should not return an error") + assert.NotNil(t, signature, "Signature should not be nil") +} + +func TestIntegrationSmartAccount_SignTypedData(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + signature, err := account.SignTypedData(context.Background(), apitypes.TypedData{ + Domain: apitypes.TypedDataDomain{ + Name: "Example", + Version: "1", + ChainId: math.NewHexOrDecimal256(270), + }, + Types: apitypes.Types{ + "Person": []apitypes.Type{ + {Name: "name", Type: "string"}, + {Name: "age", Type: "uint8"}, + }, + "EIP712Domain": []apitypes.Type{ + {Name: "name", Type: "string"}, + {Name: "version", Type: "string"}, + {Name: "chainId", Type: "uint256"}, + }, + }, + PrimaryType: "Person", + Message: apitypes.TypedDataMessage{ + "name": "John", + "age": hexutil.EncodeUint64(30), + }, + }) + assert.NoError(t, err, "SignTypedData should not return an error") + assert.NotNil(t, signature, "Signature should not be nil") +} + +func TestIntegrationSmartAccount_SendTransaction(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewECDSASmartAccount(Address1, PrivateKey1, client) + + tokenAbi, err := erc20.IERC20MetaData.GetAbi() + assert.NoError(t, err, "bind.GetAbi should not return an error") + + approveTokenCalldata, err := tokenAbi.Pack("approve", Address2, big.NewInt(1)) + assert.NoError(t, err, "abi.Pack should not return an error") + + txHash, err := account.SendTransaction(context.Background(), &zkTypes.Transaction712{ + To: &L2Dai, + Data: approveTokenCalldata, + }) + assert.NoError(t, err, "SendTransaction should not return an error") + + txReceipt, err := client.WaitMined(context.Background(), txHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + + assert.NotNil(t, txReceipt.BlockHash, "Transaction should be mined") +} + +func TestIntegrationMultisigSmartAccount_Withdraw(t *testing.T) { + amount := big.NewInt(7_000_000_000) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + ethClient, err := ethclient.Dial(EthereumProvider) + assert.NoError(t, err, "ethclient.Dial should not return an error") + defer ethClient.Close() + + c := clients.Client(client) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &c, ethClient) + assert.NoError(t, err, "NewWallet should not return an error") + + account := accounts.NewMultisigECDSASmartAccount(MultisigAccount, []string{PrivateKey1, PrivateKey2}, client) + + l2BalanceBeforeWithdrawal, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + withdrawHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ + To: wallet.Address(), + Amount: amount, + Token: utils.LegacyEthAddress, + }) + assert.NoError(t, err, "Withdraw should not return an error") + + withdrawReceipt, err := client.WaitFinalized(context.Background(), withdrawHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, withdrawReceipt.BlockHash, "Withdraw transaction should be mined") + + finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawHash, 0) + assert.NoError(t, err, "FinalizeWithdraw should not return an error") + + finalizeWithdrawReceipt, err := bind.WaitMined(context.Background(), ethClient, finalizeWithdrawTx) + assert.NoError(t, err, "bind.WaitMined should not return an error") + assert.NotNil(t, finalizeWithdrawReceipt.BlockHash, "Finalize withdraw transaction should be mined") + + l2BalanceAfterWithdrawal, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + assert.True(t, new(big.Int).Sub(l2BalanceBeforeWithdrawal, l2BalanceAfterWithdrawal).Cmp(amount) >= 0, "Balance on L2 should be decreased") +} + +func TestIntegrationMultisigSmartAccount_WithdrawUsingPaymaster(t *testing.T) { + amount := big.NewInt(7_000_000_000) + minimalAllowance := big.NewInt(1) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + ethClient, err := ethclient.Dial(EthereumProvider) + assert.NoError(t, err, "ethclient.Dial should not return an error") + defer ethClient.Close() + + c := clients.Client(client) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &c, ethClient) + assert.NoError(t, err, "NewWallet should not return an error") + + account := accounts.NewMultisigECDSASmartAccount(MultisigAccount, []string{PrivateKey1, PrivateKey2}, client) + + approvalToken, err := erc20.NewIERC20(ApprovalToken, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + l2BalanceBeforeWithdrawal, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceBeforeWithdrawal, err := approvalToken.BalanceOf(nil, MultisigAccount) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceBeforeWithdrawalPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceBeforeWithdrawalPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + paymasterParams, err := utils.GetPaymasterParams( + Paymaster, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: ApprovalToken, + MinimalAllowance: minimalAllowance, + InnerInput: []byte{}, + }) + assert.NoError(t, err, "GetPaymasterParams should not return an error") + + withdrawHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ + To: wallet.Address(), + Amount: amount, + Token: utils.LegacyEthAddress, + PaymasterParams: paymasterParams, + }) + assert.NoError(t, err, "Withdraw should not return an error") + + withdrawReceipt, err := client.WaitFinalized(context.Background(), withdrawHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, withdrawReceipt.BlockHash, "Withdraw transaction should be mined") + + finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawHash, 0) + assert.NoError(t, err, "FinalizeWithdraw should not return an error") + + finalizeWithdrawReceipt, err := bind.WaitMined(context.Background(), ethClient, finalizeWithdrawTx) + assert.NoError(t, err, "bind.WaitMined should not return an error") + assert.NotNil(t, finalizeWithdrawReceipt.BlockHash, "Finalize withdraw transaction should be mined") + + l2BalanceAfterWithdrawal, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceAfterWithdrawal, err := approvalToken.BalanceOf(nil, MultisigAccount) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceAfterWithdrawalPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceAfterWithdrawalPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + assert.True(t, balanceBeforeWithdrawalPaymaster.Cmp(balanceAfterWithdrawalPaymaster) >= 0, "Paymaster balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceAfterWithdrawalPaymaster, approvalTokenBalanceBeforeWithdrawalPaymaster).Cmp(minimalAllowance) == 0, "Paymaster approval token balance should be increased") + + assert.True(t, new(big.Int).Sub(l2BalanceBeforeWithdrawal, l2BalanceAfterWithdrawal).Cmp(amount) >= 0, "Balance on L2 should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceBeforeWithdrawal, minimalAllowance).Cmp(approvalTokenBalanceAfterWithdrawal) == 0, "Sender approval token balance should be decreased") +} + +func TestIntegrationMultisigSmartAccount_WithdrawToken(t *testing.T) { + amount := big.NewInt(5) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + ethClient, err := ethclient.Dial(EthereumProvider) + assert.NoError(t, err, "ethclient.Dial should not return an error") + defer ethClient.Close() + + c := clients.Client(client) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &c, ethClient) + assert.NoError(t, err, "NewWallet should not return an error") + + account := accounts.NewMultisigECDSASmartAccount(MultisigAccount, []string{PrivateKey1, PrivateKey2}, client) + + l2BalanceBeforeWithdrawal, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + withdrawHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ + To: wallet.Address(), + Amount: amount, + Token: L2Dai, + }) + assert.NoError(t, err, "Withdraw should not return an error") + + withdrawReceipt, err := client.WaitFinalized(context.Background(), withdrawHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, withdrawReceipt.BlockHash, "Withdraw transaction should be mined") + + finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawHash, 0) + assert.NoError(t, err, "FinalizeWithdraw should not return an error") + + finalizeWithdrawReceipt, err := bind.WaitMined(context.Background(), ethClient, finalizeWithdrawTx) + assert.NoError(t, err, "bind.WaitMined should not return an error") + assert.NotNil(t, finalizeWithdrawReceipt.BlockHash, "Finalize withdraw transaction should be mined") + + l2BalanceAfterWithdrawal, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + assert.True(t, new(big.Int).Sub(l2BalanceBeforeWithdrawal, l2BalanceAfterWithdrawal).Cmp(amount) >= 0, "Balance on L2 should be decreased") +} + +func TestIntegrationMultisigSmartAccount_WithdrawTokenUsingPaymaster(t *testing.T) { + amount := big.NewInt(5) + minimalAllowance := big.NewInt(1) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + ethClient, err := ethclient.Dial(EthereumProvider) + assert.NoError(t, err, "ethclient.Dial should not return an error") + defer ethClient.Close() + + c := clients.Client(client) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &c, ethClient) + assert.NoError(t, err, "NewWallet should not return an error") + + account := accounts.NewMultisigECDSASmartAccount(MultisigAccount, []string{PrivateKey1, PrivateKey2}, client) + + approvalToken, err := erc20.NewIERC20(ApprovalToken, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + l2BalanceBeforeWithdrawal, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceBeforeWithdrawal, err := approvalToken.BalanceOf(nil, MultisigAccount) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceBeforeWithdrawalPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceBeforeWithdrawalPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + paymasterParams, err := utils.GetPaymasterParams( + Paymaster, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: ApprovalToken, + MinimalAllowance: minimalAllowance, + InnerInput: []byte{}, + }) + assert.NoError(t, err, "GetPaymasterParams should not return an error") + + withdrawHash, err := account.Withdraw(nil, accounts.WithdrawalTransaction{ + To: wallet.Address(), + Amount: amount, + Token: L2Dai, + PaymasterParams: paymasterParams, + }) + assert.NoError(t, err, "Withdraw should not return an error") + + withdrawReceipt, err := client.WaitFinalized(context.Background(), withdrawHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, withdrawReceipt.BlockHash, "Withdraw transaction should be mined") + + finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, withdrawHash, 0) + assert.NoError(t, err, "FinalizeWithdraw should not return an error") + + finalizeWithdrawReceipt, err := bind.WaitMined(context.Background(), ethClient, finalizeWithdrawTx) + assert.NoError(t, err, "bind.WaitMined should not return an error") + assert.NotNil(t, finalizeWithdrawReceipt.BlockHash, "Finalize withdraw transaction should be mined") + + l2BalanceAfterWithdrawal, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceAfterWithdrawal, err := approvalToken.BalanceOf(nil, MultisigAccount) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceAfterWithdrawalPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceAfterWithdrawalPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + assert.True(t, balanceBeforeWithdrawalPaymaster.Cmp(balanceAfterWithdrawalPaymaster) >= 0, "Paymaster balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceAfterWithdrawalPaymaster, approvalTokenBalanceBeforeWithdrawalPaymaster).Cmp(minimalAllowance) == 0, "Paymaster approval token balance should be increased") + + assert.True(t, new(big.Int).Sub(l2BalanceBeforeWithdrawal, l2BalanceAfterWithdrawal).Cmp(amount) >= 0, "Balance on L2 should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceBeforeWithdrawal, minimalAllowance).Cmp(approvalTokenBalanceAfterWithdrawal) == 0, "Sender approval token balance should be decreased") +} + +func TestIntegrationMultisigSmartAccount_Transfer(t *testing.T) { + amount := big.NewInt(7_000_000_000) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewMultisigECDSASmartAccount(MultisigAccount, []string{PrivateKey1, PrivateKey2}, client) + + balanceBeforeTransferSender, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + balanceBeforeTransferReceiver, err := client.BalanceAt(context.Background(), Address2, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + txHash, err := account.Transfer(nil, accounts.TransferTransaction{ + To: Address2, + Amount: amount, + Token: utils.LegacyEthAddress, + }) + assert.NoError(t, err, "Transfer should not return an error") + + receipt, err := client.WaitMined(context.Background(), txHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, receipt.BlockHash, "Transaction should be mined") + + balanceAfterTransferSender, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + balanceAfterTransferReceiver, err := client.BalanceAt(context.Background(), Address2, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + assert.True(t, new(big.Int).Sub(balanceBeforeTransferSender, balanceAfterTransferSender).Cmp(amount) >= 0, "Sender balance should be decreased") + assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Address2 balance should be increased") +} + +func TestIntegrationMultisigSmartAccount_TransferUsingPaymaster(t *testing.T) { + amount := big.NewInt(7_000_000_000) + minimalAllowance := big.NewInt(1) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewMultisigECDSASmartAccount(MultisigAccount, []string{PrivateKey1, PrivateKey2}, client) + + approvalToken, err := erc20.NewIERC20(ApprovalToken, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + balanceBeforeTransferSender, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceBeforeTransferSender, err := approvalToken.BalanceOf(nil, MultisigAccount) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceBeforeTransferReceiver, err := client.BalanceAt(context.Background(), Address2, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + balanceBeforeTransferPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceBeforeTransferPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + paymasterParams, err := utils.GetPaymasterParams( + Paymaster, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: ApprovalToken, + MinimalAllowance: minimalAllowance, + InnerInput: []byte{}, + }) + assert.NoError(t, err, "GetPaymasterParams should not return an error") + + txHash, err := account.Transfer(nil, accounts.TransferTransaction{ + To: Address2, + Amount: amount, + Token: utils.LegacyEthAddress, + PaymasterParams: paymasterParams, + }) + assert.NoError(t, err, "Transfer should not return an error") + + receipt, err := client.WaitMined(context.Background(), txHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, receipt.BlockHash, "Transaction should be mined") + + balanceAfterTransferSender, err := account.Balance(context.Background(), utils.LegacyEthAddress, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceAfterTransferSender, err := approvalToken.BalanceOf(nil, MultisigAccount) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceAfterTransferReceiver, err := client.BalanceAt(context.Background(), Address2, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + balanceAfterTransferPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceAfterTransferPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + assert.True(t, balanceBeforeTransferPaymaster.Cmp(balanceAfterTransferPaymaster) >= 0, "Paymaster balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceAfterTransferPaymaster, approvalTokenBalanceBeforeTransferPaymaster).Cmp(minimalAllowance) == 0, "Paymaster approval token balance should be increased") + + assert.True(t, new(big.Int).Sub(balanceBeforeTransferSender, balanceAfterTransferSender).Cmp(amount) >= 0, "Sender balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceBeforeTransferSender, minimalAllowance).Cmp(approvalTokenBalanceAfterTransferSender) == 0, "Sender approval token balance should be decreased") + + assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Address2 balance should be increased") +} + +func TestIntegrationMultisigSmartAccount_TransferToken(t *testing.T) { + amount := big.NewInt(5) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + account := accounts.NewMultisigECDSASmartAccount(MultisigAccount, []string{PrivateKey1, PrivateKey2}, client) + + token, err := erc20.NewIERC20(L2Dai, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + balanceBeforeTransferSender, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + balanceBeforeTransferReceiver, err := token.BalanceOf(nil, Address2) + assert.NoError(t, err, "BalanceOf should not return an error") + + txHash, err := account.Transfer(nil, accounts.TransferTransaction{ + To: Address2, + Amount: amount, + Token: L2Dai, + }) + assert.NoError(t, err, "Transfer should not return an error") + + receipt, err := client.WaitMined(context.Background(), txHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, receipt.BlockHash, "Transaction should be mined") + + balanceAfterTransferSender, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + balanceAfterTransferReceiver, err := token.BalanceOf(nil, Address2) + assert.NoError(t, err, "BalanceOf should not return an error") + + assert.True(t, new(big.Int).Sub(balanceBeforeTransferSender, balanceAfterTransferSender).Cmp(amount) >= 0, "Sender balance should be decreased") + assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Address2 balance should be increased") +} + +func TestIntegrationMultisigSmartAccount_TransferTokenUsingPaymaster(t *testing.T) { + amount := big.NewInt(5) + minimalAllowance := big.NewInt(1) + + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + ethClient, err := ethclient.Dial(EthereumProvider) + assert.NoError(t, err, "ethclient.Dial should not return an error") + defer ethClient.Close() + + account := accounts.NewMultisigECDSASmartAccount(MultisigAccount, []string{PrivateKey1, PrivateKey2}, client) + + tokenContract, err := erc20.NewIERC20(L2Dai, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + approvalToken, err := erc20.NewIERC20(ApprovalToken, client) + assert.NoError(t, err, "NewIERC20 should not return an error") + + balanceBeforeTransferSender, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceBeforeTransferSender, err := approvalToken.BalanceOf(nil, MultisigAccount) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceBeforeTransferReceiver, err := tokenContract.BalanceOf(nil, Address2) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceBeforeTransferPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceBeforeTransferPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + paymasterParams, err := utils.GetPaymasterParams( + Paymaster, + &zkTypes.ApprovalBasedPaymasterInput{ + Token: ApprovalToken, + MinimalAllowance: minimalAllowance, + InnerInput: []byte{}, + }) + assert.NoError(t, err, "GetPaymasterParams should not return an error") + + txHash, err := account.Transfer(nil, accounts.TransferTransaction{ + To: Address2, + Amount: amount, + Token: L2Dai, + PaymasterParams: paymasterParams, + }) + assert.NoError(t, err, "Transfer should not return an error") + + receipt, err := client.WaitMined(context.Background(), txHash) + assert.NoError(t, err, "client.WaitMined should not return an error") + assert.NotNil(t, receipt.BlockHash, "Transaction should be mined") + + balanceAfterTransferSender, err := account.Balance(context.Background(), L2Dai, nil) + assert.NoError(t, err, "Balance should not return an error") + + approvalTokenBalanceAfterTransferSender, err := approvalToken.BalanceOf(nil, MultisigAccount) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceAfterTransferReceiver, err := tokenContract.BalanceOf(nil, Address2) + assert.NoError(t, err, "BalanceOf should not return an error") + + balanceAfterTransferPaymaster, err := client.BalanceAt(context.Background(), Paymaster, nil) + assert.NoError(t, err, "BalanceAt should not return an error") + + approvalTokenBalanceAfterTransferPaymaster, err := approvalToken.BalanceOf(nil, Paymaster) + assert.NoError(t, err, "BalanceOf should not return an error") + + assert.True(t, balanceBeforeTransferPaymaster.Cmp(balanceAfterTransferPaymaster) >= 0, "Paymaster balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceAfterTransferPaymaster, approvalTokenBalanceBeforeTransferPaymaster).Cmp(minimalAllowance) == 0, "Paymaster approval token balance should be increased") + + assert.True(t, new(big.Int).Sub(balanceBeforeTransferSender, balanceAfterTransferSender).Cmp(amount) >= 0, "Sender balance should be decreased") + assert.True(t, new(big.Int).Sub(approvalTokenBalanceBeforeTransferSender, minimalAllowance).Cmp(approvalTokenBalanceAfterTransferSender) == 0, "Sender approval token balance should be decreased") + + assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Address2 balance should be increased") +} diff --git a/test/smart_account_utils_test.go b/test/smart_account_utils_test.go new file mode 100644 index 0000000..6768ec9 --- /dev/null +++ b/test/smart_account_utils_test.go @@ -0,0 +1,58 @@ +package test + +import ( + "context" + "github.com/stretchr/testify/assert" + "github.com/zksync-sdk/zksync2-go/accounts" + "github.com/zksync-sdk/zksync2-go/clients" + zkTypes "github.com/zksync-sdk/zksync2-go/types" + "math/big" + "testing" +) + +func TestIntegration_PopulateTransactionECDSA(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + tx := zkTypes.Transaction712{ + To: &Address2, + Value: big.NewInt(7_000_000_000), + ChainID: big.NewInt(270), + From: &Address1, + } + + err = accounts.PopulateTransactionECDSA(context.Background(), &tx, PrivateKey1, client) + assert.NoError(t, err, "PopulateTransactionECDSA should not return an error") + + assert.Equal(t, tx.To, &Address2, "To addresses must be the same") + assert.Equal(t, tx.From, &Address1, "From addresses must be the same") + assert.Equal(t, tx.ChainID, big.NewInt(270), "Chain IDs must be the same") + assert.Equal(t, tx.Value, big.NewInt(7_000_000_000), "Values must be the same") + assert.NotNil(t, tx.Data, "Data must not be nil") + assert.NotNil(t, tx.Gas, "Gas must not be nil") + assert.NotNil(t, tx.GasFeeCap, "GasFeeCap must not be nil") + assert.NotNil(t, tx.GasTipCap, "GasTipCap must not be nil") + assert.NotNil(t, tx.Meta, "Meta must not be nil") +} + +func TestIntegration_PopulateTransactionECDSA_ErrorNoClientProvided(t *testing.T) { + tx := zkTypes.Transaction712{ + To: &Address2, + Value: big.NewInt(7_000_000_000), + ChainID: big.NewInt(270), + From: &Address1, + } + + err := accounts.PopulateTransactionECDSA(context.Background(), &tx, PrivateKey1, nil) + assert.Error(t, err, "PopulateTransactionECDSA should return an error when client is not provided") +} + +func TestIntegration_PopulateTransactionMultipleECDSA_ErrorNoMultipleKeysProvided(t *testing.T) { + client, err := clients.DialBase(ZkSyncEraProvider) + defer client.Close() + assert.NoError(t, err, "clients.DialBase should not return an error") + + err = accounts.PopulateTransactionMultipleECDSA(context.Background(), &zkTypes.Transaction712{}, [1]string{PrivateKey1}, client) + assert.Error(t, err, "PopulateTransactionMultipleECDSA should return an error when only one private key is provided") +} diff --git a/test/testdata/TwoUserMultisig.json b/test/testdata/TwoUserMultisig.json new file mode 100644 index 0000000..c7cebda --- /dev/null +++ b/test/testdata/TwoUserMultisig.json @@ -0,0 +1,607 @@ +{ + "_format": "hh-zksolc-artifact-1", + "contractName": "TwoUserMultisig", + "sourceName": "contracts/TwoUserMultisig.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_owner1", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner2", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "txType", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "from", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "to", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPerPubdataByteLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paymaster", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256[4]", + "name": "reserved", + "type": "uint256[4]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "factoryDeps", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "paymasterInput", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "reservedDynamic", + "type": "bytes" + } + ], + "internalType": "struct Transaction", + "name": "_transaction", + "type": "tuple" + } + ], + "name": "executeTransaction", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "txType", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "from", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "to", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPerPubdataByteLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paymaster", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256[4]", + "name": "reserved", + "type": "uint256[4]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "factoryDeps", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "paymasterInput", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "reservedDynamic", + "type": "bytes" + } + ], + "internalType": "struct Transaction", + "name": "_transaction", + "type": "tuple" + } + ], + "name": "executeTransactionFromOutside", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "magic", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner1", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner2", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "txType", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "from", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "to", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPerPubdataByteLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paymaster", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256[4]", + "name": "reserved", + "type": "uint256[4]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "factoryDeps", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "paymasterInput", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "reservedDynamic", + "type": "bytes" + } + ], + "internalType": "struct Transaction", + "name": "_transaction", + "type": "tuple" + } + ], + "name": "payForTransaction", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "txType", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "from", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "to", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPerPubdataByteLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paymaster", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256[4]", + "name": "reserved", + "type": "uint256[4]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "factoryDeps", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "paymasterInput", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "reservedDynamic", + "type": "bytes" + } + ], + "internalType": "struct Transaction", + "name": "_transaction", + "type": "tuple" + } + ], + "name": "prepareForPaymaster", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_suggestedSignedHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "txType", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "from", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "to", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPerPubdataByteLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paymaster", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256[4]", + "name": "reserved", + "type": "uint256[4]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "factoryDeps", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "paymasterInput", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "reservedDynamic", + "type": "bytes" + } + ], + "internalType": "struct Transaction", + "name": "_transaction", + "type": "tuple" + } + ], + "name": "validateTransaction", + "outputs": [ + { + "internalType": "bytes4", + "name": "magic", + "type": "bytes4" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x0004000000000002000e00000000000200000000030100190000006003300270000005d30030019d000005d303300197000300000031035500020000000103550000000102200190000000b20000c13d000000800b0000390000004000b0043f000000040230008c000000e90000413d000000000201043b000000e002200270000005d80420009c000000f70000213d000005de0420009c000001090000213d000005e10420009c000001580000613d000005e20220009c000000eb0000c13d000000040230008a000000600220008c000002c00000413d0000004402100370000000000602043b000005e30260009c000002c00000213d00000004076000390000000002730049000005e403000041000002600420008c00000000040000190000000004034019000005e402200197000000000502004b000000000300a019000005e40220009c000000000304c019000000000203004b000002c00000c13d0000002402100370000000000302043b0000000002000411000080010220008c000001f80000c13d000a00000003001d000900000007001d0000000002000414000005e503000041000000a00030043f000800000006001d0000010403600039000000000131034f000000000101043b000000a40010043f0000002401000039000000800010043f000000e001000039000000400010043f000000c0012002100000060a011001970000060b011001c700008003020000390000000003000019000000000400001900000000050000190000000006000019174717380000040f000300000001035500000000030100190000006003300270000105d30030019d000005d3053001970000003f03500039000005d406300197000000400300043d0000000004360019000000000664004b00000000060000190000000106004039000005e30740009c0000041a0000213d00000001066001900000041a0000c13d000000400040043f00000000045304360000001f065000390000000506600272000000680000613d0000000007000031000000020770036700000000080000190000000509800210000000000a940019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000000600000413d000000000600004b0000006a0000613d0000001f0650018f0000000505500272000000760000613d000000000700001900000005087002100000000009840019000000000881034f000000000808043b00000000008904350000000107700039000000000857004b0000006e0000413d000000000706004b000000850000613d0000000505500210000000000151034f00000000055400190000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f00000000001504350000000101200190000002390000613d0000000a01000029000000000201004b0000008c0000c13d0000000901000029174706190000040f000a00000001001d0000000901000029174714420000040f0000000002000410000e00000002001d000700000001001d0000800a01000039000000240300003900000000040004150000000e0440008a00000020044000c9000005e602000041174717200000040f000000070110006b0000000001000019000000010100a039174705620000040f0000000801000029000001e40210003900000009010000291747057a0000040f0000000003000031174704ed0000040f00000000020100190000000a01000029174715670000040f000005ee011001970000060c020000410000060d0110009c000000000200c019000000400100043d0000000000210435000005d302000041000005d30310009c000000000102801900000040011002100000060e011001c7000017480001042e0000000002000416000000000202004b000002c00000c13d0000009f02300039000005d402200197000000400020043f0000001f0230018f0000000504300272000000c40000613d00000000050000190000000506500210000000000761034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b000000bc0000413d000000000502004b000000d30000613d0000000504400210000000000141034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f0000000000140435000000400130008c000002c00000413d000000800100043d000005d50210009c000002c00000213d000000a00200043d000005d50320009c000002c00000213d000000000300041a000005d603300197000000000113019f000000000010041b0000000101000039000000000301041a000005d603300197000000000223019f000000000021041b000000200100003900000100001004430000012000000443000005d701000041000017480001042e000000000103004b0000021e0000613d0000000001000416000000000101004b000002c00000c13d0000000001000411000080010110008c0000021e0000c13d000005e70100004100000000001004350000000101000039000000040010043f000005e8010000410000174900010430000005d90420009c000001120000213d000005dc0420009c000001830000613d000005dd0120009c000000eb0000c13d0000000001030019174705280000040f000a00000001001d0000000001000411000080010110008c000000000100001900000001010060391747054a0000040f0000000a01000029174714680000040f0000000001000019000017480001042e000005df0120009c000001cb0000613d000005e00120009c000000eb0000c13d0000000001000416000000000101004b000002c00000c13d000000000100041a000001d00000013d000005da0420009c000001d40000613d000005db0220009c000000eb0000c13d000000040230008a000000200220008c000002c00000413d0000000402100370000000000702043b000005e30270009c000002c00000213d00000004067000390000000002630049000005e403000041000002600420008c00000000040000190000000004034019000005e402200197000000000502004b000000000300a019000005e40220009c000000000304c019000000000203004b000002c00000c13d0000000002000414000005e503000041000000a00030043f0000010403700039000000000131034f000000000101043b000000a40010043f0000002401000039000700000001001d000000800010043f000000e001000039000000400010043f000005d3012001970000008002000039000a00000006001d000800000007001d174705a40000040f0000000a01000029174706190000040f000900000001001d0000000a01000029174714420000040f0000000002000410000b00000002001d000600000001001d0000800a0100003900000000040004150000000b0440008a00000020044000c9000005e6020000410000000703000029174717200000040f000000060110006b0000000001000019000000010100a039174705620000040f0000000801000029000001e4021000390000000a010000291747057a0000040f0000000003000031174704ed0000040f00000000020100190000000901000029174715670000040f000001050000013d0000000002000416000000000202004b000002c00000c13d000000040230008a000000400220008c000002c00000413d0000002402100370000000000402043b000005e30240009c000002c00000213d0000002302400039000005e405000041000000000632004b00000000060000190000000006058019000005e402200197000000000702004b0000000005008019000005e40220009c000000000506c019000000000205004b000002c00000c13d0000000402400039000000000121034f000000000201043b0000002401400039174704ed0000040f00000004020000390000000202200367000000000202043b000000000301001900000000010200190000000002030019174715670000040f000005ee01100197000000400200043d0000000000120435000005d301000041000005d30320009c000000000201801900000040012002100000060e011001c7000017480001042e000000040230008a000000600220008c000002c00000413d0000004402100370000000000202043b000005e30420009c000002c00000213d00000004042000390000000005430049000005e406000041000002600750008c00000000070000190000000007064019000005e408500197000000000908004b000000000600a019000005e40880009c000000000607c019000000000606004b000002c00000c13d0000000006000411000080010660008c000001f80000c13d0000022402200039000000000621034f000000000606043b0000001f0550008a000005e407000041000000000856004b00000000080000190000000008078019000005e405500197000005e409600197000000000a59004b0000000007008019000000000559013f000005e40550009c000000000708c019000000000507004b000002c00000c13d0000000005460019000000000451034f000000000404043b000005e30640009c000002c00000213d00000000064300490000002005500039000005e407000041000000000865004b00000000080000190000000008072019000005e406600197000005e409500197000000000a69004b0000000007008019000000000669013f000005e40660009c000000000708c019000000000607004b000002c00000c13d000000030640008c000002500000213d000005ec01000041000000800010043f0000002001000039000000840010043f0000003a01000039000000a40010043f0000060501000041000000c40010043f0000060601000041000002010000013d0000000001000416000000000101004b000002c00000c13d0000000101000039000000000101041a000005d501100197000000800010043f0000060701000041000017480001042e000000040330008a000000600230008c000002c00000413d0000004402100370000000000202043b000005e30420009c000002c00000213d0000000003230049000005e404000041000002600530008c00000000050000190000000005044019000005e403300197000000000603004b000000000400a019000005e40330009c000000000405c019000000000304004b000002c00000c13d0000000003000411000080010330008c000001f80000c13d000000a403200039000000000331034f0000006402200039000000000121034f000000000101043b000000000203043b000000000302004b000002040000c13d00000000040004150000000d0440008a00000020044000c90000000001000414000d00000000001d0000020f0000013d000005ec01000041000000800010043f0000002001000039000000840010043f0000002401000039000000a40010043f0000060801000041000000c40010043f0000060901000041000000e40010043f0000060201000041000017490001043000000000431200a900000000422300d9000000000112004b000002350000c13d00000000040004150000000c0440008a00000020044000c90000000001000414000c00000000001d000000000203004b000002430000c13d000a00000004001d000005d302000041000005d30310009c0000000001028019000000c0011002100000800102000039174717380000040f0000000a0300002900030000000103550000006001100270000105d30010019d000000050130027000000001012001950000000101200190000002200000613d0000000001000019000017480001042e000000400100043d0000006402100039000005ea0300004100000000003204350000004402100039000005eb030000410000000000320435000000240210003900000025030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ed011001c70000174900010430000005e70100004100000000001004350000001101000039000000f40000013d0000000001030433000005d302000041000005d30310009c0000000001028019000005d30340009c000000000402801900000040024002100000006001100210000000000121019f0000174900010430000005d302000041000005d30410009c0000000001028019000000c001100210000005e9011001c7000080090200003900008001040000390000000005000019174717380000040f00000000030004150000000c0330008a00000020033000c9000002170000013d000a0000000b001d000000000651034f000000000606043b000005ee06600197000005ef0760009c000002620000613d000005f00160009c0000021e0000613d000005ec01000041000000800010043f0000002001000039000000840010043f0000001a01000039000000a40010043f0000060301000041000000c40010043f00000604010000410000174900010430000000430440008c0000026e0000213d000005ec01000041000000800010043f0000002001000039000000840010043f0000004001000039000000a40010043f0000060001000041000000c40010043f0000060101000041000002010000013d0000000404500039000000000541034f000000000505043b000900000005001d000005d50550009c000002c00000213d000001400220008a000000000221034f0000002004400039000000000441034f000000000404043b000800000004001d000000000202043b000005f104000041000000800040043f0000000004000410000005d504400197000600000004001d000000840040043f000005d502200197000700000002001d000000a40020043f00000000020004140000000904000029000000040440008c0000028e0000c13d000000000131034f0000000103000031000000200230008c00000000040300190000002004008039000002ba0000013d000005d301000041000005d30320009c0000000002018019000000c001200210000005f2011001c700000009020000291747173d0000040f00000000030100190000006003300270000005d303300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000002a70000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b0000029f0000413d000000000705004b000002b60000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000002e40000613d0000001f02400039000000600520018f00000080025001bf000000400020043f000000200430008c000002c20000813d00000000010000190000174900010430000000800400043d000000080440006c0000021e0000813d000000a004500039000005f3060000410000000000640435000000a40650003900000007070000290000000000760435000000c40650003900000000000604350000004406000039000100000006001d00000000006204350000014006500039000000400060043f0000012007500039000005f406000041000300000007001d000000000067043500000100065001bf0000002005000039000400000005001d000200000006001d0000000000560435000000000502043300000000020004140000000906000029000000040660008c000003070000c13d0000000102000039000005e30430009c0000041a0000213d0000031b0000013d000000400200043d0000001f0430018f0000000505300272000002f10000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000002e90000413d000000000604004b000003000000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005d301000041000005d30420009c000000000201801900000040012002100000006002300210000000000121019f0000174900010430000005d301000041000005d30350009c000000000501801900000060035002100000004004400210000000000343019f000005d30420009c0000000002018019000000c001200210000000000113019f0000000902000029174717380000040f000500600000003d000000010220018f000300000001035500000000030100190000006003300270000105d30030019d000005d303300198000003470000613d0000003f04300039000000200500008a000000000454016f000000400500043d0000000004450019000500000005001d000000000554004b00000000050000190000000105004039000005e30640009c0000041a0000213d00000001055001900000041a0000c13d000000400040043f0000001f0430018f000000050500002900000000083504360000000503300272000003370000613d000000000500001900000005065002100000000007680019000000000661034f000000000606043b00000000006704350000000105500039000000000635004b0000032f0000413d000a00000008001d000000000504004b000003470000613d0000000503300210000000000131034f0000000a033000290000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000013043500000005010000290000000001010433000000000202004b000003660000c13d000000000201004b000003610000c13d000000400400043d000a00000004001d000005ec01000041000000000014043500000004014000390000000402000029000000000021043500000002010000290000000003010433000900000003001d0000002401400039000000000031043500000044024000390000000301000029174714350000040f00000009010000290000001f01100039000000200200008a000000000121016f0000004401100039000005d302000041000005d30310009c00000000010280190000000a040000290000023d0000013d000000000201004b0000038f0000c13d000005f501000041000000000010043900000009010000290000000400100443000005d3010000410000000002000414000005d30320009c0000000002018019000000c001200210000005f6011001c700008002020000391747173d0000040f0000000102200190000004e70000613d000000000101043b000000000101004b0000038b0000c13d000000400100043d0000004402100039000005fe03000041000000000032043500000024021000390000001d030000390000000000320435000005ec020000410000000000210435000000040210003900000004030000290000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ff011001c7000017490001043000000005010000290000000001010433000000000201004b000003b20000613d000005e402000041000000200310008c00000000030000190000000003024019000005e401100197000000000401004b000000000200a019000005e40110009c000000000203c019000000000102004b0000000a01000029000002c00000c13d0000000001010433000000000201004b0000000002000019000000010200c039000000000221004b000002c00000c13d000000000101004b000003b20000c13d000000400100043d0000006402100039000005fc0300004100000000003204350000004402100039000005fd03000041000000000032043500000024021000390000002a030000390000000000320435000005ec020000410000000000210435000000040210003900000004030000290000022e0000013d000000400300043d000000240130003900000007020000290000000000210435000005f1010000410000000000130435000a00000003001d00000004013000390000000602000029000000000021043500000000010004140000000902000029000000040220008c000003c50000c13d0000000103000031000000200130008c00000000040300190000002004008039000003f70000013d000005d302000041000005d30310009c00000000010280190000000a04000029000005d30340009c00000000020440190000004002200210000000c001100210000000000121019f000005f7011001c700000009020000291747173d0000040f0000000a0a00002900000000030100190000006003300270000005d303300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000003e40000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000003dc0000413d000000000705004b000003f30000613d0000000506600210000000000761034f0000000a066000290000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f000300000001035500000001022001900000041e0000613d0000001f01400039000000600210018f0000000a01200029000000000221004b00000000020000190000000102004039000005e30410009c0000041a0000213d00000001022001900000041a0000c13d000000400010043f000000200230008c000002c00000413d000000440410003900000024051000390000000a020000290000000002020433000000000202004b0000043b0000c13d0000002002100039000005f3060000410000000000620435000000070600002900000000006504350000000805000029000000000054043500000001040000290000000000410435000005fa0410009c0000041a0000213d0000008004100039000a00000004001d000000400040043f000005fb0410009c000004470000a13d000005e70100004100000000001004350000004101000039000000f40000013d000000400200043d0000001f0430018f00000005053002720000042b0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000004230000413d000000000604004b0000043a0000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000003000000013d000005ec02000041000000000021043500000004021000390000000403000029000000000032043500000036020000390000000000250435000005f80200004100000000002404350000006402100039000005f9030000410000022e0000013d000000c004100039000000400040043f00000004040000290000000a050000290000000000450435000000a005100039000005f404000041000700000005001d0000000000450435000000000401043300000000010004140000000905000029000000040550008c000004590000c13d0000000102000039000005e30130009c0000041a0000213d0000046f0000013d000005d303000041000005d30520009c00000000020380190000004002200210000005d30540009c00000000040380190000006004400210000000000224019f000005d30410009c0000000001038019000000c001100210000000000112019f0000000902000029174717380000040f000800600000003d000600800000003d000000010220018f00030000000103550000006001100270000105d30010019d000005d3031001980000049c0000613d0000003f01300039000000200400008a000000000141016f000000400400043d0000000001140019000800000004001d000000000441004b00000000040000190000000104004039000005e30510009c0000041a0000213d00000001044001900000041a0000c13d000000400010043f0000001f0130018f00000008040000290000000008340436000000030400036700000005033002720000048c0000613d000000000500001900000005065002100000000007680019000000000664034f000000000606043b00000000006704350000000105500039000000000635004b000004840000413d000600000008001d000000000501004b0000049c0000613d0000000503300210000000000434034f00000006033000290000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f000000000013043500000008010000290000000001010433000000000202004b000004bb0000c13d000000000201004b000004e80000c13d000000400400043d000900000004001d000005ec0100004100000000001404350000000401400039000000040200002900000000002104350000000a010000290000000003010433000a00000003001d0000002401400039000000000031043500000044024000390000000701000029174714350000040f0000000a010000290000001f01100039000000200200008a000000000121016f0000004401100039000005d302000041000005d30310009c000000000102801900000009040000290000023d0000013d000000000201004b000004d20000c13d000005f501000041000000000010043900000009010000290000000400100443000005d3010000410000000002000414000005d30320009c0000000002018019000000c001200210000005f6011001c700008002020000391747173d0000040f0000000102200190000004e70000613d000000000101043b000000000101004b000003790000613d00000008010000290000000001010433000000000201004b0000021e0000613d000005e402000041000000200310008c00000000030000190000000003024019000005e401100197000000000401004b000000000200a019000005e40110009c000000000203c019000000000102004b000002c00000c13d00000006010000290000000001010433000000000201004b0000000002000019000000010200c039000000000221004b000002c00000c13d000000000101004b0000021e0000c13d000003a30000013d000000000001042f000005d302000041000005d30310009c000000000102801900000006040000290000023d0000013d00000000040100190000060f0120009c000005200000813d0000003f01200039000000200500008a000000000551016f000000400100043d0000000005510019000000000615004b00000000060000190000000106004039000005e30750009c000005200000213d0000000106600190000005200000c13d000000400050043f00000000052104360000000006420019000000000336004b000005260000213d0000001f0320018f000000020440036700000005062002720000050e0000613d000000000700001900000005087002100000000009850019000000000884034f000000000808043b00000000008904350000000107700039000000000867004b000005060000413d000000000703004b0000051d0000613d0000000506600210000000000464034f00000000066500190000000303300210000000000706043300000000073701cf000000000737022f000000000404043b0000010003300089000000000434022f00000000033401cf000000000373019f000000000036043500000000022500190000000000020435000000000001042d000005e70100004100000000001004350000004101000039000000040010043f000005e801000041000017490001043000000000010000190000174900010430000000040210008a000005e4030000410000005f0420008c00000000040000190000000004032019000005e402200197000000000502004b0000000003008019000005e40220009c000000000304c019000000000203004b000005480000613d00000044020000390000000202200367000000000202043b000005e30320009c000005480000213d00000004022000390000000001210049000005e403000041000002600410008c00000000040000190000000004034019000005e401100197000000000501004b000000000300a019000005e40110009c000000000304c019000000000103004b000005480000c13d0000000001020019000000000001042d00000000010000190000174900010430000000000101004b0000054d0000613d000000000001042d000000400100043d000000640210003900000609030000410000000000320435000000440210003900000608030000410000000000320435000000240210003900000024030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ed011001c70000174900010430000000000101004b000005650000613d000000000001042d000000400100043d000000640210003900000610030000410000000000320435000000440210003900000611030000410000000000320435000000240210003900000022030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ed011001c70000174900010430000000000300003100000000041300490000001f0540008a0000000204000367000000000224034f000000000202043b000005e406000041000000000752004b00000000070000190000000007064019000005e405500197000005e408200197000000000958004b000000000600a019000000000558013f000005e40550009c000000000607c019000000000506004b000005a20000613d0000000001120019000000000214034f000000000202043b000005e30420009c000005a20000213d00000000032300490000002001100039000005e404000041000000000531004b00000000050000190000000005042019000005e403300197000005e406100197000000000736004b0000000004008019000000000336013f000005e40330009c000000000405c019000000000304004b000005a20000c13d000000000001042d000000000100001900001749000104300000000003020433000006120430009c000005f70000813d000000c0011002100000060a01100197000000400220021000000613022000410000061402200197000000000121019f00000060023002100000061502200197000000000121019f00000616011001c700008003020000390000000003000019000000000400001900000000050000190000000006000019174717380000040f000300000001035500000000030100190000006003300270000105d30030019d000005d3053001970000003f03500039000005d406300197000000400300043d0000000004360019000000000664004b00000000060000190000000106004039000005e30740009c000006090000213d0000000106600190000006090000c13d000000400040043f00000000045304360000001f065000390000000506600272000005d70000613d0000000007000031000000020770036700000000080000190000000509800210000000000a940019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000005cf0000413d000000000600004b000005d90000613d0000001f0650018f0000000505500272000005e50000613d000000000700001900000005087002100000000009840019000000000881034f000000000808043b00000000008904350000000107700039000000000857004b000005dd0000413d000000000706004b000005f40000613d0000000505500210000000000151034f00000000055400190000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f000000000015043500000001012001900000060f0000613d000000000001042d000000400100043d000000440210003900000617030000410000000000320435000000240210003900000008030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ff011001c70000174900010430000005e70100004100000000001004350000004101000039000000040010043f000005e80100004100001749000104300000000001030433000005d302000041000005d30310009c0000000001028019000005d30340009c000000000402801900000040024002100000006001100210000000000121019f00001749000104300007000000000002000000020d00036700000000021d034f000000000202043b000000010320008c000700000001001d0000067e0000213d000000000302004b000008900000613d000000010120008c000013ed0000c13d00000618010000410000000000100439000005d3010000410000000002000414000005d30320009c0000000002018019000000c00120021000000619011001c70000800b020000391747173d0000040f0000000102200190000013da0000613d000000400400043d000000000101043b000000800210008c0000099c0000413d00000080021002700000061c0310009c000000000201a0190000061c0310009c0000000003000019000000100300203900000008053001bf000005e30620009c000000000503a0190000004003200270000005e30620009c000000000302a01900000004025001bf000005d30630009c000000000205a0190000002006300270000005d30530009c000000000603a01900000002052001bf0000ffff0360008c000000000502a0190000001002600270000000000206a019000000ff0220008c0000000105502039000000200200008a0000004103500039000000000223016f0000000002240019000000000342004b00000000030000190000000103004039000005e30620009c000000070f000029000013ce0000213d0000000103300190000013ce0000c13d000000400020043f0000000202500039000000000624043600000002020003670000000003000031000000210750003900000005077002720000066b0000613d000000000832034f0000000009000019000000050a900210000000000ba60019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b000006630000413d000600000003001d000000000300004b0000066e0000613d0000000007040433000000000707004b000013d40000613d00000000070604330000061b07700197000000f808500210000000000778019f0000061d0770004100000000007604350000000305500210000000f80550008900000000015101cf000000ff0550008c00000000010020190000002105400039000009b00000013d000000020320008c000008e10000613d000000710220008c000013ed0000c13d000001c00210003900000000032d034f000000000200003100000000041200490000001f0440008a000000000303043b000005e405000041000000000643004b00000000060000190000000006058019000005e404400197000005e407300197000000000847004b0000000005008019000000000447013f000005e40440009c000000000506c019000000000405004b000013d20000c13d000000000313001900000000043d034f000000000504043b000005e30450009c000013d20000213d00000000045200490000002003300039000005e406000041000000000743004b00000000070000190000000007062019000005e404400197000005e408300197000000000948004b0000000006008019000000000448013f000005e40440009c000000000607c019000000000406004b000013d20000c13d0000000004000414000000000605004b000006b70000613d0000000006350019000000000556004b000000000500001900000001050040390000000105500190000013e90000c13d000000000562004b000013e90000413d0000000002620049000005d303300197000000000d3d034f000006120340009c000013db0000813d000005d30220019700000000012d03df000000c0024002100000060a0220019700000622022001c700000000012103af0000801002000039174717420000040f00000000030100190000006003300270000105d30030019d000005d30530019700030000000103550000000102200190000013ff0000613d0000003f02500039000005d402200197000000400600043d0000000002260019000000000362004b00000000030000190000000103004039000005e30420009c000000070c000029000013ce0000213d0000000103300190000013ce0000c13d000000400020043f0000000004560436000000020200036700000000030000310000001f075000390000000507700272000006e50000613d000000000832034f0000000009000019000000050a900210000000000ba40019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b000006dd0000413d000000000700004b000006e70000613d0000001f0750018f0000000505500272000006f30000613d00000000080000190000000509800210000000000a940019000000000991034f000000000909043b00000000009a04350000000108800039000000000958004b000006eb0000413d000000000807004b000007020000613d0000000505500210000000000151034f00000000055400190000000307700210000000000805043300000000087801cf000000000878022f000000000101043b0000010007700089000000000171022f00000000017101cf000000000181019f00000000001504350000000001060433000000200110008c000013e20000c13d0000000001c300490000001f0510008a000002000ac000390000000001a2034f000000000101043b000005e406000041000000000751004b00000000070000190000000007068019000005e405500197000005e408100197000000000958004b0000000006008019000000000558013f000005e40550009c000000000607c019000000000506004b000013d20000c13d0000000004040433000500000004001d0000000001c10019000000000412034f000000000504043b000005e30450009c000013d20000213d000000050450021000000000034300490000002006100039000005e401000041000000000736004b00000000070000190000000007012019000005e403300197000005e408600197000000000938004b0000000001008019000000000338013f000005e40330009c000000000107c019000000000101004b000013d20000c13d000000400100043d000000200310003900000623055001980000073c0000613d000000000262034f000000000600001900000005076002100000000008730019000000000772034f000000000707043b00000000007804350000000106600039000000000756004b000007340000413d00060000000a001d000000000200004b0000073f0000613d00000000004104350000003f02400039000000200400008a000000000242016f0000000002210019000000000412004b00000000040000190000000104004039000005e30520009c000013ce0000213d0000000104400190000013ce0000c13d000000400020043f000005d302000041000005d30430009c000000000302801900000040033002100000000001010433000005d30410009c00000000010280190000006001100210000000000131019f0000000003000414000005d30430009c0000000003028019000000c002300210000000000112019f000005e9011001c700008010020000391747173d0000040f000000070a00002900000001022001900000000604000029000013d20000613d00000000020000310000000003a200490000001f0530008a00000020044000390000000203000367000000000443034f000000000404043b000005e406000041000000000754004b00000000070000190000000007068019000005e405500197000005e408400197000000000958004b0000000006008019000000000558013f000005e40550009c000000000607c019000000000b01043b000000000106004b000013d20000c13d0000000001a40019000000000413034f000000000504043b000005e30450009c000013d20000213d00000000045200490000002001100039000005e406000041000000000741004b00000000070000190000000007062019000005e404400197000005e408100197000000000948004b0000000006008019000000000448013f000005e40440009c000000000607c019000000000406004b000013d20000c13d0000000004000414000000000605004b000007980000613d0000000006150019000000000556004b000000000500001900000001050040390000000105500190000013e90000c13d000000000562004b000013e90000413d0000000002620049000005d301100197000000000313034f00060000000b001d000005d30140009c000013db0000213d000005d30120019700000000011303df000000c0024002100000060a0220019700000622022001c700000000012103af0000801002000039174717420000040f00000000030100190000006003300270000105d30030019d000005d304300197000300000001035500000001022001900000141a0000613d0000003f02400039000005d402200197000000400500043d0000000002250019000000000352004b00000000030000190000000103004039000005e30620009c000000070c000029000013ce0000213d0000000103300190000013ce0000c13d000000400020043f000000000245043600000002030003670000001f064000390000000506600272000007c60000613d000000000730036800000000080000190000000509800210000000000a920019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000007be0000413d000000000600004b000007c80000613d0000001f0640018f0000000504400272000007d40000613d000000000700001900000005087002100000000009820019000000000881034f000000000808043b00000000008904350000000107700039000000000847004b000007cc0000413d000000000706004b000007e30000613d0000000504400210000000000141034f00000000044200190000000306600210000000000704043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f00000000001404350000000001050433000000200110008c000013e20000c13d0000006001c00039000000000113034f0000004004c00039000000000543034f0000002004c00039000000000443034f0000012006c00039000000000663034f0000010007c00039000000000773034f000000e008c00039000000000883034f000000c009c00039000000000993034f000000a00ac00039000000000aa3034f000000800bc00039000000000bb3034f0000000003c3034f000000000303043b000000000404043b000000000505043b000000000c01043b000000000b0b043b000000000a0a043b000000000909043b000000000808043b000000000707043b000000000606043b0000000002020433000000400100043d000001c00d10003900000000002d0435000001a002100039000000060d0000290000000000d204350000018002100039000000050d0000290000000000d2043500000160021000390000000000620435000001400210003900000000007204350000012002100039000000000082043500000100021000390000000000920435000000e0021000390000000000a20435000000c0021000390000000000b20435000000a0021000390000000000c20435000000800210003900000000005204350000006002100039000000000042043500000040021000390000000000320435000000200210003900000625030000410000000000320435000001c0030000390000000000310435000006260310009c000013ce0000213d000001e003100039000000400030043f000005d304000041000005d30320009c000000000204801900000040022002100000000001010433000005d30310009c00000000010480190000006001100210000000000121019f0000000002000414000005d30320009c0000000002048019000000c002200210000000000112019f000005e9011001c700008010020000391747173d0000040f0000000102200190000013d20000613d000000000101043b000600000001001d000000400100043d000700000001001d000006180100004100000000001004390000000001000414000005d30210009c000005d301008041000000c00110021000000619011001c70000800b020000391747173d0000040f0000000102200190000013da0000613d00000007040000290000002002400039000000000101043b0000062703000041000000000032043500000080034000390000000000130435000000600140003900000628030000410000000000310435000000400140003900000629030000410000000000310435000000800100003900000000001404350000062a0140009c000013ce0000213d000000a001400039000000400010043f000005d301000041000005d30320009c000000000201801900000040022002100000000003040433000005d30430009c00000000030180190000006003300210000000000223019f0000000003000414000005d30430009c0000000003018019000000c001300210000000000121019f000005e9011001c700008010020000391747173d0000040f0000000102200190000013d20000613d000000000301043b000000400100043d00000042021000390000000604000029000000000042043500000020021000390000062b0400004100000000004204350000002204100039000000000034043500000042030000390000000000310435000005fa0310009c000013ce0000213d0000008003100039000000400030043f000005d303000041000005d30420009c000000000203801900000040022002100000000001010433000005d30410009c00000000010380190000006001100210000000000121019f0000000002000414000005d30420009c0000000002038019000000c002200210000013c60000013d000000400200043d000600000002001d000001000410003900000000024d034f000000000302043b000000800230008c0000093b0000413d00000080023002700000061c0530009c000000000203a0190000061c0530009c0000000005000019000000100500203900000008065001bf000005e30720009c000000000605a0190000004005200270000005e30720009c000000000502a01900000004026001bf000005d30750009c000000000206a0190000002006500270000005d30750009c000000000605a01900000002052001bf0000ffff0760008c000000000502a0190000001002600270000000000206a019000000ff0220008c0000000105502039000000200200008a0000004106500039000000000226016f0000000602200029000000060620006c00000000060000190000000106004039000005e30720009c000013ce0000213d0000000106600190000013ce0000c13d000000400020043f000000020250003900000006060000290000000006260436000000000e00003100000021075000390000000507700272000008cd0000613d0000000008ed034f0000000009000019000000050a900210000000000ba60019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b000008c50000413d000000000700004b000008cf0000613d00000006020000290000000007020433000000000707004b000013d40000613d00000000070604330000061b07700197000000f808500210000000000778019f0000061d0770004100000000007604350000000305500210000000f80550008900000000035301cf000000ff0550008c0000000003002019000000060200002900000021052000390000094f0000013d00000618010000410000000000100439000005d3010000410000000002000414000005d30320009c0000000002018019000000c00120021000000619011001c70000800b020000391747173d0000040f0000000102200190000013da0000613d000000400400043d000000000101043b000000800210008c000009fd0000413d00000080021002700000061c0310009c000000000201a0190000061c0310009c0000000003000019000000100300203900000008053001bf000005e30620009c000000000503a0190000004003200270000005e30620009c000000000302a01900000004025001bf000005d30630009c000000000205a0190000002006300270000005d30530009c000000000603a01900000002052001bf0000ffff0360008c000000000502a0190000001002600270000000000206a019000000ff0220008c0000000105502039000000200200008a0000004103500039000000000223016f0000000002240019000000000342004b00000000030000190000000103004039000005e30620009c000000070f000029000013ce0000213d0000000103300190000013ce0000c13d000000400020043f00000002025000390000000006240436000600020000036b000000000300003100000021075000390000000507700272000009280000613d000000060830035f0000000009000019000000050a900210000000000ba60019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b000009200000413d000500000003001d000000000200004b0000092b0000613d0000000007040433000000000707004b000013d40000613d00000000070604330000061b07700197000000f808500210000000000778019f0000061d0770004100000000007604350000000305500210000000f80550008900000000015101cf000000ff0550008c0000000001002019000000210540003900000a120000013d00000006020000290000061a0220009c000013ce0000213d00000006050000290000004002500039000000400020043f000000010200003a0000000005250436000000000e0000310000000006ed034f0000000006600350000000000606043b0000000000650435000013d40000613d000000f807300210000005e408000041000000000303004b000000000807c0190000061b03600197000000000383019f0000000000350435000000400300043d000000600440008a00000000054d034f000000000505043b000000800650008c00000a600000413d00000080065002700000061c0750009c000000000605a0190000061c0750009c0000000007000019000000100700203900000008087001bf000005e30960009c000000000807a0190000004007600270000005e30960009c000000000706a01900000004098001bf000005d30670009c000000000908a0190000002008700270000005d30670009c000000000807a01900000002069001bf0000ffff0780008c000000000609a0190000001007800270000000000708a019000000ff0770008c0000000106602039000000200700008a0000004108600039000000000778016f0000000007730019000000000837004b00000000080000190000000108004039000005e30970009c000013ce0000213d0000000108800190000013ce0000c13d000000400070043f00000002076000390000000007730436000000210860003900000005088002720000098a0000613d0000000009ed034f000000000a000019000000050ba00210000000000cb70019000000000bb9034f000000000b0b043b0000000000bc0435000000010aa00039000000000b8a004b000009820000413d000000000800004b0000098c0000613d0000000008030433000000000808004b000013d40000613d00000000080704330000061b08800197000000f809600210000000000889019f0000061d0880004100000000008704350000000306600210000000f80660008900000000056501cf000000ff0660008c0000000005002019000000210630003900000a710000013d0000061a0240009c000000070f000029000013ce0000213d0000004002400039000000400020043f000000010200003a00000000052404360000000202000367000600000000003500000000062003680000000006600350000000000606043b0000000000650435000013d40000613d000000f807100210000005e408000041000000000101004b000000000807c0190000061b01600197000000000181019f0000000000150435000000400500043d0000010007f00039000000000172034f000000000601043b000000800160008c000000060120036000000abe0000413d00000080086002700000061c0960009c000000000806a0190000061c0960009c00000000090000190000001009002039000000080a9001bf000005e30b80009c000000000a09a0190000004009800270000005e30b80009c000000000908a019000000040ba001bf000005d30890009c000000000b0aa019000000200a900270000005d30890009c000000000a09a0190000000208b001bf0000ffff09a0008c00000000080ba0190000001009a0027000000000090aa019000000ff0990008c0000000108802039000000200900008a000000410a80003900000000099a016f0000000009950019000000000a59004b000000000a000019000000010a004039000005e30b90009c000013ce0000213d000000010aa00190000013ce0000c13d000000400090043f00000002098000390000000009950436000000210a800039000000050aa00272000009eb0000613d000000000b000019000000050cb00210000000000dc90019000000000cc1034f000000000c0c043b0000000000cd0435000000010bb00039000000000cab004b000009e30000413d000000000300004b000009ed0000613d000000000a050433000000000a0a004b000013d40000613d000000000a0904330000061b0aa00197000000f80b800210000000000aab019f0000061d0aa000410000000000a904350000000308800210000000f80880008900000000068601cf000000ff0880008c0000000006002019000000210850003900000ace0000013d0000061a0240009c000000070f000029000013ce0000213d0000004002400039000000400020043f000000010200003a000000000524043600000002020003670006000000020353000500000000003500000000062003680000000006600350000000000606043b0000000000650435000013d40000613d000000f807100210000005e408000041000000000101004b000000000807c0190000061b01600197000000000181019f0000000000150435000000400500043d0000010007f00039000000060170035f000000000601043b000000800160008c0000000501000029000000060110035f00000b1a0000413d00000080086002700000061c0960009c000000000806a0190000061c0960009c00000000090000190000001009002039000000080a9001bf000005e30b80009c000000000a09a0190000004009800270000005e30b80009c000000000908a019000000040ba001bf000005d30890009c000000000b0aa019000000200a900270000005d30890009c000000000a09a0190000000208b001bf0000ffff09a0008c00000000080ba0190000001009a0027000000000090aa019000000ff0990008c0000000108802039000000200900008a000000410a80003900000000099a016f0000000009950019000000000a59004b000000000a000019000000010a004039000005e30b90009c000013ce0000213d000000010aa00190000013ce0000c13d000000400090043f00000002098000390000000009950436000000210a800039000000050aa0027200000a4e0000613d000000000b000019000000050cb00210000000000dc90019000000000cc1034f000000000c0c043b0000000000cd0435000000010bb00039000000000cab004b00000a460000413d000000000200004b00000a500000613d000000000a050433000000000a0a004b000013d40000613d000000000a0904330000061b0aa00197000000f80b800210000000000aab019f0000061d0aa000410000000000a904350000000308800210000000f80880008900000000068601cf000000ff0880008c0000000006002019000000210850003900000b2a0000013d0000061a0630009c000013ce0000213d0000004006300039000000400060043f0000000007ed034f000000010600003a00000000066304360000000007700350000000000707043b0000000000760435000013d40000613d000000f808500210000005e409000041000000000505004b000000000908c0190000061b05700197000000000595019f0000000000560435000000400440008a00000000054d034f000000400400043d000000000505043b000000800650008c00000b760000413d00000080065002700000061c0750009c000000000605a0190000061c0750009c0000000007000019000000100700203900000008087001bf000005e30960009c000000000807a0190000004007600270000005e30960009c000000000706a01900000004098001bf000005d30670009c000000000908a0190000002008700270000005d30670009c000000000807a01900000002069001bf0000ffff0780008c000000000609a0190000001007800270000000000708a019000000ff0770008c0000000106602039000000200700008a0000004108600039000000000778016f0000000007740019000000000847004b00000000080000190000000108004039000005e30970009c000013ce0000213d0000000108800190000013ce0000c13d000000400070043f000000020760003900000000077404360000002108600039000000050880027200000aac0000613d0000000009ed034f000000000a000019000000050ba00210000000000cb70019000000000bb9034f000000000b0b043b0000000000bc0435000000010aa00039000000000b8a004b00000aa40000413d000000000800004b00000aae0000613d0000000008040433000000000808004b000013d40000613d00000000080704330000061b08800197000000f809600210000000000889019f0000061d0880004100000000008704350000000306600210000000f80660008900000000056501cf000000ff0660008c0000000005002019000000210640003900000b870000013d0000061a0850009c000013ce0000213d0000004008500039000000400080043f000000010800003a00000000088504360000000009100350000000000909043b0000000000980435000013d40000613d000000f80a600210000005e40b000041000000000606004b000000000b0ac0190000061b069001970000000006b6019f0000000000680435000000400600043d000000600770008a000000000872034f000000000808043b000000800980008c00000c150000413d00000080098002700000061c0a80009c000000000908a0190000061c0a80009c000000000a000019000000100a002039000000080ba001bf000005e30c90009c000000000b0aa019000000400a900270000005e30c90009c000000000a09a019000000040cb001bf000005d309a0009c000000000c0ba019000000200ba00270000005d309a0009c000000000b0aa0190000000209c001bf0000ffff0ab0008c00000000090ca019000000100ab00270000000000a0ba019000000ff0aa0008c0000000109902039000000200a00008a000000410b900039000000000aab016f000000000aa60019000000000b6a004b000000000b000019000000010b004039000005e30ca0009c000013ce0000213d000000010bb00190000013ce0000c13d0000004000a0043f000000020a900039000000000aa60436000000210b900039000000050bb0027200000b080000613d000000000c000019000000050dc00210000000000eda0019000000000dd1034f000000000d0d043b0000000000de0435000000010cc00039000000000dbc004b00000b000000413d000000000300004b00000b0a0000613d000000000b060433000000000b0b004b000013d40000613d000000000b0a04330000061b0bb00197000000f80c900210000000000bbc019f0000061d0bb000410000000000ba04350000000309900210000000f80990008900000000089801cf000000ff0990008c0000000008002019000000210960003900000c250000013d0000061a0850009c000013ce0000213d0000004008500039000000400080043f000000010800003a00000000088504360000000009100350000000000909043b0000000000980435000013d40000613d000000f80a600210000005e40b000041000000000606004b000000000b0ac0190000061b069001970000000006b6019f0000000000680435000000400600043d000000400870008a000000060780035f000000000707043b000000800970008c00000c720000413d00000080097002700000061c0a70009c000000000907a0190000061c0a70009c000000000a000019000000100a002039000000080ba001bf000005e30c90009c000000000b0aa019000000400a900270000005e30c90009c000000000a09a019000000040cb001bf000005d309a0009c000000000c0ba019000000200ba00270000005d309a0009c000000000b0aa0190000000209c001bf0000ffff0ab0008c00000000090ca019000000100ab00270000000000a0ba019000000ff0aa0008c0000000109902039000000200a00008a000000410b900039000000000aab016f000000000aa60019000000000b6a004b000000000b000019000000010b004039000005e30ca0009c000013ce0000213d000000010bb00190000013ce0000c13d0000004000a0043f000000020a900039000000000aa60436000000210b900039000000050bb0027200000b640000613d000000000c000019000000050dc00210000000000eda0019000000000dd1034f000000000d0d043b0000000000de0435000000010cc00039000000000dbc004b00000b5c0000413d000000000200004b00000b660000613d000000000b060433000000000b0b004b000013d40000613d000000000b0a04330000061b0bb00197000000f80c900210000000000bbc019f0000061d0bb000410000000000ba04350000000309900210000000f80990008900000000079701cf000000ff0990008c0000000007002019000000210960003900000c820000013d0000061a0640009c000013ce0000213d0000004006400039000000400060043f0000000007ed034f000000010600003a00000000066404360000000007700350000000000707043b0000000000760435000013d40000613d000000f808500210000005e409000041000000000505004b000000000908c0190000061b05700197000000000595019f0000000000560435000000400500043d000200000005001d00000020065000390000000005030433000000000705004b00000b960000613d000000000700001900000000086700190000002007700039000000000937001900000000090904330000000000980435000000000857004b00000b8f0000413d000000000365001900000000000304350000000006040433000000000706004b00000ba30000613d000000000700001900000000083700190000002007700039000000000947001900000000090904330000000000980435000000000867004b00000b9c0000413d000000000336001900000000000304350000000003560019000000020400002900000000003404350000003f03300039000000200200008a000000000323016f0000000004430019000000000334004b00000000030000190000000103004039000500000004001d000005e30440009c000013ce0000213d0000000103300190000013ce0000c13d0000000503000029000000400030043f0000061a0330009c000013ce0000213d000000400310003900000000033d034f000000000303043b00000005060000290000004004600039000000400040043f00000020046000390000061e05000041000000000054043500000015040000390000000000460435000000600330021000000021046000390000000000340435000001200310003900000000043d034f000000400900043d000000000404043b000000800540008c000400000009001d00000d9b0000413d00000080054002700000061c0640009c000000000504a0190000061c0640009c0000000006000019000000100600203900000008076001bf000005e30850009c000000000706a0190000004006500270000005e30850009c000000000605a01900000004087001bf000005d30560009c000000000807a0190000002007600270000005d30560009c000000000706a01900000002058001bf0000ffff0670008c000000000508a0190000001006700270000000000607a019000000ff0660008c00000001055020390000004106500039000000000626016f0000000006690019000000000796004b00000000070000190000000107004039000005e30860009c000013ce0000213d0000000107700190000013ce0000c13d000000400060043f0000000206500039000000040700002900000000066704360000002107500039000000050770027200000c010000613d0000000008ed034f0000000009000019000000050a900210000000000ba60019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b00000bf90000413d000000000700004b00000c030000613d00000004070000290000000007070433000000000707004b000013d40000613d00000000070604330000061b07700197000000f808500210000000000778019f0000061d0770004100000000007604350000000305500210000000f80550008900000000045401cf000000ff0550008c00000000040020190000000405000029000000210550003900000dad0000013d0000061a0960009c000013ce0000213d0000004009600039000000400090043f000000010900003a0000000009960436000000000a100350000000000a0a043b0000000000a90435000013d40000613d000000f80b800210000005e40c000041000000000808004b000000000c0bc0190000061b08a001970000000008c8019f0000000000890435000000400800043d000000400770008a000000000972034f000000000909043b000000800a90008c00000ccf0000413d000000800a9002700000061c0b90009c000000000a09a0190000061c0b90009c000000000b000019000000100b002039000000080cb001bf000005e30da0009c000000000c0ba019000000400ba00270000005e30da0009c000000000b0aa019000000040dc001bf000005d30ab0009c000000000d0ca019000000200cb00270000005d30ab0009c000000000c0ba019000000020ad001bf0000ffff0bc0008c000000000a0da019000000100bc00270000000000b0ca019000000ff0bb0008c000000010aa02039000000200b00008a000000410ca00039000000000bbc016f000000000bb80019000000000c8b004b000000000c000019000000010c004039000005e30db0009c000013ce0000213d000000010cc00190000013ce0000c13d0000004000b0043f000000020ba00039000000000bb80436000000210ca00039000000050cc0027200000c5f0000613d000000000d000019000000050ed00210000000000feb0019000000000ee1034f000000000e0e043b0000000000ef0435000000010dd00039000000000ecd004b00000c570000413d000000000300004b00000c610000613d000000000c080433000000000c0c004b000000070f000029000013d40000613d000000000c0b04330000061b0cc00197000000f80da00210000000000ccd019f0000061d0cc000410000000000cb0435000000030aa00210000000f80aa000890000000009a901cf000000ff0aa0008c0000000009002019000000210a80003900000cdf0000013d0000061a0960009c000013ce0000213d0000004009600039000000400090043f000000010900003a0000000009960436000000000a100350000000000a0a043b0000000000a90435000013d40000613d000000f80b700210000005e40c000041000000000707004b000000000c0bc0190000061b07a001970000000007c7019f0000000000790435000000400700043d000000200880008a000000060980035f000000000909043b000000800a90008c00000d3d0000413d000000800a9002700000061c0b90009c000000000a09a0190000061c0b90009c000000000b000019000000100b002039000000080cb001bf000005e30da0009c000000000c0ba019000000400ba00270000005e30da0009c000000000b0aa019000000040dc001bf000005d30ab0009c000000000d0ca019000000200cb00270000005d30ab0009c000000000c0ba019000000020ad001bf0000ffff0bc0008c000000000a0da019000000100bc00270000000000b0ca019000000ff0bb0008c000000010aa02039000000200b00008a000000410ca00039000000000bbc016f000000000bb70019000000000c7b004b000000000c000019000000010c004039000005e30db0009c000013ce0000213d000000010cc00190000013ce0000c13d0000004000b0043f000000020ba00039000000000bb70436000000210ca00039000000050cc0027200000cbc0000613d000000000d000019000000050ed00210000000000feb0019000000000ee1034f000000000e0e043b0000000000ef0435000000010dd00039000000000ecd004b00000cb40000413d000000000200004b00000cbe0000613d000000000c070433000000000c0c004b000000070f000029000013d40000613d000000000c0b04330000061b0cc00197000000f80da00210000000000ccd019f0000061d0cc000410000000000cb0435000000030aa00210000000f80aa000890000000009a901cf000000ff0aa0008c0000000009002019000000210a70003900000d4d0000013d0000061a0a80009c000013ce0000213d000000400a8000390000004000a0043f000000010a00003a000000000aa80436000000000b100350000000000b0b043b0000000000ba0435000013d40000613d000000f80c900210000005e40d000041000000000909004b000000000d0cc0190000061b09b001970000000009d9019f00000000009a0435000000400a00043d0000061a09a0009c000013ce0000213d000000200970008a000000000992034f000000000909043b000000400ba000390000004000b0043f000000200ba000390000061e0c0000410000000000cb0435000000150b0000390000000000ba04350000006009900210000000210ba0003900000000009b0435000000c007700039000000000772034f000000400900043d000000000707043b000000800b70008c00000e630000413d000000800b7002700000061c0c70009c000000000b07a0190000061c0c70009c000000000c000019000000100c002039000000080dc001bf000005e30eb0009c000000000d0ca019000000400cb00270000005e30eb0009c000000000c0ba019000000040ed001bf000005d30bc0009c000000000e0da019000000200dc00270000005d30bc0009c000000000d0ca019000000020be001bf0000ffff0cd0008c000000000b0ea019000000100cd00270000000000c0da019000000ff0cc0008c000000010bb02039000000200c00008a000000410db00039000000000ccd016f000000000cc90019000000000d9c004b000000000d000019000000010d004039000005e30ec0009c000013ce0000213d000000010dd00190000013ce0000c13d0000004000c0043f000000020cb00039000000000cc90436000000210db00039000000050dd0027200000d290000613d000000000e000019000000050fe002100000000003fc0019000000000ff1034f000000000f0f043b0000000000f30435000000010ee000390000000003de004b00000d210000413d000000000300004b00000d2b0000613d0000000003090433000000000303004b000000070f000029000013d40000613d00000000030c04330000061b03300197000000f80db0021000000000033d019f0000061d0330004100000000003c04350000000303b00210000000f80330008900000000073701cf000000ff0330008c00000000070020190000002103900039000000000073043500000e740000013d0000061a0a70009c000013ce0000213d000000400a7000390000004000a0043f000000010a00003a000000000aa70436000000000b100350000000000b0b043b0000000000ba0435000013d40000613d000000f80c900210000005e40d000041000000000909004b000000000d0cc0190000061b09b001970000000009d9019f00000000009a0435000000400900043d000000400880008a000000060a80035f000000000a0a043b000000800ba0008c00000df50000413d000000800ba002700000061c0ca0009c000000000b0aa0190000061c0ca0009c000000000c000019000000100c002039000000080dc001bf000005e30eb0009c000000000d0ca019000000400cb00270000005e30eb0009c000000000c0ba019000000040ed001bf000005d30bc0009c000000000e0da019000000200dc00270000005d30bc0009c000000000d0ca019000000020be001bf0000ffff0cd0008c000000000b0ea019000000100cd00270000000000c0da019000000ff0cc0008c000000010bb02039000000200c00008a000000410db00039000000000ccd016f000000000cc90019000000000d9c004b000000000d000019000000010d004039000005e30ec0009c000013ce0000213d000000010dd00190000013ce0000c13d0000004000c0043f000000020cb00039000000000cc90436000000210db00039000000050dd0027200000d870000613d000000000e000019000000050fe002100000000003fc0019000000000ff1034f000000000f0f043b0000000000f30435000000010ee000390000000003de004b00000d7f0000413d000000000200004b00000d890000613d0000000003090433000000000303004b000000070f000029000013d40000613d00000000030c04330000061b03300197000000f80db0021000000000033d019f0000061d0330004100000000003c04350000000303b00210000000f803300089000000000a3a01cf000000ff0330008c000000000a00201900000021039000390000000000a3043500000e060000013d0000061a0590009c000013ce0000213d00000004070000290000004005700039000000400050043f0000000006ed034f000000010500003a00000000055704360000000006600350000000000606043b0000000000650435000013d40000613d000000f807400210000005e408000041000000000404004b000000000807c0190000061b04600197000000000484019f0000000000450435000000a00330003900000000043d034f000000000404043b000000000f0e001900000000051e00490000001f0550008a000005e406500197000005e407400197000005e408000041000000000967004b00000000090000190000000009084019000000000667013f000000000754004b0000000008004019000005e40660009c000000000908c019000000000609004b000013d20000c13d000000000714001900000000067d034f000000000606043b000005e30860009c000013d20000213d00000000086f00490000002007700039000005e409000041000000000a87004b000000000a000019000000000a092019000005e408800197000005e40b700197000000000c8b004b000000000900801900000000088b013f000005e40880009c00000000090ac019000000000809004b000013d20000c13d000000010860008c000000000c02001900000fee0000c13d00000000067d034f000000000606043b000000010700008a000005e408000041000000000776004b00000000070000190000000007082019000005e406600197000005e40960009c0000000008008019000005e406600167000005e40660009c000000000807c019000300600000003d000000000608004b000010780000c13d000000400600043d000300000006001d0000061a0660009c000013ce0000213d00000003080000290000004006800039000000400060043f00000020068000390000061d07000041000000000076043500000001060000390000000000680435000010780000013d0000061a0390009c000013ce0000213d0000004003900039000000400030043f000000010300003a000000000b3904360000000003100350000000000c03043b0000000000cb0435000013d40000613d000000f803a00210000005e40d000041000000000a0a004b000000000d03c0190000061b03c001970000000003d3019f00000000003b0435000000400b00043d0000061a03b0009c000013ce0000213d000000200380008a000000060330035f000000000303043b000000400ab000390000004000a0043f000000200ab000390000061e0c0000410000000000ca0435000000150a0000390000000000ab04350000006003300210000000210ab0003900000000003a0435000000c003800039000000060330035f000000400a00043d000000000803043b000000800380008c00000f210000413d00000080038002700000061c0c80009c000000000308a0190000061c0c80009c000000000c000019000000100c002039000000080dc001bf000005e30e30009c000000000d0ca019000000400c300270000005e30e30009c000000000c03a0190000000403d001bf000005d30ec0009c00000000030da019000000200dc00270000005d30ec0009c000000000d0ca019000000020c3001bf0000ffff0ed0008c000000000c03a0190000001003d0027000000000030da019000000ff0330008c000000010cc02039000000200300008a000000410dc0003900000000033d016f000000000d3a00190000000003ad004b000000000e000019000000010e004039000005e303d0009c000013ce0000213d0000000103e00190000013ce0000c13d0000004000d0043f0000000203c00039000000000d3a04360000002103c00039000000050e30027200000e4f0000613d000000000f0000190000000503f0021000000000023d0019000000000331034f000000000303043b0000000000320435000000010ff000390000000002ef004b00000e470000413d000000000200004b00000e510000613d00000000020a0433000000000202004b000000070f000029000013d40000613d00000000020d04330000061b02200197000000f803c00210000000000223019f0000061d0220004100000000002d04350000000302c00210000000f80220008900000000032801cf000000ff0220008c00000000030020190000002102a00039000000000032043500000f320000013d0000061a0390009c000013ce0000213d0000004003900039000000400030043f000000010300003a000000000b3904360000000003100350000000000c03043b0000000000cb0435000013d40000613d000000f803700210000005e40d000041000000000707004b000000000d03c0190000061b03c001970000000003d3019f00000000003b0435000000400700043d000000200c700039000000000b04043300000000030b004b00000e810000613d000000000d0000190000000003cd0019000000200dd00039000000000e4d0019000000000e0e04330000000000e304350000000003bd004b00000e7a0000413d0000000003cb0019000000000003043500000000047b0019000000200c400039000000000b05043300000000030b004b00000e900000613d000000000d0000190000000003cd0019000000200dd00039000000000e5d0019000000000e0e04330000000000e304350000000003bd004b00000e890000413d0000000003cb0019000000000003043500000000044b0019000000200b4000390000000005060433000000000305004b00000e9f0000613d000000000c0000190000000003bc0019000000200cc00039000000000d6c0019000000000d0d04330000000000d3043500000000035c004b00000e980000413d0000000003b500190000000000030435000000000445001900000020064000390000000005080433000000000305004b00000eae0000613d000000000b00001900000000036b0019000000200bb00039000000000c8b0019000000000c0c04330000000000c3043500000000035b004b00000ea70000413d000000000365001900000000000304350000000004450019000000200640003900000000050a0433000000000305004b00000ebd0000613d000000000800001900000000036800190000002008800039000000000ba80019000000000b0b04330000000000b30435000000000358004b00000eb60000413d00000000036500190000000000030435000000000445001900000020064000390000000005090433000000000305004b00000ecc0000613d000000000800001900000000036800190000002008800039000000000a980019000000000a0a04330000000000a30435000000000358004b00000ec50000413d000000000365001900000000000304350000000003740049000000000335001900000000003704350000003f03300039000000200400008a000000000343016f0000000008730019000000000338004b00000000050000190000000105004039000005e30380009c000013ce0000213d0000000103500190000013ce0000c13d000000400080043f000001c003f00039000000000332034f000000060c0000290000000005fc00490000001f0650008a000000000503043b000005e403000041000000000965004b00000000090000190000000009034019000005e406600197000005e40a500197000000000b6a004b000000000300a01900000000066a013f000005e40660009c000000000309c019000000000303004b000013d20000613d0000000006f50019000000000362034f000000000503043b000005e30350009c000013d20000213d00000000095c00490000002003600039000005e406000041000000000a93004b000000000a000019000000000a062019000005e409900197000005e40b300197000000000c9b004b000000000600801900000000099b013f000005e40990009c00000000060ac019000000000606004b000013d20000c13d000000010650008c000000000232034f000010190000c13d000000000302043b000000010600008a000005e409000041000000000663004b00000000060000190000000006092019000005e403300197000005e40a30009c0000000009008019000005e403300167000005e40330009c000000000906c0190000006006000039000000000309004b0000123e0000c13d0000061a0380009c000013ce0000213d0000004003800039000000400030043f00000020038000390000061d0600004100000000006304350000000103000039000000000038043500000000060800190000123e0000013d0000061a02a0009c000013ce0000213d0000004002a00039000000400020043f000000010200003a000000000c2a04360000000002100350000000000d02043b0000000000dc0435000013d40000613d000000f802800210000005e403000041000000000808004b000000000302c0190000061b02d00197000000000232019f00000000002c0435000000400800043d000000200d800039000000000c04043300000000020c004b00000f3f0000613d000000000e0000190000000002de0019000000200ee0003900000000034e0019000000000303043300000000003204350000000002ce004b00000f380000413d0000000002dc0019000000000002043500000000048c0019000000200d400039000000000c05043300000000020c004b00000f4e0000613d000000000e0000190000000002de0019000000200ee0003900000000035e0019000000000303043300000000003204350000000002ce004b00000f470000413d0000000002dc0019000000000002043500000000044c0019000000200c4000390000000005060433000000000205004b00000f5d0000613d000000000d0000190000000002cd0019000000200dd0003900000000036d00190000000003030433000000000032043500000000025d004b00000f560000413d0000000002c500190000000000020435000000000445001900000020064000390000000005070433000000000205004b00000f6c0000613d000000000c00001900000000026c0019000000200cc0003900000000037c00190000000003030433000000000032043500000000025c004b00000f650000413d00000000026500190000000000020435000000000445001900000020064000390000000005090433000000000205004b00000f7b0000613d000000000700001900000000026700190000002007700039000000000397001900000000030304330000000000320435000000000257004b00000f740000413d000000000265001900000000000204350000000004450019000000200640003900000000050b0433000000000205004b00000f8a0000613d0000000007000019000000000267001900000020077000390000000003b7001900000000030304330000000000320435000000000257004b00000f830000413d000000000265001900000000000204350000000004450019000000200640003900000000050a0433000000000205004b00000f990000613d0000000007000019000000000267001900000020077000390000000003a7001900000000030304330000000000320435000000000257004b00000f920000413d000000000265001900000000000204350000000002840049000000000225001900000000002804350000003f02200039000000200400008a000000000242016f0000000007820019000000000227004b00000000050000190000000105004039000005e30270009c000013ce0000213d0000000102500190000013ce0000c13d000000400070043f000001c002f00039000000060220035f000000050b0000290000000003fb00490000001f0330008a000000000502043b000005e402000041000000000635004b00000000060000190000000006028019000005e403300197000005e409500197000000000a39004b0000000002008019000000000339013f000005e40330009c000000000206c019000000000202004b000013d20000c13d0000000006f50019000000060260035f000000000502043b000005e30250009c000013d20000213d00000000025b00490000002003600039000005e406000041000000000923004b00000000090000190000000009062019000005e402200197000005e40a300197000000000b2a004b000000000600801900000000022a013f000005e40220009c000000000609c019000000000206004b000013d20000c13d000000010250008c000000060230035f000010400000c13d000000000302043b000000010600008a000005e409000041000000000663004b00000000060000190000000006092019000005e403300197000005e40a30009c0000000009008019000005e403300167000005e40330009c000000000906c0190000006006000039000000000309004b000013060000c13d0000061a0370009c000013ce0000213d0000004003700039000000400030043f00000020037000390000061d060000410000000000630435000000010300003900000000003704350000000006070019000013060000013d000000400b00043d000000380760008c00030000000b001d000010670000413d0000002008600270000005d30760009c000000000806a019000005d30760009c0000000009000019000000040900203900000002079001bf0000ffff0a80008c000000000709a0190000001009800270000000000908a019000000ff0890008c000000000800001900000001080020390000061a09b0009c000013ce0000213d000000000787019f000000030a0000290000004008a00039000000400080043f0000000009fd034f000000020870003a00000000088a04360000000009900350000000000909043b0000000000980435000013d40000613d0000061b09900197000000f80a70021000000000099a019f0000061f099001c700000000009804350000000307700210000000f80770015f00000000067601cf000000030700002900000021077000390000000000670435000010780000013d000000380350008c0000122e0000413d0000002006500270000005d30350009c000000000605a019000005d30350009c0000000009000019000000040900203900000002039001bf0000ffff0a60008c000000000309a0190000001009600270000000000906a019000000ff0690008c000000000600001900000001060020390000061a0980009c000013ce0000213d000000000363019f0000004006800039000000400060043f000000020630003a00000000066804360000000009100350000000000909043b0000000000960435000013d40000613d0000061b09900197000000f80a30021000000000099a019f0000061f099001c700000000009604350000000303300210000000f80330015f00000000033501cf0000002106800039000000000036043500000000060800190000123e0000013d000000380350008c000012f60000413d0000002006500270000005d30350009c000000000605a019000005d30350009c0000000009000019000000040900203900000002039001bf0000ffff0a60008c000000000309a0190000001009600270000000000906a019000000ff0690008c000000000600001900000001060020390000061a0970009c000013ce0000213d000000000363019f0000004006700039000000400060043f000000020630003a00000000066704360000000009100350000000000909043b0000000000960435000013d40000613d0000061b09900197000000f80a30021000000000099a019f0000061f099001c700000000009604350000000303300210000000f80330015f00000000033501cf000000210670003900000000003604350000000006070019000013060000013d0000061a07b0009c000013ce0000213d00000003090000290000004007900039000000400070043f0000000008fd034f000000010700003a00000000077904360000000008800350000000000808043b0000000000870435000013d40000613d000000f8066002100000061b08800197000000000668019f000005e4066001670000000000670435000000800330008a00000000063d034f0000006003000039000000000606043b000000000606004b0000110f0000613d00010000000c001d00000618010000410000000000100439000005d3010000410000000002000414000005d30320009c0000000002018019000000c00120021000000619011001c70000800b020000391747173d0000040f0000000102200190000013da0000613d000000400400043d000000000301043b000000800130008c000000010c000029000010d80000413d00000080013002700000061c0230009c000000000103a0190000061c0230009c0000000002000019000000100200203900000008052001bf000005e30610009c000000000502a0190000004002100270000005e30610009c000000000201a01900000004015001bf000005d30620009c000000000105a0190000002006200270000005d30520009c000000000602a01900000002051001bf0000ffff0260008c000000000501a0190000001001600270000000000106a019000000ff0110008c000000010550203900000041015000390000000001c1016f0000000007140019000000000247004b00000000020000190000000102004039000005e30670009c0000000701000029000013ce0000213d0000000102200190000013ce0000c13d000000400070043f00000002025000390000000006240436000000020d000367000000000f00003100000021075000390000000507700272000010c60000613d0000000008fd034f0000000009000019000000050a900210000000000ba60019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b000010be0000413d000000000700004b000010c80000613d0000000007040433000000000707004b000013d40000613d00000000070604330000061b07700197000000f808500210000000000778019f0000061d0770004100000000007604350000000305500210000000f80550008900000000035301cf000000ff0550008c00000000030020190000002105400039000010ec0000013d0000061a0140009c0000000701000029000013ce0000213d0000004002400039000000400020043f000000010200003a0000000005240436000000000f000031000000020d0003670000000006fd034f0000000006600350000000000606043b0000000000650435000013d40000613d000000f807300210000005e408000041000000000303004b000000000807c0190000061b03600197000000000383019f0000000000350435000000400300043d00000020063000390000000005040433000000000705004b000010fa0000613d000000000700001900000000086700190000002007700039000000000947001900000000090904330000000000980435000000000857004b000010f30000413d00000000046500190000062c0600004100000000006404350000000204500039000000000043043500000041045000390000000005c4016f0000000004350019000000000554004b00000000050000190000000105004039000005e30640009c000013ce0000213d0000000105500190000013ce0000c13d000001c005100039000000400040043f00000000045d034f00000000051f00490000001f0550008a000000000404043b00000000020f0019000000000f0c0019000005e406000041000000000754004b00000000070000190000000007068019000005e405500197000005e408400197000000000958004b0000000006008019000000000558013f000005e40550009c000000000607c019000000000506004b000013d20000c13d000000060500002900000000060504330000000205000029000000000705043300000005050000290000000008050433000000040500002900000000090504330000000305000029000000000a050433000000000114001900000000041d034f000000000404043b000005e30b40009c000013d20000213d0000000005020019000000000b450049000000200e100039000005e40c00004100000000010d034f000000000dbe004b000000000d000019000000000d0c2019000005e40bb0019700010000000e001d000005e40ee00197000700000004001d00000000040f0019000000000fbe004b000000000f0400190000000704000029000000000c008019000000000bbe013f000000060e000029000005e40bb0009c000000000c0dc019000000000b0c004b000013d20000c13d0000000006670019000000000686001900000000069600190000000006a60019000000000646001900000000070304330000000006760019000000400700043d000005e306600197000000380860008c000011740000413d0000002009600270000005d30860009c000000000906a019000005d30860009c000000000a000019000000040a0020390000000208a001bf0000ffff0b90008c00000000080aa019000000100a900270000000000a09a019000000ff09a0008c000000000900001900000001090020390000061a0a70009c000013ce0000213d000000000898019f0000004009700039000000400090043f000000000951034f000000020280003a00000000022704360000000009900350000000000909043b0000000000920435000013d40000613d0000061b09900197000000f80a80021000000000099a019f00000621099001c700000000009204350000000302800210000000f80220015f00000000022601cf00000021067000390000000000260435000011840000013d0000061a0870009c000013ce0000213d0000004008700039000000400080043f000000000851034f000000010200003a00000000022704360000000008800350000000000808043b0000000000820435000013d40000613d0000061b08800197000000f806600210000000000686019f00000620066000410000000000620435000000400200043d00000020062000390000000008070433000000000908004b00000002040000290000000505000029000011930000613d0000000009000019000000000a6900190000002009900039000000000b790019000000000b0b04330000000000ba0435000000000a89004b0000118c0000413d000000000768001900000000000704350000000007280019000000200970003900000000080e0433000000000a08004b000011a20000613d000000000a000019000000000b9a0019000000200aa00039000000000cea0019000000000c0c04330000000000cb0435000000000b8a004b0000119b0000413d00000000099800190000000000090435000000000778001900000020097000390000000008040433000000000a08004b000011b10000613d000000000a000019000000000b9a0019000000200aa00039000000000c4a0019000000000c0c04330000000000cb0435000000000b8a004b000011aa0000413d00000000099800190000000000090435000000000778001900000020097000390000000008050433000000000a08004b000011c00000613d000000000a000019000000000b9a0019000000200aa00039000000000c5a0019000000000c0c04330000000000cb0435000000000b8a004b000011b90000413d000000000998001900000000000904350000000007780019000000200970003900000004040000290000000008040433000000000a08004b000011d00000613d000000000a000019000000000b9a0019000000200aa00039000000000c4a0019000000000c0c04330000000000cb0435000000000b8a004b000011c90000413d000000000998001900000000000904350000000007780019000000200970003900000003040000290000000008040433000000000a08004b000011e00000613d000000000a000019000000000b9a0019000000200aa00039000000000c4a0019000000000c0c04330000000000cb0435000000000b8a004b000011d90000413d000000000998001900000000000904350000000105100360000000000178001900000007040000290000001f0740018f00000020081000390000000509400272000011f20000613d000000000a000019000000050ba00210000000000cb80019000000000bb5034f000000000b0b043b0000000000bc0435000000010aa00039000000000b9a004b000011ea0000413d000000000a07004b000012010000613d0000000509900210000000000595034f00000000089800190000000307700210000000000908043300000000097901cf000000000979022f000000000505043b0000010007700089000000000575022f00000000057501cf000000000595019f00000000005804350000000001410019000000200510003900000000000504350000000004030433000000000704004b0000120f0000613d000000000700001900000000085700190000002007700039000000000937001900000000090904330000000000980435000000000847004b000012080000413d000000000354001900000000000304350000000001210049000000000114001900000000001204350000003f011000390000000003f1016f0000000001230019000000000331004b00000000030000190000000103004039000005e30410009c000013ce0000213d0000000103300190000013ce0000c13d000000400010043f000005d301000041000005d30360009c000000000601801900000040036002100000000002020433000005d30420009c00000000020180190000006002200210000000000232019f0000000003000414000005d30430009c0000000003018019000000c001300210000000000121019f000013c70000013d0000061a0380009c000013ce0000213d0000004003800039000000400030043f000000010300003a00000000033804360000000006100350000000000606043b0000000000630435000013d40000613d000000f8095002100000061b06600197000000000696019f000005e40660016700000000006304350000000006080019000000400300043d0000061a0830009c000013ce0000213d0000004008300039000000400080043f000000010b00003a0000000008b304360000000001100350000000000a01043b0000000000a80435000013d40000613d0000061b01a0019700000620091001c70000000000980435000000000807043300000000085800190000000009060433000000000898001900000000090304330000000008980019000000400900043d000005e308800197000000380c80008c000012780000413d000000200c800270000005d30b80009c000000000c08a019000005d30b80009c000000000d000019000000040d002039000000020bd001bf0000ffff0ec0008c000000000b0da019000000100dc00270000000000d0ca019000000ff0cd0008c000000000c000019000000010c0020390000061a0d90009c000013ce0000213d000000000bcb019f000000400c9000390000004000c0043f000000200c9000390000000000ac0435000000020ab0003a0000000000a90435000013d40000613d000000f80ab0021000000000011a019f00000621011001c700000000001c04350000000301b00210000000f80110015f00000000011801cf00000021089000390000000000180435000012850000013d0000061a0c90009c000013ce0000213d000000400c9000390000004000c0043f000000200c9000390000000000ac04350000000000b90435000000000a0b004b000013d40000613d000000f808800210000000000118019f000006200110004100000000001c0435000000400100043d0000002008100039000006160a0000410000000000a80435000000210b100039000000000a090433000000000c0a004b000012950000613d000000000c000019000000000dbc0019000000200cc00039000000000e9c0019000000000e0e04330000000000ed0435000000000dac004b0000128e0000413d0000000009ba0019000000000009043500000000091a0019000000210b900039000000000a070433000000000c0a004b000012a40000613d000000000c000019000000000dbc0019000000200cc00039000000000e7c0019000000000e0e04330000000000ed0435000000000dac004b0000129d0000413d0000000007ba0019000000000007043500000000079a0019000000210a7000390000000009060433000000000b09004b000012b30000613d000000000b000019000000000cab0019000000200bb00039000000000d6b0019000000000d0d04330000000000dc0435000000000c9b004b000012ac0000413d0000000006a90019000000000006043500000000067900190000001f0750018f0000002109600039000000050a500272000012c30000613d000000000b000019000000050cb00210000000000dc90019000000000cc2034f000000000c0c043b0000000000cd0435000000010bb00039000000000cab004b000012bb0000413d000000000b07004b000012d20000613d000000050aa002100000000002a2034f0000000009a900190000000307700210000000000a090433000000000a7a01cf000000000a7a022f000000000202043b0000010007700089000000000272022f00000000027201cf0000000002a2019f00000000002904350000000002560019000000210620003900000000000604350000000005030433000000000705004b000012e00000613d000000000700001900000000096700190000002007700039000000000a370019000000000a0a04330000000000a90435000000000957004b000012d90000413d0000000003650019000000000003043500000000021200490000000002250019000000010320003900000000003104350000004002200039000000000342016f0000000002130019000000000332004b00000000030000190000000103004039000005e30420009c000013ce0000213d0000000103300190000013ce0000c13d000000400020043f000005d302000041000005d30380009c00000000080280190000004003800210000013bd0000013d0000061a0370009c000013ce0000213d0000004003700039000000400030043f000000010300003a00000000033704360000000006100350000000000606043b0000000000630435000013d40000613d000000f8095002100000061b06600197000000000696019f000005e40660016700000000006304350000000006070019000000400300043d0000061a0730009c000013ce0000213d0000004007300039000000400070043f000000010b00003a0000000007b304360000000001100350000000000a01043b0000000000a70435000013d40000613d0000061b01a0019700000620091001c70000000000970435000000000708043300000000075700190000000009060433000000000797001900000000090304330000000007970019000000400900043d000005e307700197000000380c70008c000013400000413d000000200c700270000005d30b70009c000000000c07a019000005d30b70009c000000000d000019000000040d002039000000020bd001bf0000ffff0ec0008c000000000b0da019000000100dc00270000000000d0ca019000000ff0cd0008c000000000c000019000000010c0020390000061a0d90009c000013ce0000213d000000000bcb019f000000400c9000390000004000c0043f000000200c9000390000000000ac0435000000020ab0003a0000000000a90435000013d40000613d000000f80ab0021000000000011a019f00000621011001c700000000001c04350000000301b00210000000f80110015f00000000011701cf000000210790003900000000001704350000134d0000013d0000061a0c90009c000013ce0000213d000000400c9000390000004000c0043f000000200c9000390000000000ac04350000000000b90435000000000a0b004b000013d40000613d000000f807700210000000000117019f000006200110004100000000001c0435000000400100043d0000002007100039000005e90a0000410000000000a70435000000210b100039000000000a090433000000000c0a004b0000135d0000613d000000000c000019000000000dbc0019000000200cc00039000000000e9c0019000000000e0e04330000000000ed0435000000000dac004b000013560000413d0000000009ba0019000000000009043500000000091a0019000000210b900039000000000a080433000000000c0a004b0000136c0000613d000000000c000019000000000dbc0019000000200cc00039000000000e8c0019000000000e0e04330000000000ed0435000000000dac004b000013650000413d0000000008ba0019000000000008043500000000089a0019000000210a8000390000000009060433000000000b09004b0000137b0000613d000000000b000019000000000cab0019000000200bb00039000000000d6b0019000000000d0d04330000000000dc0435000000000c9b004b000013740000413d0000000006a90019000000000006043500000000068900190000001f0850018f0000002109600039000000050a5002720000138b0000613d000000000b000019000000050cb00210000000000dc90019000000000cc2034f000000000c0c043b0000000000cd0435000000010bb00039000000000cab004b000013830000413d000000000b08004b0000139a0000613d000000050aa002100000000002a2034f0000000009a900190000000308800210000000000a090433000000000a8a01cf000000000a8a022f000000000202043b0000010008800089000000000282022f00000000028201cf0000000002a2019f00000000002904350000000002560019000000210620003900000000000604350000000005030433000000000805004b000013a80000613d000000000800001900000000096800190000002008800039000000000a380019000000000a0a04330000000000a90435000000000958004b000013a10000413d0000000003650019000000000003043500000000021200490000000002250019000000010320003900000000003104350000004002200039000000000342016f0000000002130019000000000332004b00000000030000190000000103004039000005e30420009c000013ce0000213d0000000103300190000013ce0000c13d000000400020043f000005d302000041000005d30370009c000000000702801900000040037002100000000001010433000005d30410009c00000000010280190000006001100210000000000131019f0000000003000414000005d30430009c0000000003028019000000c002300210000000000112019f000005e9011001c700008010020000391747173d0000040f0000000102200190000013d20000613d000000000101043b000000000001042d000005e70100004100000000001004350000004101000039000013d70000013d00000000010000190000174900010430000005e70100004100000000001004350000003201000039000000040010043f000005e8010000410000174900010430000000000001042f000000400100043d00000044021000390000061703000041000000000032043500000024021000390000000803000039000013f30000013d000000400100043d00000044021000390000062403000041000000000032043500000024021000390000001f03000039000013f30000013d000005e70100004100000000001004350000001101000039000013d70000013d000000400100043d00000044021000390000062d030000410000000000320435000000240210003900000017030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ff011001c700001749000104300000001f0350018f00000005025002720000140a0000613d00000000040000190000000506400210000000000761034f000000000707043b00000000007604350000000104400039000000000624004b000014030000413d000000000403004b000014180000613d00000003033002100000000502200210000000000402043300000000043401cf000000000434022f000000000121034f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f0000000000120435000000600150021000001749000104300000001f0340018f0000000502400272000014250000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b0000141e0000413d000000000503004b000014330000613d00000003033002100000000502200210000000000502043300000000053501cf000000000535022f000000000121034f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f000000000012043500000060014002100000174900010430000000000403004b0000143f0000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000014380000413d00000000012300190000000000010435000000000001042d000000e0021000390000000201000367000000000321034f000000000303043b000005d5033001980000144c0000613d0000004002200039000000000121034f000000000101043b000014610000013d000000800320008a000000000331034f000000400220008a000000000521034f000000000403043b000000000505043b00000000634500a9000000000605004b000014580000613d00000000655300d9000000000445004b000014620000c13d0000008002200039000000000121034f000000000201043b0000000001320019000000000221004b000000000200001900000001020040390000000102200190000014620000c13d000000000001042d000005e70100004100000000001004350000001101000039000000040010043f000005e801000041000017490001043000000040031000390000000202000367000000000332034f0000012005100039000000000652034f000000000303043b000005d504300197000000000306043b0000062e0630009c0000154f0000813d000000a005500039000000000552034f000000000700003100000000061700490000001f0660008a000000000505043b000005e408000041000000000965004b00000000090000190000000009084019000005e406600197000005e40a500197000000000b6a004b000000000800a01900000000066a013f000005e40660009c000000000809c019000000000608004b0000154d0000613d0000000005150019000000000152034f000000000101043b000005e30610009c0000154d0000213d00000000061700490000002008500039000005e405000041000000000968004b00000000090000190000000009052019000005e406600197000005e40a800197000000000b6a004b000000000500801900000000066a013f000005e40660009c000000000509c019000000000505004b0000154d0000c13d0000003f05100039000000200600008a000000000565016f000000400600043d0000000005560019000000000965004b00000000090000190000000109004039000005e30a50009c000015610000213d0000000109900190000015610000c13d000000400050043f00000000051604360000000009810019000000000779004b0000154d0000213d000000000782034f0000001f0210018f0000000508100272000014b70000613d0000000009000019000000050a900210000000000ba50019000000000aa7034f000000000a0a043b0000000000ab04350000000109900039000000000a89004b000014af0000413d000000000902004b000014c60000613d0000000508800210000000000787034f00000000088500190000000302200210000000000908043300000000092901cf000000000929022f000000000707043b0000010002200089000000000727022f00000000022701cf000000000292019f000000000028043500000000011500190000000000010435000080060140008c000014df0000c13d0000000001000414000005d30210009c0000154f0000213d0000000002060433000005d30420009c0000154f0000213d000000c0011002100000060a0110019700000040045002100000061404400197000000000114019f00000060022002100000061502200197000000000121019f00000616011001c7000000000203004b000014f60000613d000080090200003900008006040000390000000105000039000014fa0000013d00000000020604330000000001000414000000040640008c0000154c0000613d000005d306000041000005d30750009c00000000050680190000004005500210000005d30720009c00000000020680190000006002200210000000000252019f000005d30510009c0000000001068019000000c001100210000000000112019f000000000203004b000015450000613d000005e9011001c700008009020000390000000005000019174717380000040f000015470000013d00008006020000390000000003000019000000000400001900000000050000190000000006000019174717380000040f000300000001035500000000030100190000006003300270000105d30030019d000005d3053001970000003f03500039000005d406300197000000400300043d0000000004360019000000000664004b00000000060000190000000106004039000005e30740009c000015610000213d0000000106600190000015610000c13d000000400040043f00000000045304360000001f0650003900000005066002720000151c0000613d0000000007000031000000020770036700000000080000190000000509800210000000000a940019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000015140000413d000000000600004b0000151e0000613d0000001f0650018f00000005055002720000152a0000613d000000000700001900000005087002100000000009840019000000000881034f000000000808043b00000000008904350000000107700039000000000857004b000015220000413d000000000706004b000015390000613d0000000505500210000000000151034f00000000055400190000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f000000000015043500000001012001900000154c0000c13d0000000001030433000005d302000041000005d30310009c0000000001028019000005d30340009c000000000402801900000040024002100000006001100210000000000121019f00001749000104300000000002040019174717380000040f00030000000103550000006001100270000105d30010019d00000001012001900000154d0000613d000000000001042d00000000010000190000174900010430000000400100043d000000440210003900000617030000410000000000320435000000240210003900000008030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ff011001c70000174900010430000005e70100004100000000001004350000004101000039000000040010043f000005e80100004100001749000104300009000000000002000000400600043d0000000003020433000000820330008c0000000003060019000015920000613d0000062f0260009c000016960000813d000000c002600039000000400020043f000000820200003900000000022604360000000003000031000000020330036700000000040000190000000505400210000000000553034f000000000505043b00000000025204360000000104400039000000050540008c000015760000413d0000000002060433000000400220008c000016c80000a13d000000600260003900000000030204330000061b0330019700000630033001c700000000003204350000000002060433000000820220008c000016c80000413d000000a10260003900000000030204330000061b0330019700000630033001c70000000000320435000000400300043d0000000002060433000000820220008c00000000020600190000170e0000c13d000005fa0430009c000016960000213d0000008004300039000000400040043f0000004105000039000000000953043600000000040000310000000204400367000000000600001900000000070900190000000508600210000000000884034f000000000808043b00000000078704360000000106600039000000030860008c0000159c0000413d000000400a00043d000005fa06a0009c000016960000213d0000008006a00039000000400060043f00000000085a0436000000000500001900000000060800190000000507500210000000000774034f000000000707043b00000000067604360000000105500039000000030750008c000015ab0000413d000000410420003900000000040404330000004005200039000000000605043300000020052000390000000005050433000000000059043500000040053000390000000000650435000000f806400210000000600430003900000000070404330000061b07700197000000000667019f00000000006404350000006106200039000000810720003900000082022000390000000002020433000000000707043300000000060604330000000000680435000000400ba0003900000000007b04350000006007a00039000000f80220021000000000060704330000061b06600197000000000226019f000200000007001d00000000002704350000000002030433000000410220008c0000169a0000c13d0000000006000415000000090660008a00000020066000c9000000000205043300000041033000390000000003030433000000ff0330018f0000001b0330008a000000010330008c0000000005000019000015f50000213d000006320320009c000015f10000213d00000000030a0433000000410330008c000015f10000c13d0000004103a000390000000003030433000000ff0330018f0000001b0330008a000000010330008c000015f10000213d0000060d050000410000000006000415000000080660008a00000020066000c900000000030b0433000006330330009c000015f50000413d0000000006000415000000080660008a00000020066000c90000000005000019000300000006001d00060000000b001d00070000000a001d000100000005001d000006320320009c000016a10000213d000400000008001d00000000030404330000000006090433000000400400043d0000006005400039000000000025043500000040024000390000000000620435000000f80330027000000020024000390000000000320435000500000001001d00000000001404350000000000000435000005d3010000410000000002000414000005d30320009c0000000002018019000005d30340009c00000000040180190000004001400210000000c002200210000000000112019f00000634011001c700000001020000391747173d0000040f00000000030100190000006003300270000005d303300197000000200430008c000000000403001900000020040080390000001f0540018f0000000504400272000016260000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000746004b0000161f0000413d000000000605004b000016340000613d00000003055002100000000504400210000000000604043300000000065601cf000000000656022f000000000741034f000000000707043b0000010005500089000000000757022f00000000055701cf000000000565019f0000000000540435000100000003001f000300000001035500000001022001900000000506000029000000040400002900000007050000290000000607000029000016ce0000613d0000000001000433000005d503100198000016b60000613d00000003020000290000000502200270000000000201001f0000000001050433000000410110008c0000169a0000c13d000700000003001d0000000001070433000006320210009c000016a10000213d000000020200002900000000020204330000000003040433000000400400043d0000006005400039000000000015043500000040014000390000000000310435000000f8012002700000002002400039000000000012043500000000006404350000000000000435000005d3010000410000000002000414000005d30320009c0000000002018019000005d30340009c00000000040180190000004001400210000000c002200210000000000112019f00000634011001c70000000102000039000600000002001d1747173d0000040f00000000030100190000006003300270000005d303300197000000200430008c000000000403001900000020040080390000001f0540018f0000000504400272000016740000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000746004b0000166d0000413d000000000605004b000016820000613d00000003055002100000000504400210000000000604043300000000065601cf000000000656022f000000000741034f000000000707043b0000010005500089000000000757022f00000000055701cf000000000565019f0000000000540435000100000003001f00030000000103550000000102200190000016eb0000613d0000000001000433000005d5021001980000000703000029000016b60000613d000000000100041a000005d501100197000000000113004b0000000001000019000016950000c13d0000000601000029000000000101041a000005d501100197000000000112004b00000000010000190000000101006029000000000001042d000005e70100004100000000001004350000004101000039000016cb0000013d000000400100043d00000044021000390000063503000041000000000032043500000024021000390000001f03000039000016bc0000013d000000400100043d000000640210003900000610030000410000000000320435000000440210003900000637030000410000000000320435000000240210003900000022030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ed011001c70000174900010430000000400100043d000000440210003900000636030000410000000000320435000000240210003900000018030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ff011001c70000174900010430000005e70100004100000000001004350000003201000039000000040010043f000005e8010000410000174900010430000000400200043d0000001f0430018f0000000505300272000016db0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000016d30000413d000000000604004b000017070000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000017070000013d000000400200043d0000001f0430018f0000000505300272000016f80000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000016f00000413d000000000604004b000017070000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005d301000041000005d30420009c000000000201801900000040012002100000006002300210000000000121019f000017490001043000000044013000390000063102000041000000000021043500000024013000390000000e020000390000000000210435000005ec010000410000000000130435000000040130003900000020020000390000000000210435000005d301000041000005d30230009c00000000030180190000004001300210000005ff011001c70000174900010430000000000001042f00000000050100190000000000200439000000040130008c000017270000a13d000000050140027000000000010100310000000400100443000005d3010000410000000002000414000005d30420009c0000000002018019000005d30430009c00000000030180190000006001300210000000c002200210000000000112019f00000638011001c700000000020500191747173d0000040f0000000102200190000017370000613d000000000101043b000000000001042d000000000001042f0000173b002104210000000102000039000000000001042d0000000002000019000000000001042d00001740002104230000000102000039000000000001042d0000000002000019000000000001042d00001745002104230000000102000039000000000001042d0000000002000019000000000001042d0000174700000432000017480001042e00001749000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000020000000000000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000a28c1aed00000000000000000000000000000000000000000000000000000000e2f318e200000000000000000000000000000000000000000000000000000000e2f318e300000000000000000000000000000000000000000000000000000000eeb8cb0900000000000000000000000000000000000000000000000000000000a28c1aee00000000000000000000000000000000000000000000000000000000df9c1589000000000000000000000000000000000000000000000000000000005270972400000000000000000000000000000000000000000000000000000000527097250000000000000000000000000000000000000000000000000000000073688914000000000000000000000000000000000000000000000000000000001626ba7e00000000000000000000000000000000000000000000000000000000202bcce7000000000000000000000000000000000000000000000000ffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000e1239cd8000000000000000000000000000000000000000000000000000000009cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f394e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000002000000000000000000000000000000000000000000000000000000000000007261746f720000000000000000000000000000000000000000000000000000004661696c656420746f20706179207468652066656520746f20746865206f706508c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000000949431dc000000000000000000000000000000000000000000000000000000008c5a344500000000000000000000000000000000000000000000000000000000dd62ed3e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000800000000000000000095ea7b3000000000000000000000000000000000000000000000000000000005361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65641806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000440000000000000000000000005361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f000000000000000000000000000000000000000000000000ffffffffffffff3f6f742073756363656564000000000000000000000000000000000000000000005361666545524332303a204552433230206f7065726174696f6e20646964206e416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000000000000000000000000000000000000000006400000000000000000000000054686520617070726f76616c4261736564207061796d617374657220696e707574206d757374206265206174206c65617374203638206279746573206c6f6e670000000000000000000000000000000000000084000000800000000000000000556e737570706f72746564207061796d617374657220666c6f770000000000000000000000000000000000000000000000000064000000800000000000000000546865207374616e64617264207061796d617374657220696e707574206d757374206265206174206c656173742034206279746573206c6f6e6700000000000000000000000000000000000000000000000000200000008000000000000000004f6e6c7920626f6f746c6f616465722063616e2063616c6c2074686973206d6574686f640000000000000000000000000000000000000000000000000000000000000000ffffffff0000000000000000000000000000000000000000000000000100000000000000000000000000000000000024000000a00000000000000000202bcce7000000000000000000000000000000000000000000000000000000001626ba7e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000001000000000000000075650000000000000000000000000000000000000000000000000000000000004e6f7420656e6f7567682062616c616e636520666f7220666565202b2076616c000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000ffffffff000000000000000000000000000000000000000000000000ffffffff00000000000000000000000001000000000000000000000000000000000000000000000000000000000000004f766572666c6f770000000000000000000000000000000000000000000000009a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b0200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000ffffffffffffffffffffffffffffffff81000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6b656363616b3235362072657475726e656420696e76616c6964206461746100848e1bfa1ac4e3576b728bda6721b215c70a7799a5b4866282a71bab954baac8000000000000000000000000000000000000000000000000fffffffffffffe1fc2f8787176b8ac6bf7215b4adcc1e069bf4ab82d9ab1df05a57a91d425935b6ead7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a519b453ce45aaaaf3a300f5a9ec95869b4f28ab10430b572ee218c3a6a5e07d6f000000000000000000000000000000000000000000000000ffffffffffffff5f19010000000000000000000000000000000000000000000000000000000000008080000000000000000000000000000000000000000000000000000000000000456e636f64696e6720756e737570706f727465642074780000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff401b00000000000000000000000000000000000000000000000000000000000000496e76616c6964206c656e6774680000000000000000000000000000000000007fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a07fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1000000000000000000000000000000000000008000000000000000000000000045434453413a20696e76616c6964207369676e6174757265206c656e6774680045434453413a20696e76616c6964207369676e6174757265000000000000000045434453413a20696e76616c6964207369676e6174757265202773272076616c020000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d448c295e929e696b285e58d46eeef7df7814594a3c50b601ee9abfe479ae5d", + "deployedBytecode": "0x0004000000000002000e00000000000200000000030100190000006003300270000005d30030019d000005d303300197000300000031035500020000000103550000000102200190000000b20000c13d000000800b0000390000004000b0043f000000040230008c000000e90000413d000000000201043b000000e002200270000005d80420009c000000f70000213d000005de0420009c000001090000213d000005e10420009c000001580000613d000005e20220009c000000eb0000c13d000000040230008a000000600220008c000002c00000413d0000004402100370000000000602043b000005e30260009c000002c00000213d00000004076000390000000002730049000005e403000041000002600420008c00000000040000190000000004034019000005e402200197000000000502004b000000000300a019000005e40220009c000000000304c019000000000203004b000002c00000c13d0000002402100370000000000302043b0000000002000411000080010220008c000001f80000c13d000a00000003001d000900000007001d0000000002000414000005e503000041000000a00030043f000800000006001d0000010403600039000000000131034f000000000101043b000000a40010043f0000002401000039000000800010043f000000e001000039000000400010043f000000c0012002100000060a011001970000060b011001c700008003020000390000000003000019000000000400001900000000050000190000000006000019174717380000040f000300000001035500000000030100190000006003300270000105d30030019d000005d3053001970000003f03500039000005d406300197000000400300043d0000000004360019000000000664004b00000000060000190000000106004039000005e30740009c0000041a0000213d00000001066001900000041a0000c13d000000400040043f00000000045304360000001f065000390000000506600272000000680000613d0000000007000031000000020770036700000000080000190000000509800210000000000a940019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000000600000413d000000000600004b0000006a0000613d0000001f0650018f0000000505500272000000760000613d000000000700001900000005087002100000000009840019000000000881034f000000000808043b00000000008904350000000107700039000000000857004b0000006e0000413d000000000706004b000000850000613d0000000505500210000000000151034f00000000055400190000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f00000000001504350000000101200190000002390000613d0000000a01000029000000000201004b0000008c0000c13d0000000901000029174706190000040f000a00000001001d0000000901000029174714420000040f0000000002000410000e00000002001d000700000001001d0000800a01000039000000240300003900000000040004150000000e0440008a00000020044000c9000005e602000041174717200000040f000000070110006b0000000001000019000000010100a039174705620000040f0000000801000029000001e40210003900000009010000291747057a0000040f0000000003000031174704ed0000040f00000000020100190000000a01000029174715670000040f000005ee011001970000060c020000410000060d0110009c000000000200c019000000400100043d0000000000210435000005d302000041000005d30310009c000000000102801900000040011002100000060e011001c7000017480001042e0000000002000416000000000202004b000002c00000c13d0000009f02300039000005d402200197000000400020043f0000001f0230018f0000000504300272000000c40000613d00000000050000190000000506500210000000000761034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b000000bc0000413d000000000502004b000000d30000613d0000000504400210000000000141034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f0000000000140435000000400130008c000002c00000413d000000800100043d000005d50210009c000002c00000213d000000a00200043d000005d50320009c000002c00000213d000000000300041a000005d603300197000000000113019f000000000010041b0000000101000039000000000301041a000005d603300197000000000223019f000000000021041b000000200100003900000100001004430000012000000443000005d701000041000017480001042e000000000103004b0000021e0000613d0000000001000416000000000101004b000002c00000c13d0000000001000411000080010110008c0000021e0000c13d000005e70100004100000000001004350000000101000039000000040010043f000005e8010000410000174900010430000005d90420009c000001120000213d000005dc0420009c000001830000613d000005dd0120009c000000eb0000c13d0000000001030019174705280000040f000a00000001001d0000000001000411000080010110008c000000000100001900000001010060391747054a0000040f0000000a01000029174714680000040f0000000001000019000017480001042e000005df0120009c000001cb0000613d000005e00120009c000000eb0000c13d0000000001000416000000000101004b000002c00000c13d000000000100041a000001d00000013d000005da0420009c000001d40000613d000005db0220009c000000eb0000c13d000000040230008a000000200220008c000002c00000413d0000000402100370000000000702043b000005e30270009c000002c00000213d00000004067000390000000002630049000005e403000041000002600420008c00000000040000190000000004034019000005e402200197000000000502004b000000000300a019000005e40220009c000000000304c019000000000203004b000002c00000c13d0000000002000414000005e503000041000000a00030043f0000010403700039000000000131034f000000000101043b000000a40010043f0000002401000039000700000001001d000000800010043f000000e001000039000000400010043f000005d3012001970000008002000039000a00000006001d000800000007001d174705a40000040f0000000a01000029174706190000040f000900000001001d0000000a01000029174714420000040f0000000002000410000b00000002001d000600000001001d0000800a0100003900000000040004150000000b0440008a00000020044000c9000005e6020000410000000703000029174717200000040f000000060110006b0000000001000019000000010100a039174705620000040f0000000801000029000001e4021000390000000a010000291747057a0000040f0000000003000031174704ed0000040f00000000020100190000000901000029174715670000040f000001050000013d0000000002000416000000000202004b000002c00000c13d000000040230008a000000400220008c000002c00000413d0000002402100370000000000402043b000005e30240009c000002c00000213d0000002302400039000005e405000041000000000632004b00000000060000190000000006058019000005e402200197000000000702004b0000000005008019000005e40220009c000000000506c019000000000205004b000002c00000c13d0000000402400039000000000121034f000000000201043b0000002401400039174704ed0000040f00000004020000390000000202200367000000000202043b000000000301001900000000010200190000000002030019174715670000040f000005ee01100197000000400200043d0000000000120435000005d301000041000005d30320009c000000000201801900000040012002100000060e011001c7000017480001042e000000040230008a000000600220008c000002c00000413d0000004402100370000000000202043b000005e30420009c000002c00000213d00000004042000390000000005430049000005e406000041000002600750008c00000000070000190000000007064019000005e408500197000000000908004b000000000600a019000005e40880009c000000000607c019000000000606004b000002c00000c13d0000000006000411000080010660008c000001f80000c13d0000022402200039000000000621034f000000000606043b0000001f0550008a000005e407000041000000000856004b00000000080000190000000008078019000005e405500197000005e409600197000000000a59004b0000000007008019000000000559013f000005e40550009c000000000708c019000000000507004b000002c00000c13d0000000005460019000000000451034f000000000404043b000005e30640009c000002c00000213d00000000064300490000002005500039000005e407000041000000000865004b00000000080000190000000008072019000005e406600197000005e409500197000000000a69004b0000000007008019000000000669013f000005e40660009c000000000708c019000000000607004b000002c00000c13d000000030640008c000002500000213d000005ec01000041000000800010043f0000002001000039000000840010043f0000003a01000039000000a40010043f0000060501000041000000c40010043f0000060601000041000002010000013d0000000001000416000000000101004b000002c00000c13d0000000101000039000000000101041a000005d501100197000000800010043f0000060701000041000017480001042e000000040330008a000000600230008c000002c00000413d0000004402100370000000000202043b000005e30420009c000002c00000213d0000000003230049000005e404000041000002600530008c00000000050000190000000005044019000005e403300197000000000603004b000000000400a019000005e40330009c000000000405c019000000000304004b000002c00000c13d0000000003000411000080010330008c000001f80000c13d000000a403200039000000000331034f0000006402200039000000000121034f000000000101043b000000000203043b000000000302004b000002040000c13d00000000040004150000000d0440008a00000020044000c90000000001000414000d00000000001d0000020f0000013d000005ec01000041000000800010043f0000002001000039000000840010043f0000002401000039000000a40010043f0000060801000041000000c40010043f0000060901000041000000e40010043f0000060201000041000017490001043000000000431200a900000000422300d9000000000112004b000002350000c13d00000000040004150000000c0440008a00000020044000c90000000001000414000c00000000001d000000000203004b000002430000c13d000a00000004001d000005d302000041000005d30310009c0000000001028019000000c0011002100000800102000039174717380000040f0000000a0300002900030000000103550000006001100270000105d30010019d000000050130027000000001012001950000000101200190000002200000613d0000000001000019000017480001042e000000400100043d0000006402100039000005ea0300004100000000003204350000004402100039000005eb030000410000000000320435000000240210003900000025030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ed011001c70000174900010430000005e70100004100000000001004350000001101000039000000f40000013d0000000001030433000005d302000041000005d30310009c0000000001028019000005d30340009c000000000402801900000040024002100000006001100210000000000121019f0000174900010430000005d302000041000005d30410009c0000000001028019000000c001100210000005e9011001c7000080090200003900008001040000390000000005000019174717380000040f00000000030004150000000c0330008a00000020033000c9000002170000013d000a0000000b001d000000000651034f000000000606043b000005ee06600197000005ef0760009c000002620000613d000005f00160009c0000021e0000613d000005ec01000041000000800010043f0000002001000039000000840010043f0000001a01000039000000a40010043f0000060301000041000000c40010043f00000604010000410000174900010430000000430440008c0000026e0000213d000005ec01000041000000800010043f0000002001000039000000840010043f0000004001000039000000a40010043f0000060001000041000000c40010043f0000060101000041000002010000013d0000000404500039000000000541034f000000000505043b000900000005001d000005d50550009c000002c00000213d000001400220008a000000000221034f0000002004400039000000000441034f000000000404043b000800000004001d000000000202043b000005f104000041000000800040043f0000000004000410000005d504400197000600000004001d000000840040043f000005d502200197000700000002001d000000a40020043f00000000020004140000000904000029000000040440008c0000028e0000c13d000000000131034f0000000103000031000000200230008c00000000040300190000002004008039000002ba0000013d000005d301000041000005d30320009c0000000002018019000000c001200210000005f2011001c700000009020000291747173d0000040f00000000030100190000006003300270000005d303300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000002a70000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b0000029f0000413d000000000705004b000002b60000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000002e40000613d0000001f02400039000000600520018f00000080025001bf000000400020043f000000200430008c000002c20000813d00000000010000190000174900010430000000800400043d000000080440006c0000021e0000813d000000a004500039000005f3060000410000000000640435000000a40650003900000007070000290000000000760435000000c40650003900000000000604350000004406000039000100000006001d00000000006204350000014006500039000000400060043f0000012007500039000005f406000041000300000007001d000000000067043500000100065001bf0000002005000039000400000005001d000200000006001d0000000000560435000000000502043300000000020004140000000906000029000000040660008c000003070000c13d0000000102000039000005e30430009c0000041a0000213d0000031b0000013d000000400200043d0000001f0430018f0000000505300272000002f10000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000002e90000413d000000000604004b000003000000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005d301000041000005d30420009c000000000201801900000040012002100000006002300210000000000121019f0000174900010430000005d301000041000005d30350009c000000000501801900000060035002100000004004400210000000000343019f000005d30420009c0000000002018019000000c001200210000000000113019f0000000902000029174717380000040f000500600000003d000000010220018f000300000001035500000000030100190000006003300270000105d30030019d000005d303300198000003470000613d0000003f04300039000000200500008a000000000454016f000000400500043d0000000004450019000500000005001d000000000554004b00000000050000190000000105004039000005e30640009c0000041a0000213d00000001055001900000041a0000c13d000000400040043f0000001f0430018f000000050500002900000000083504360000000503300272000003370000613d000000000500001900000005065002100000000007680019000000000661034f000000000606043b00000000006704350000000105500039000000000635004b0000032f0000413d000a00000008001d000000000504004b000003470000613d0000000503300210000000000131034f0000000a033000290000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000013043500000005010000290000000001010433000000000202004b000003660000c13d000000000201004b000003610000c13d000000400400043d000a00000004001d000005ec01000041000000000014043500000004014000390000000402000029000000000021043500000002010000290000000003010433000900000003001d0000002401400039000000000031043500000044024000390000000301000029174714350000040f00000009010000290000001f01100039000000200200008a000000000121016f0000004401100039000005d302000041000005d30310009c00000000010280190000000a040000290000023d0000013d000000000201004b0000038f0000c13d000005f501000041000000000010043900000009010000290000000400100443000005d3010000410000000002000414000005d30320009c0000000002018019000000c001200210000005f6011001c700008002020000391747173d0000040f0000000102200190000004e70000613d000000000101043b000000000101004b0000038b0000c13d000000400100043d0000004402100039000005fe03000041000000000032043500000024021000390000001d030000390000000000320435000005ec020000410000000000210435000000040210003900000004030000290000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ff011001c7000017490001043000000005010000290000000001010433000000000201004b000003b20000613d000005e402000041000000200310008c00000000030000190000000003024019000005e401100197000000000401004b000000000200a019000005e40110009c000000000203c019000000000102004b0000000a01000029000002c00000c13d0000000001010433000000000201004b0000000002000019000000010200c039000000000221004b000002c00000c13d000000000101004b000003b20000c13d000000400100043d0000006402100039000005fc0300004100000000003204350000004402100039000005fd03000041000000000032043500000024021000390000002a030000390000000000320435000005ec020000410000000000210435000000040210003900000004030000290000022e0000013d000000400300043d000000240130003900000007020000290000000000210435000005f1010000410000000000130435000a00000003001d00000004013000390000000602000029000000000021043500000000010004140000000902000029000000040220008c000003c50000c13d0000000103000031000000200130008c00000000040300190000002004008039000003f70000013d000005d302000041000005d30310009c00000000010280190000000a04000029000005d30340009c00000000020440190000004002200210000000c001100210000000000121019f000005f7011001c700000009020000291747173d0000040f0000000a0a00002900000000030100190000006003300270000005d303300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000003e40000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000003dc0000413d000000000705004b000003f30000613d0000000506600210000000000761034f0000000a066000290000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f000300000001035500000001022001900000041e0000613d0000001f01400039000000600210018f0000000a01200029000000000221004b00000000020000190000000102004039000005e30410009c0000041a0000213d00000001022001900000041a0000c13d000000400010043f000000200230008c000002c00000413d000000440410003900000024051000390000000a020000290000000002020433000000000202004b0000043b0000c13d0000002002100039000005f3060000410000000000620435000000070600002900000000006504350000000805000029000000000054043500000001040000290000000000410435000005fa0410009c0000041a0000213d0000008004100039000a00000004001d000000400040043f000005fb0410009c000004470000a13d000005e70100004100000000001004350000004101000039000000f40000013d000000400200043d0000001f0430018f00000005053002720000042b0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000004230000413d000000000604004b0000043a0000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000003000000013d000005ec02000041000000000021043500000004021000390000000403000029000000000032043500000036020000390000000000250435000005f80200004100000000002404350000006402100039000005f9030000410000022e0000013d000000c004100039000000400040043f00000004040000290000000a050000290000000000450435000000a005100039000005f404000041000700000005001d0000000000450435000000000401043300000000010004140000000905000029000000040550008c000004590000c13d0000000102000039000005e30130009c0000041a0000213d0000046f0000013d000005d303000041000005d30520009c00000000020380190000004002200210000005d30540009c00000000040380190000006004400210000000000224019f000005d30410009c0000000001038019000000c001100210000000000112019f0000000902000029174717380000040f000800600000003d000600800000003d000000010220018f00030000000103550000006001100270000105d30010019d000005d3031001980000049c0000613d0000003f01300039000000200400008a000000000141016f000000400400043d0000000001140019000800000004001d000000000441004b00000000040000190000000104004039000005e30510009c0000041a0000213d00000001044001900000041a0000c13d000000400010043f0000001f0130018f00000008040000290000000008340436000000030400036700000005033002720000048c0000613d000000000500001900000005065002100000000007680019000000000664034f000000000606043b00000000006704350000000105500039000000000635004b000004840000413d000600000008001d000000000501004b0000049c0000613d0000000503300210000000000434034f00000006033000290000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f000000000013043500000008010000290000000001010433000000000202004b000004bb0000c13d000000000201004b000004e80000c13d000000400400043d000900000004001d000005ec0100004100000000001404350000000401400039000000040200002900000000002104350000000a010000290000000003010433000a00000003001d0000002401400039000000000031043500000044024000390000000701000029174714350000040f0000000a010000290000001f01100039000000200200008a000000000121016f0000004401100039000005d302000041000005d30310009c000000000102801900000009040000290000023d0000013d000000000201004b000004d20000c13d000005f501000041000000000010043900000009010000290000000400100443000005d3010000410000000002000414000005d30320009c0000000002018019000000c001200210000005f6011001c700008002020000391747173d0000040f0000000102200190000004e70000613d000000000101043b000000000101004b000003790000613d00000008010000290000000001010433000000000201004b0000021e0000613d000005e402000041000000200310008c00000000030000190000000003024019000005e401100197000000000401004b000000000200a019000005e40110009c000000000203c019000000000102004b000002c00000c13d00000006010000290000000001010433000000000201004b0000000002000019000000010200c039000000000221004b000002c00000c13d000000000101004b0000021e0000c13d000003a30000013d000000000001042f000005d302000041000005d30310009c000000000102801900000006040000290000023d0000013d00000000040100190000060f0120009c000005200000813d0000003f01200039000000200500008a000000000551016f000000400100043d0000000005510019000000000615004b00000000060000190000000106004039000005e30750009c000005200000213d0000000106600190000005200000c13d000000400050043f00000000052104360000000006420019000000000336004b000005260000213d0000001f0320018f000000020440036700000005062002720000050e0000613d000000000700001900000005087002100000000009850019000000000884034f000000000808043b00000000008904350000000107700039000000000867004b000005060000413d000000000703004b0000051d0000613d0000000506600210000000000464034f00000000066500190000000303300210000000000706043300000000073701cf000000000737022f000000000404043b0000010003300089000000000434022f00000000033401cf000000000373019f000000000036043500000000022500190000000000020435000000000001042d000005e70100004100000000001004350000004101000039000000040010043f000005e801000041000017490001043000000000010000190000174900010430000000040210008a000005e4030000410000005f0420008c00000000040000190000000004032019000005e402200197000000000502004b0000000003008019000005e40220009c000000000304c019000000000203004b000005480000613d00000044020000390000000202200367000000000202043b000005e30320009c000005480000213d00000004022000390000000001210049000005e403000041000002600410008c00000000040000190000000004034019000005e401100197000000000501004b000000000300a019000005e40110009c000000000304c019000000000103004b000005480000c13d0000000001020019000000000001042d00000000010000190000174900010430000000000101004b0000054d0000613d000000000001042d000000400100043d000000640210003900000609030000410000000000320435000000440210003900000608030000410000000000320435000000240210003900000024030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ed011001c70000174900010430000000000101004b000005650000613d000000000001042d000000400100043d000000640210003900000610030000410000000000320435000000440210003900000611030000410000000000320435000000240210003900000022030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ed011001c70000174900010430000000000300003100000000041300490000001f0540008a0000000204000367000000000224034f000000000202043b000005e406000041000000000752004b00000000070000190000000007064019000005e405500197000005e408200197000000000958004b000000000600a019000000000558013f000005e40550009c000000000607c019000000000506004b000005a20000613d0000000001120019000000000214034f000000000202043b000005e30420009c000005a20000213d00000000032300490000002001100039000005e404000041000000000531004b00000000050000190000000005042019000005e403300197000005e406100197000000000736004b0000000004008019000000000336013f000005e40330009c000000000405c019000000000304004b000005a20000c13d000000000001042d000000000100001900001749000104300000000003020433000006120430009c000005f70000813d000000c0011002100000060a01100197000000400220021000000613022000410000061402200197000000000121019f00000060023002100000061502200197000000000121019f00000616011001c700008003020000390000000003000019000000000400001900000000050000190000000006000019174717380000040f000300000001035500000000030100190000006003300270000105d30030019d000005d3053001970000003f03500039000005d406300197000000400300043d0000000004360019000000000664004b00000000060000190000000106004039000005e30740009c000006090000213d0000000106600190000006090000c13d000000400040043f00000000045304360000001f065000390000000506600272000005d70000613d0000000007000031000000020770036700000000080000190000000509800210000000000a940019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000005cf0000413d000000000600004b000005d90000613d0000001f0650018f0000000505500272000005e50000613d000000000700001900000005087002100000000009840019000000000881034f000000000808043b00000000008904350000000107700039000000000857004b000005dd0000413d000000000706004b000005f40000613d0000000505500210000000000151034f00000000055400190000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f000000000015043500000001012001900000060f0000613d000000000001042d000000400100043d000000440210003900000617030000410000000000320435000000240210003900000008030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ff011001c70000174900010430000005e70100004100000000001004350000004101000039000000040010043f000005e80100004100001749000104300000000001030433000005d302000041000005d30310009c0000000001028019000005d30340009c000000000402801900000040024002100000006001100210000000000121019f00001749000104300007000000000002000000020d00036700000000021d034f000000000202043b000000010320008c000700000001001d0000067e0000213d000000000302004b000008900000613d000000010120008c000013ed0000c13d00000618010000410000000000100439000005d3010000410000000002000414000005d30320009c0000000002018019000000c00120021000000619011001c70000800b020000391747173d0000040f0000000102200190000013da0000613d000000400400043d000000000101043b000000800210008c0000099c0000413d00000080021002700000061c0310009c000000000201a0190000061c0310009c0000000003000019000000100300203900000008053001bf000005e30620009c000000000503a0190000004003200270000005e30620009c000000000302a01900000004025001bf000005d30630009c000000000205a0190000002006300270000005d30530009c000000000603a01900000002052001bf0000ffff0360008c000000000502a0190000001002600270000000000206a019000000ff0220008c0000000105502039000000200200008a0000004103500039000000000223016f0000000002240019000000000342004b00000000030000190000000103004039000005e30620009c000000070f000029000013ce0000213d0000000103300190000013ce0000c13d000000400020043f0000000202500039000000000624043600000002020003670000000003000031000000210750003900000005077002720000066b0000613d000000000832034f0000000009000019000000050a900210000000000ba60019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b000006630000413d000600000003001d000000000300004b0000066e0000613d0000000007040433000000000707004b000013d40000613d00000000070604330000061b07700197000000f808500210000000000778019f0000061d0770004100000000007604350000000305500210000000f80550008900000000015101cf000000ff0550008c00000000010020190000002105400039000009b00000013d000000020320008c000008e10000613d000000710220008c000013ed0000c13d000001c00210003900000000032d034f000000000200003100000000041200490000001f0440008a000000000303043b000005e405000041000000000643004b00000000060000190000000006058019000005e404400197000005e407300197000000000847004b0000000005008019000000000447013f000005e40440009c000000000506c019000000000405004b000013d20000c13d000000000313001900000000043d034f000000000504043b000005e30450009c000013d20000213d00000000045200490000002003300039000005e406000041000000000743004b00000000070000190000000007062019000005e404400197000005e408300197000000000948004b0000000006008019000000000448013f000005e40440009c000000000607c019000000000406004b000013d20000c13d0000000004000414000000000605004b000006b70000613d0000000006350019000000000556004b000000000500001900000001050040390000000105500190000013e90000c13d000000000562004b000013e90000413d0000000002620049000005d303300197000000000d3d034f000006120340009c000013db0000813d000005d30220019700000000012d03df000000c0024002100000060a0220019700000622022001c700000000012103af0000801002000039174717420000040f00000000030100190000006003300270000105d30030019d000005d30530019700030000000103550000000102200190000013ff0000613d0000003f02500039000005d402200197000000400600043d0000000002260019000000000362004b00000000030000190000000103004039000005e30420009c000000070c000029000013ce0000213d0000000103300190000013ce0000c13d000000400020043f0000000004560436000000020200036700000000030000310000001f075000390000000507700272000006e50000613d000000000832034f0000000009000019000000050a900210000000000ba40019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b000006dd0000413d000000000700004b000006e70000613d0000001f0750018f0000000505500272000006f30000613d00000000080000190000000509800210000000000a940019000000000991034f000000000909043b00000000009a04350000000108800039000000000958004b000006eb0000413d000000000807004b000007020000613d0000000505500210000000000151034f00000000055400190000000307700210000000000805043300000000087801cf000000000878022f000000000101043b0000010007700089000000000171022f00000000017101cf000000000181019f00000000001504350000000001060433000000200110008c000013e20000c13d0000000001c300490000001f0510008a000002000ac000390000000001a2034f000000000101043b000005e406000041000000000751004b00000000070000190000000007068019000005e405500197000005e408100197000000000958004b0000000006008019000000000558013f000005e40550009c000000000607c019000000000506004b000013d20000c13d0000000004040433000500000004001d0000000001c10019000000000412034f000000000504043b000005e30450009c000013d20000213d000000050450021000000000034300490000002006100039000005e401000041000000000736004b00000000070000190000000007012019000005e403300197000005e408600197000000000938004b0000000001008019000000000338013f000005e40330009c000000000107c019000000000101004b000013d20000c13d000000400100043d000000200310003900000623055001980000073c0000613d000000000262034f000000000600001900000005076002100000000008730019000000000772034f000000000707043b00000000007804350000000106600039000000000756004b000007340000413d00060000000a001d000000000200004b0000073f0000613d00000000004104350000003f02400039000000200400008a000000000242016f0000000002210019000000000412004b00000000040000190000000104004039000005e30520009c000013ce0000213d0000000104400190000013ce0000c13d000000400020043f000005d302000041000005d30430009c000000000302801900000040033002100000000001010433000005d30410009c00000000010280190000006001100210000000000131019f0000000003000414000005d30430009c0000000003028019000000c002300210000000000112019f000005e9011001c700008010020000391747173d0000040f000000070a00002900000001022001900000000604000029000013d20000613d00000000020000310000000003a200490000001f0530008a00000020044000390000000203000367000000000443034f000000000404043b000005e406000041000000000754004b00000000070000190000000007068019000005e405500197000005e408400197000000000958004b0000000006008019000000000558013f000005e40550009c000000000607c019000000000b01043b000000000106004b000013d20000c13d0000000001a40019000000000413034f000000000504043b000005e30450009c000013d20000213d00000000045200490000002001100039000005e406000041000000000741004b00000000070000190000000007062019000005e404400197000005e408100197000000000948004b0000000006008019000000000448013f000005e40440009c000000000607c019000000000406004b000013d20000c13d0000000004000414000000000605004b000007980000613d0000000006150019000000000556004b000000000500001900000001050040390000000105500190000013e90000c13d000000000562004b000013e90000413d0000000002620049000005d301100197000000000313034f00060000000b001d000005d30140009c000013db0000213d000005d30120019700000000011303df000000c0024002100000060a0220019700000622022001c700000000012103af0000801002000039174717420000040f00000000030100190000006003300270000105d30030019d000005d304300197000300000001035500000001022001900000141a0000613d0000003f02400039000005d402200197000000400500043d0000000002250019000000000352004b00000000030000190000000103004039000005e30620009c000000070c000029000013ce0000213d0000000103300190000013ce0000c13d000000400020043f000000000245043600000002030003670000001f064000390000000506600272000007c60000613d000000000730036800000000080000190000000509800210000000000a920019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000007be0000413d000000000600004b000007c80000613d0000001f0640018f0000000504400272000007d40000613d000000000700001900000005087002100000000009820019000000000881034f000000000808043b00000000008904350000000107700039000000000847004b000007cc0000413d000000000706004b000007e30000613d0000000504400210000000000141034f00000000044200190000000306600210000000000704043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f00000000001404350000000001050433000000200110008c000013e20000c13d0000006001c00039000000000113034f0000004004c00039000000000543034f0000002004c00039000000000443034f0000012006c00039000000000663034f0000010007c00039000000000773034f000000e008c00039000000000883034f000000c009c00039000000000993034f000000a00ac00039000000000aa3034f000000800bc00039000000000bb3034f0000000003c3034f000000000303043b000000000404043b000000000505043b000000000c01043b000000000b0b043b000000000a0a043b000000000909043b000000000808043b000000000707043b000000000606043b0000000002020433000000400100043d000001c00d10003900000000002d0435000001a002100039000000060d0000290000000000d204350000018002100039000000050d0000290000000000d2043500000160021000390000000000620435000001400210003900000000007204350000012002100039000000000082043500000100021000390000000000920435000000e0021000390000000000a20435000000c0021000390000000000b20435000000a0021000390000000000c20435000000800210003900000000005204350000006002100039000000000042043500000040021000390000000000320435000000200210003900000625030000410000000000320435000001c0030000390000000000310435000006260310009c000013ce0000213d000001e003100039000000400030043f000005d304000041000005d30320009c000000000204801900000040022002100000000001010433000005d30310009c00000000010480190000006001100210000000000121019f0000000002000414000005d30320009c0000000002048019000000c002200210000000000112019f000005e9011001c700008010020000391747173d0000040f0000000102200190000013d20000613d000000000101043b000600000001001d000000400100043d000700000001001d000006180100004100000000001004390000000001000414000005d30210009c000005d301008041000000c00110021000000619011001c70000800b020000391747173d0000040f0000000102200190000013da0000613d00000007040000290000002002400039000000000101043b0000062703000041000000000032043500000080034000390000000000130435000000600140003900000628030000410000000000310435000000400140003900000629030000410000000000310435000000800100003900000000001404350000062a0140009c000013ce0000213d000000a001400039000000400010043f000005d301000041000005d30320009c000000000201801900000040022002100000000003040433000005d30430009c00000000030180190000006003300210000000000223019f0000000003000414000005d30430009c0000000003018019000000c001300210000000000121019f000005e9011001c700008010020000391747173d0000040f0000000102200190000013d20000613d000000000301043b000000400100043d00000042021000390000000604000029000000000042043500000020021000390000062b0400004100000000004204350000002204100039000000000034043500000042030000390000000000310435000005fa0310009c000013ce0000213d0000008003100039000000400030043f000005d303000041000005d30420009c000000000203801900000040022002100000000001010433000005d30410009c00000000010380190000006001100210000000000121019f0000000002000414000005d30420009c0000000002038019000000c002200210000013c60000013d000000400200043d000600000002001d000001000410003900000000024d034f000000000302043b000000800230008c0000093b0000413d00000080023002700000061c0530009c000000000203a0190000061c0530009c0000000005000019000000100500203900000008065001bf000005e30720009c000000000605a0190000004005200270000005e30720009c000000000502a01900000004026001bf000005d30750009c000000000206a0190000002006500270000005d30750009c000000000605a01900000002052001bf0000ffff0760008c000000000502a0190000001002600270000000000206a019000000ff0220008c0000000105502039000000200200008a0000004106500039000000000226016f0000000602200029000000060620006c00000000060000190000000106004039000005e30720009c000013ce0000213d0000000106600190000013ce0000c13d000000400020043f000000020250003900000006060000290000000006260436000000000e00003100000021075000390000000507700272000008cd0000613d0000000008ed034f0000000009000019000000050a900210000000000ba60019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b000008c50000413d000000000700004b000008cf0000613d00000006020000290000000007020433000000000707004b000013d40000613d00000000070604330000061b07700197000000f808500210000000000778019f0000061d0770004100000000007604350000000305500210000000f80550008900000000035301cf000000ff0550008c0000000003002019000000060200002900000021052000390000094f0000013d00000618010000410000000000100439000005d3010000410000000002000414000005d30320009c0000000002018019000000c00120021000000619011001c70000800b020000391747173d0000040f0000000102200190000013da0000613d000000400400043d000000000101043b000000800210008c000009fd0000413d00000080021002700000061c0310009c000000000201a0190000061c0310009c0000000003000019000000100300203900000008053001bf000005e30620009c000000000503a0190000004003200270000005e30620009c000000000302a01900000004025001bf000005d30630009c000000000205a0190000002006300270000005d30530009c000000000603a01900000002052001bf0000ffff0360008c000000000502a0190000001002600270000000000206a019000000ff0220008c0000000105502039000000200200008a0000004103500039000000000223016f0000000002240019000000000342004b00000000030000190000000103004039000005e30620009c000000070f000029000013ce0000213d0000000103300190000013ce0000c13d000000400020043f00000002025000390000000006240436000600020000036b000000000300003100000021075000390000000507700272000009280000613d000000060830035f0000000009000019000000050a900210000000000ba60019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b000009200000413d000500000003001d000000000200004b0000092b0000613d0000000007040433000000000707004b000013d40000613d00000000070604330000061b07700197000000f808500210000000000778019f0000061d0770004100000000007604350000000305500210000000f80550008900000000015101cf000000ff0550008c0000000001002019000000210540003900000a120000013d00000006020000290000061a0220009c000013ce0000213d00000006050000290000004002500039000000400020043f000000010200003a0000000005250436000000000e0000310000000006ed034f0000000006600350000000000606043b0000000000650435000013d40000613d000000f807300210000005e408000041000000000303004b000000000807c0190000061b03600197000000000383019f0000000000350435000000400300043d000000600440008a00000000054d034f000000000505043b000000800650008c00000a600000413d00000080065002700000061c0750009c000000000605a0190000061c0750009c0000000007000019000000100700203900000008087001bf000005e30960009c000000000807a0190000004007600270000005e30960009c000000000706a01900000004098001bf000005d30670009c000000000908a0190000002008700270000005d30670009c000000000807a01900000002069001bf0000ffff0780008c000000000609a0190000001007800270000000000708a019000000ff0770008c0000000106602039000000200700008a0000004108600039000000000778016f0000000007730019000000000837004b00000000080000190000000108004039000005e30970009c000013ce0000213d0000000108800190000013ce0000c13d000000400070043f00000002076000390000000007730436000000210860003900000005088002720000098a0000613d0000000009ed034f000000000a000019000000050ba00210000000000cb70019000000000bb9034f000000000b0b043b0000000000bc0435000000010aa00039000000000b8a004b000009820000413d000000000800004b0000098c0000613d0000000008030433000000000808004b000013d40000613d00000000080704330000061b08800197000000f809600210000000000889019f0000061d0880004100000000008704350000000306600210000000f80660008900000000056501cf000000ff0660008c0000000005002019000000210630003900000a710000013d0000061a0240009c000000070f000029000013ce0000213d0000004002400039000000400020043f000000010200003a00000000052404360000000202000367000600000000003500000000062003680000000006600350000000000606043b0000000000650435000013d40000613d000000f807100210000005e408000041000000000101004b000000000807c0190000061b01600197000000000181019f0000000000150435000000400500043d0000010007f00039000000000172034f000000000601043b000000800160008c000000060120036000000abe0000413d00000080086002700000061c0960009c000000000806a0190000061c0960009c00000000090000190000001009002039000000080a9001bf000005e30b80009c000000000a09a0190000004009800270000005e30b80009c000000000908a019000000040ba001bf000005d30890009c000000000b0aa019000000200a900270000005d30890009c000000000a09a0190000000208b001bf0000ffff09a0008c00000000080ba0190000001009a0027000000000090aa019000000ff0990008c0000000108802039000000200900008a000000410a80003900000000099a016f0000000009950019000000000a59004b000000000a000019000000010a004039000005e30b90009c000013ce0000213d000000010aa00190000013ce0000c13d000000400090043f00000002098000390000000009950436000000210a800039000000050aa00272000009eb0000613d000000000b000019000000050cb00210000000000dc90019000000000cc1034f000000000c0c043b0000000000cd0435000000010bb00039000000000cab004b000009e30000413d000000000300004b000009ed0000613d000000000a050433000000000a0a004b000013d40000613d000000000a0904330000061b0aa00197000000f80b800210000000000aab019f0000061d0aa000410000000000a904350000000308800210000000f80880008900000000068601cf000000ff0880008c0000000006002019000000210850003900000ace0000013d0000061a0240009c000000070f000029000013ce0000213d0000004002400039000000400020043f000000010200003a000000000524043600000002020003670006000000020353000500000000003500000000062003680000000006600350000000000606043b0000000000650435000013d40000613d000000f807100210000005e408000041000000000101004b000000000807c0190000061b01600197000000000181019f0000000000150435000000400500043d0000010007f00039000000060170035f000000000601043b000000800160008c0000000501000029000000060110035f00000b1a0000413d00000080086002700000061c0960009c000000000806a0190000061c0960009c00000000090000190000001009002039000000080a9001bf000005e30b80009c000000000a09a0190000004009800270000005e30b80009c000000000908a019000000040ba001bf000005d30890009c000000000b0aa019000000200a900270000005d30890009c000000000a09a0190000000208b001bf0000ffff09a0008c00000000080ba0190000001009a0027000000000090aa019000000ff0990008c0000000108802039000000200900008a000000410a80003900000000099a016f0000000009950019000000000a59004b000000000a000019000000010a004039000005e30b90009c000013ce0000213d000000010aa00190000013ce0000c13d000000400090043f00000002098000390000000009950436000000210a800039000000050aa0027200000a4e0000613d000000000b000019000000050cb00210000000000dc90019000000000cc1034f000000000c0c043b0000000000cd0435000000010bb00039000000000cab004b00000a460000413d000000000200004b00000a500000613d000000000a050433000000000a0a004b000013d40000613d000000000a0904330000061b0aa00197000000f80b800210000000000aab019f0000061d0aa000410000000000a904350000000308800210000000f80880008900000000068601cf000000ff0880008c0000000006002019000000210850003900000b2a0000013d0000061a0630009c000013ce0000213d0000004006300039000000400060043f0000000007ed034f000000010600003a00000000066304360000000007700350000000000707043b0000000000760435000013d40000613d000000f808500210000005e409000041000000000505004b000000000908c0190000061b05700197000000000595019f0000000000560435000000400440008a00000000054d034f000000400400043d000000000505043b000000800650008c00000b760000413d00000080065002700000061c0750009c000000000605a0190000061c0750009c0000000007000019000000100700203900000008087001bf000005e30960009c000000000807a0190000004007600270000005e30960009c000000000706a01900000004098001bf000005d30670009c000000000908a0190000002008700270000005d30670009c000000000807a01900000002069001bf0000ffff0780008c000000000609a0190000001007800270000000000708a019000000ff0770008c0000000106602039000000200700008a0000004108600039000000000778016f0000000007740019000000000847004b00000000080000190000000108004039000005e30970009c000013ce0000213d0000000108800190000013ce0000c13d000000400070043f000000020760003900000000077404360000002108600039000000050880027200000aac0000613d0000000009ed034f000000000a000019000000050ba00210000000000cb70019000000000bb9034f000000000b0b043b0000000000bc0435000000010aa00039000000000b8a004b00000aa40000413d000000000800004b00000aae0000613d0000000008040433000000000808004b000013d40000613d00000000080704330000061b08800197000000f809600210000000000889019f0000061d0880004100000000008704350000000306600210000000f80660008900000000056501cf000000ff0660008c0000000005002019000000210640003900000b870000013d0000061a0850009c000013ce0000213d0000004008500039000000400080043f000000010800003a00000000088504360000000009100350000000000909043b0000000000980435000013d40000613d000000f80a600210000005e40b000041000000000606004b000000000b0ac0190000061b069001970000000006b6019f0000000000680435000000400600043d000000600770008a000000000872034f000000000808043b000000800980008c00000c150000413d00000080098002700000061c0a80009c000000000908a0190000061c0a80009c000000000a000019000000100a002039000000080ba001bf000005e30c90009c000000000b0aa019000000400a900270000005e30c90009c000000000a09a019000000040cb001bf000005d309a0009c000000000c0ba019000000200ba00270000005d309a0009c000000000b0aa0190000000209c001bf0000ffff0ab0008c00000000090ca019000000100ab00270000000000a0ba019000000ff0aa0008c0000000109902039000000200a00008a000000410b900039000000000aab016f000000000aa60019000000000b6a004b000000000b000019000000010b004039000005e30ca0009c000013ce0000213d000000010bb00190000013ce0000c13d0000004000a0043f000000020a900039000000000aa60436000000210b900039000000050bb0027200000b080000613d000000000c000019000000050dc00210000000000eda0019000000000dd1034f000000000d0d043b0000000000de0435000000010cc00039000000000dbc004b00000b000000413d000000000300004b00000b0a0000613d000000000b060433000000000b0b004b000013d40000613d000000000b0a04330000061b0bb00197000000f80c900210000000000bbc019f0000061d0bb000410000000000ba04350000000309900210000000f80990008900000000089801cf000000ff0990008c0000000008002019000000210960003900000c250000013d0000061a0850009c000013ce0000213d0000004008500039000000400080043f000000010800003a00000000088504360000000009100350000000000909043b0000000000980435000013d40000613d000000f80a600210000005e40b000041000000000606004b000000000b0ac0190000061b069001970000000006b6019f0000000000680435000000400600043d000000400870008a000000060780035f000000000707043b000000800970008c00000c720000413d00000080097002700000061c0a70009c000000000907a0190000061c0a70009c000000000a000019000000100a002039000000080ba001bf000005e30c90009c000000000b0aa019000000400a900270000005e30c90009c000000000a09a019000000040cb001bf000005d309a0009c000000000c0ba019000000200ba00270000005d309a0009c000000000b0aa0190000000209c001bf0000ffff0ab0008c00000000090ca019000000100ab00270000000000a0ba019000000ff0aa0008c0000000109902039000000200a00008a000000410b900039000000000aab016f000000000aa60019000000000b6a004b000000000b000019000000010b004039000005e30ca0009c000013ce0000213d000000010bb00190000013ce0000c13d0000004000a0043f000000020a900039000000000aa60436000000210b900039000000050bb0027200000b640000613d000000000c000019000000050dc00210000000000eda0019000000000dd1034f000000000d0d043b0000000000de0435000000010cc00039000000000dbc004b00000b5c0000413d000000000200004b00000b660000613d000000000b060433000000000b0b004b000013d40000613d000000000b0a04330000061b0bb00197000000f80c900210000000000bbc019f0000061d0bb000410000000000ba04350000000309900210000000f80990008900000000079701cf000000ff0990008c0000000007002019000000210960003900000c820000013d0000061a0640009c000013ce0000213d0000004006400039000000400060043f0000000007ed034f000000010600003a00000000066404360000000007700350000000000707043b0000000000760435000013d40000613d000000f808500210000005e409000041000000000505004b000000000908c0190000061b05700197000000000595019f0000000000560435000000400500043d000200000005001d00000020065000390000000005030433000000000705004b00000b960000613d000000000700001900000000086700190000002007700039000000000937001900000000090904330000000000980435000000000857004b00000b8f0000413d000000000365001900000000000304350000000006040433000000000706004b00000ba30000613d000000000700001900000000083700190000002007700039000000000947001900000000090904330000000000980435000000000867004b00000b9c0000413d000000000336001900000000000304350000000003560019000000020400002900000000003404350000003f03300039000000200200008a000000000323016f0000000004430019000000000334004b00000000030000190000000103004039000500000004001d000005e30440009c000013ce0000213d0000000103300190000013ce0000c13d0000000503000029000000400030043f0000061a0330009c000013ce0000213d000000400310003900000000033d034f000000000303043b00000005060000290000004004600039000000400040043f00000020046000390000061e05000041000000000054043500000015040000390000000000460435000000600330021000000021046000390000000000340435000001200310003900000000043d034f000000400900043d000000000404043b000000800540008c000400000009001d00000d9b0000413d00000080054002700000061c0640009c000000000504a0190000061c0640009c0000000006000019000000100600203900000008076001bf000005e30850009c000000000706a0190000004006500270000005e30850009c000000000605a01900000004087001bf000005d30560009c000000000807a0190000002007600270000005d30560009c000000000706a01900000002058001bf0000ffff0670008c000000000508a0190000001006700270000000000607a019000000ff0660008c00000001055020390000004106500039000000000626016f0000000006690019000000000796004b00000000070000190000000107004039000005e30860009c000013ce0000213d0000000107700190000013ce0000c13d000000400060043f0000000206500039000000040700002900000000066704360000002107500039000000050770027200000c010000613d0000000008ed034f0000000009000019000000050a900210000000000ba60019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b00000bf90000413d000000000700004b00000c030000613d00000004070000290000000007070433000000000707004b000013d40000613d00000000070604330000061b07700197000000f808500210000000000778019f0000061d0770004100000000007604350000000305500210000000f80550008900000000045401cf000000ff0550008c00000000040020190000000405000029000000210550003900000dad0000013d0000061a0960009c000013ce0000213d0000004009600039000000400090043f000000010900003a0000000009960436000000000a100350000000000a0a043b0000000000a90435000013d40000613d000000f80b800210000005e40c000041000000000808004b000000000c0bc0190000061b08a001970000000008c8019f0000000000890435000000400800043d000000400770008a000000000972034f000000000909043b000000800a90008c00000ccf0000413d000000800a9002700000061c0b90009c000000000a09a0190000061c0b90009c000000000b000019000000100b002039000000080cb001bf000005e30da0009c000000000c0ba019000000400ba00270000005e30da0009c000000000b0aa019000000040dc001bf000005d30ab0009c000000000d0ca019000000200cb00270000005d30ab0009c000000000c0ba019000000020ad001bf0000ffff0bc0008c000000000a0da019000000100bc00270000000000b0ca019000000ff0bb0008c000000010aa02039000000200b00008a000000410ca00039000000000bbc016f000000000bb80019000000000c8b004b000000000c000019000000010c004039000005e30db0009c000013ce0000213d000000010cc00190000013ce0000c13d0000004000b0043f000000020ba00039000000000bb80436000000210ca00039000000050cc0027200000c5f0000613d000000000d000019000000050ed00210000000000feb0019000000000ee1034f000000000e0e043b0000000000ef0435000000010dd00039000000000ecd004b00000c570000413d000000000300004b00000c610000613d000000000c080433000000000c0c004b000000070f000029000013d40000613d000000000c0b04330000061b0cc00197000000f80da00210000000000ccd019f0000061d0cc000410000000000cb0435000000030aa00210000000f80aa000890000000009a901cf000000ff0aa0008c0000000009002019000000210a80003900000cdf0000013d0000061a0960009c000013ce0000213d0000004009600039000000400090043f000000010900003a0000000009960436000000000a100350000000000a0a043b0000000000a90435000013d40000613d000000f80b700210000005e40c000041000000000707004b000000000c0bc0190000061b07a001970000000007c7019f0000000000790435000000400700043d000000200880008a000000060980035f000000000909043b000000800a90008c00000d3d0000413d000000800a9002700000061c0b90009c000000000a09a0190000061c0b90009c000000000b000019000000100b002039000000080cb001bf000005e30da0009c000000000c0ba019000000400ba00270000005e30da0009c000000000b0aa019000000040dc001bf000005d30ab0009c000000000d0ca019000000200cb00270000005d30ab0009c000000000c0ba019000000020ad001bf0000ffff0bc0008c000000000a0da019000000100bc00270000000000b0ca019000000ff0bb0008c000000010aa02039000000200b00008a000000410ca00039000000000bbc016f000000000bb70019000000000c7b004b000000000c000019000000010c004039000005e30db0009c000013ce0000213d000000010cc00190000013ce0000c13d0000004000b0043f000000020ba00039000000000bb70436000000210ca00039000000050cc0027200000cbc0000613d000000000d000019000000050ed00210000000000feb0019000000000ee1034f000000000e0e043b0000000000ef0435000000010dd00039000000000ecd004b00000cb40000413d000000000200004b00000cbe0000613d000000000c070433000000000c0c004b000000070f000029000013d40000613d000000000c0b04330000061b0cc00197000000f80da00210000000000ccd019f0000061d0cc000410000000000cb0435000000030aa00210000000f80aa000890000000009a901cf000000ff0aa0008c0000000009002019000000210a70003900000d4d0000013d0000061a0a80009c000013ce0000213d000000400a8000390000004000a0043f000000010a00003a000000000aa80436000000000b100350000000000b0b043b0000000000ba0435000013d40000613d000000f80c900210000005e40d000041000000000909004b000000000d0cc0190000061b09b001970000000009d9019f00000000009a0435000000400a00043d0000061a09a0009c000013ce0000213d000000200970008a000000000992034f000000000909043b000000400ba000390000004000b0043f000000200ba000390000061e0c0000410000000000cb0435000000150b0000390000000000ba04350000006009900210000000210ba0003900000000009b0435000000c007700039000000000772034f000000400900043d000000000707043b000000800b70008c00000e630000413d000000800b7002700000061c0c70009c000000000b07a0190000061c0c70009c000000000c000019000000100c002039000000080dc001bf000005e30eb0009c000000000d0ca019000000400cb00270000005e30eb0009c000000000c0ba019000000040ed001bf000005d30bc0009c000000000e0da019000000200dc00270000005d30bc0009c000000000d0ca019000000020be001bf0000ffff0cd0008c000000000b0ea019000000100cd00270000000000c0da019000000ff0cc0008c000000010bb02039000000200c00008a000000410db00039000000000ccd016f000000000cc90019000000000d9c004b000000000d000019000000010d004039000005e30ec0009c000013ce0000213d000000010dd00190000013ce0000c13d0000004000c0043f000000020cb00039000000000cc90436000000210db00039000000050dd0027200000d290000613d000000000e000019000000050fe002100000000003fc0019000000000ff1034f000000000f0f043b0000000000f30435000000010ee000390000000003de004b00000d210000413d000000000300004b00000d2b0000613d0000000003090433000000000303004b000000070f000029000013d40000613d00000000030c04330000061b03300197000000f80db0021000000000033d019f0000061d0330004100000000003c04350000000303b00210000000f80330008900000000073701cf000000ff0330008c00000000070020190000002103900039000000000073043500000e740000013d0000061a0a70009c000013ce0000213d000000400a7000390000004000a0043f000000010a00003a000000000aa70436000000000b100350000000000b0b043b0000000000ba0435000013d40000613d000000f80c900210000005e40d000041000000000909004b000000000d0cc0190000061b09b001970000000009d9019f00000000009a0435000000400900043d000000400880008a000000060a80035f000000000a0a043b000000800ba0008c00000df50000413d000000800ba002700000061c0ca0009c000000000b0aa0190000061c0ca0009c000000000c000019000000100c002039000000080dc001bf000005e30eb0009c000000000d0ca019000000400cb00270000005e30eb0009c000000000c0ba019000000040ed001bf000005d30bc0009c000000000e0da019000000200dc00270000005d30bc0009c000000000d0ca019000000020be001bf0000ffff0cd0008c000000000b0ea019000000100cd00270000000000c0da019000000ff0cc0008c000000010bb02039000000200c00008a000000410db00039000000000ccd016f000000000cc90019000000000d9c004b000000000d000019000000010d004039000005e30ec0009c000013ce0000213d000000010dd00190000013ce0000c13d0000004000c0043f000000020cb00039000000000cc90436000000210db00039000000050dd0027200000d870000613d000000000e000019000000050fe002100000000003fc0019000000000ff1034f000000000f0f043b0000000000f30435000000010ee000390000000003de004b00000d7f0000413d000000000200004b00000d890000613d0000000003090433000000000303004b000000070f000029000013d40000613d00000000030c04330000061b03300197000000f80db0021000000000033d019f0000061d0330004100000000003c04350000000303b00210000000f803300089000000000a3a01cf000000ff0330008c000000000a00201900000021039000390000000000a3043500000e060000013d0000061a0590009c000013ce0000213d00000004070000290000004005700039000000400050043f0000000006ed034f000000010500003a00000000055704360000000006600350000000000606043b0000000000650435000013d40000613d000000f807400210000005e408000041000000000404004b000000000807c0190000061b04600197000000000484019f0000000000450435000000a00330003900000000043d034f000000000404043b000000000f0e001900000000051e00490000001f0550008a000005e406500197000005e407400197000005e408000041000000000967004b00000000090000190000000009084019000000000667013f000000000754004b0000000008004019000005e40660009c000000000908c019000000000609004b000013d20000c13d000000000714001900000000067d034f000000000606043b000005e30860009c000013d20000213d00000000086f00490000002007700039000005e409000041000000000a87004b000000000a000019000000000a092019000005e408800197000005e40b700197000000000c8b004b000000000900801900000000088b013f000005e40880009c00000000090ac019000000000809004b000013d20000c13d000000010860008c000000000c02001900000fee0000c13d00000000067d034f000000000606043b000000010700008a000005e408000041000000000776004b00000000070000190000000007082019000005e406600197000005e40960009c0000000008008019000005e406600167000005e40660009c000000000807c019000300600000003d000000000608004b000010780000c13d000000400600043d000300000006001d0000061a0660009c000013ce0000213d00000003080000290000004006800039000000400060043f00000020068000390000061d07000041000000000076043500000001060000390000000000680435000010780000013d0000061a0390009c000013ce0000213d0000004003900039000000400030043f000000010300003a000000000b3904360000000003100350000000000c03043b0000000000cb0435000013d40000613d000000f803a00210000005e40d000041000000000a0a004b000000000d03c0190000061b03c001970000000003d3019f00000000003b0435000000400b00043d0000061a03b0009c000013ce0000213d000000200380008a000000060330035f000000000303043b000000400ab000390000004000a0043f000000200ab000390000061e0c0000410000000000ca0435000000150a0000390000000000ab04350000006003300210000000210ab0003900000000003a0435000000c003800039000000060330035f000000400a00043d000000000803043b000000800380008c00000f210000413d00000080038002700000061c0c80009c000000000308a0190000061c0c80009c000000000c000019000000100c002039000000080dc001bf000005e30e30009c000000000d0ca019000000400c300270000005e30e30009c000000000c03a0190000000403d001bf000005d30ec0009c00000000030da019000000200dc00270000005d30ec0009c000000000d0ca019000000020c3001bf0000ffff0ed0008c000000000c03a0190000001003d0027000000000030da019000000ff0330008c000000010cc02039000000200300008a000000410dc0003900000000033d016f000000000d3a00190000000003ad004b000000000e000019000000010e004039000005e303d0009c000013ce0000213d0000000103e00190000013ce0000c13d0000004000d0043f0000000203c00039000000000d3a04360000002103c00039000000050e30027200000e4f0000613d000000000f0000190000000503f0021000000000023d0019000000000331034f000000000303043b0000000000320435000000010ff000390000000002ef004b00000e470000413d000000000200004b00000e510000613d00000000020a0433000000000202004b000000070f000029000013d40000613d00000000020d04330000061b02200197000000f803c00210000000000223019f0000061d0220004100000000002d04350000000302c00210000000f80220008900000000032801cf000000ff0220008c00000000030020190000002102a00039000000000032043500000f320000013d0000061a0390009c000013ce0000213d0000004003900039000000400030043f000000010300003a000000000b3904360000000003100350000000000c03043b0000000000cb0435000013d40000613d000000f803700210000005e40d000041000000000707004b000000000d03c0190000061b03c001970000000003d3019f00000000003b0435000000400700043d000000200c700039000000000b04043300000000030b004b00000e810000613d000000000d0000190000000003cd0019000000200dd00039000000000e4d0019000000000e0e04330000000000e304350000000003bd004b00000e7a0000413d0000000003cb0019000000000003043500000000047b0019000000200c400039000000000b05043300000000030b004b00000e900000613d000000000d0000190000000003cd0019000000200dd00039000000000e5d0019000000000e0e04330000000000e304350000000003bd004b00000e890000413d0000000003cb0019000000000003043500000000044b0019000000200b4000390000000005060433000000000305004b00000e9f0000613d000000000c0000190000000003bc0019000000200cc00039000000000d6c0019000000000d0d04330000000000d3043500000000035c004b00000e980000413d0000000003b500190000000000030435000000000445001900000020064000390000000005080433000000000305004b00000eae0000613d000000000b00001900000000036b0019000000200bb00039000000000c8b0019000000000c0c04330000000000c3043500000000035b004b00000ea70000413d000000000365001900000000000304350000000004450019000000200640003900000000050a0433000000000305004b00000ebd0000613d000000000800001900000000036800190000002008800039000000000ba80019000000000b0b04330000000000b30435000000000358004b00000eb60000413d00000000036500190000000000030435000000000445001900000020064000390000000005090433000000000305004b00000ecc0000613d000000000800001900000000036800190000002008800039000000000a980019000000000a0a04330000000000a30435000000000358004b00000ec50000413d000000000365001900000000000304350000000003740049000000000335001900000000003704350000003f03300039000000200400008a000000000343016f0000000008730019000000000338004b00000000050000190000000105004039000005e30380009c000013ce0000213d0000000103500190000013ce0000c13d000000400080043f000001c003f00039000000000332034f000000060c0000290000000005fc00490000001f0650008a000000000503043b000005e403000041000000000965004b00000000090000190000000009034019000005e406600197000005e40a500197000000000b6a004b000000000300a01900000000066a013f000005e40660009c000000000309c019000000000303004b000013d20000613d0000000006f50019000000000362034f000000000503043b000005e30350009c000013d20000213d00000000095c00490000002003600039000005e406000041000000000a93004b000000000a000019000000000a062019000005e409900197000005e40b300197000000000c9b004b000000000600801900000000099b013f000005e40990009c00000000060ac019000000000606004b000013d20000c13d000000010650008c000000000232034f000010190000c13d000000000302043b000000010600008a000005e409000041000000000663004b00000000060000190000000006092019000005e403300197000005e40a30009c0000000009008019000005e403300167000005e40330009c000000000906c0190000006006000039000000000309004b0000123e0000c13d0000061a0380009c000013ce0000213d0000004003800039000000400030043f00000020038000390000061d0600004100000000006304350000000103000039000000000038043500000000060800190000123e0000013d0000061a02a0009c000013ce0000213d0000004002a00039000000400020043f000000010200003a000000000c2a04360000000002100350000000000d02043b0000000000dc0435000013d40000613d000000f802800210000005e403000041000000000808004b000000000302c0190000061b02d00197000000000232019f00000000002c0435000000400800043d000000200d800039000000000c04043300000000020c004b00000f3f0000613d000000000e0000190000000002de0019000000200ee0003900000000034e0019000000000303043300000000003204350000000002ce004b00000f380000413d0000000002dc0019000000000002043500000000048c0019000000200d400039000000000c05043300000000020c004b00000f4e0000613d000000000e0000190000000002de0019000000200ee0003900000000035e0019000000000303043300000000003204350000000002ce004b00000f470000413d0000000002dc0019000000000002043500000000044c0019000000200c4000390000000005060433000000000205004b00000f5d0000613d000000000d0000190000000002cd0019000000200dd0003900000000036d00190000000003030433000000000032043500000000025d004b00000f560000413d0000000002c500190000000000020435000000000445001900000020064000390000000005070433000000000205004b00000f6c0000613d000000000c00001900000000026c0019000000200cc0003900000000037c00190000000003030433000000000032043500000000025c004b00000f650000413d00000000026500190000000000020435000000000445001900000020064000390000000005090433000000000205004b00000f7b0000613d000000000700001900000000026700190000002007700039000000000397001900000000030304330000000000320435000000000257004b00000f740000413d000000000265001900000000000204350000000004450019000000200640003900000000050b0433000000000205004b00000f8a0000613d0000000007000019000000000267001900000020077000390000000003b7001900000000030304330000000000320435000000000257004b00000f830000413d000000000265001900000000000204350000000004450019000000200640003900000000050a0433000000000205004b00000f990000613d0000000007000019000000000267001900000020077000390000000003a7001900000000030304330000000000320435000000000257004b00000f920000413d000000000265001900000000000204350000000002840049000000000225001900000000002804350000003f02200039000000200400008a000000000242016f0000000007820019000000000227004b00000000050000190000000105004039000005e30270009c000013ce0000213d0000000102500190000013ce0000c13d000000400070043f000001c002f00039000000060220035f000000050b0000290000000003fb00490000001f0330008a000000000502043b000005e402000041000000000635004b00000000060000190000000006028019000005e403300197000005e409500197000000000a39004b0000000002008019000000000339013f000005e40330009c000000000206c019000000000202004b000013d20000c13d0000000006f50019000000060260035f000000000502043b000005e30250009c000013d20000213d00000000025b00490000002003600039000005e406000041000000000923004b00000000090000190000000009062019000005e402200197000005e40a300197000000000b2a004b000000000600801900000000022a013f000005e40220009c000000000609c019000000000206004b000013d20000c13d000000010250008c000000060230035f000010400000c13d000000000302043b000000010600008a000005e409000041000000000663004b00000000060000190000000006092019000005e403300197000005e40a30009c0000000009008019000005e403300167000005e40330009c000000000906c0190000006006000039000000000309004b000013060000c13d0000061a0370009c000013ce0000213d0000004003700039000000400030043f00000020037000390000061d060000410000000000630435000000010300003900000000003704350000000006070019000013060000013d000000400b00043d000000380760008c00030000000b001d000010670000413d0000002008600270000005d30760009c000000000806a019000005d30760009c0000000009000019000000040900203900000002079001bf0000ffff0a80008c000000000709a0190000001009800270000000000908a019000000ff0890008c000000000800001900000001080020390000061a09b0009c000013ce0000213d000000000787019f000000030a0000290000004008a00039000000400080043f0000000009fd034f000000020870003a00000000088a04360000000009900350000000000909043b0000000000980435000013d40000613d0000061b09900197000000f80a70021000000000099a019f0000061f099001c700000000009804350000000307700210000000f80770015f00000000067601cf000000030700002900000021077000390000000000670435000010780000013d000000380350008c0000122e0000413d0000002006500270000005d30350009c000000000605a019000005d30350009c0000000009000019000000040900203900000002039001bf0000ffff0a60008c000000000309a0190000001009600270000000000906a019000000ff0690008c000000000600001900000001060020390000061a0980009c000013ce0000213d000000000363019f0000004006800039000000400060043f000000020630003a00000000066804360000000009100350000000000909043b0000000000960435000013d40000613d0000061b09900197000000f80a30021000000000099a019f0000061f099001c700000000009604350000000303300210000000f80330015f00000000033501cf0000002106800039000000000036043500000000060800190000123e0000013d000000380350008c000012f60000413d0000002006500270000005d30350009c000000000605a019000005d30350009c0000000009000019000000040900203900000002039001bf0000ffff0a60008c000000000309a0190000001009600270000000000906a019000000ff0690008c000000000600001900000001060020390000061a0970009c000013ce0000213d000000000363019f0000004006700039000000400060043f000000020630003a00000000066704360000000009100350000000000909043b0000000000960435000013d40000613d0000061b09900197000000f80a30021000000000099a019f0000061f099001c700000000009604350000000303300210000000f80330015f00000000033501cf000000210670003900000000003604350000000006070019000013060000013d0000061a07b0009c000013ce0000213d00000003090000290000004007900039000000400070043f0000000008fd034f000000010700003a00000000077904360000000008800350000000000808043b0000000000870435000013d40000613d000000f8066002100000061b08800197000000000668019f000005e4066001670000000000670435000000800330008a00000000063d034f0000006003000039000000000606043b000000000606004b0000110f0000613d00010000000c001d00000618010000410000000000100439000005d3010000410000000002000414000005d30320009c0000000002018019000000c00120021000000619011001c70000800b020000391747173d0000040f0000000102200190000013da0000613d000000400400043d000000000301043b000000800130008c000000010c000029000010d80000413d00000080013002700000061c0230009c000000000103a0190000061c0230009c0000000002000019000000100200203900000008052001bf000005e30610009c000000000502a0190000004002100270000005e30610009c000000000201a01900000004015001bf000005d30620009c000000000105a0190000002006200270000005d30520009c000000000602a01900000002051001bf0000ffff0260008c000000000501a0190000001001600270000000000106a019000000ff0110008c000000010550203900000041015000390000000001c1016f0000000007140019000000000247004b00000000020000190000000102004039000005e30670009c0000000701000029000013ce0000213d0000000102200190000013ce0000c13d000000400070043f00000002025000390000000006240436000000020d000367000000000f00003100000021075000390000000507700272000010c60000613d0000000008fd034f0000000009000019000000050a900210000000000ba60019000000000aa8034f000000000a0a043b0000000000ab04350000000109900039000000000a79004b000010be0000413d000000000700004b000010c80000613d0000000007040433000000000707004b000013d40000613d00000000070604330000061b07700197000000f808500210000000000778019f0000061d0770004100000000007604350000000305500210000000f80550008900000000035301cf000000ff0550008c00000000030020190000002105400039000010ec0000013d0000061a0140009c0000000701000029000013ce0000213d0000004002400039000000400020043f000000010200003a0000000005240436000000000f000031000000020d0003670000000006fd034f0000000006600350000000000606043b0000000000650435000013d40000613d000000f807300210000005e408000041000000000303004b000000000807c0190000061b03600197000000000383019f0000000000350435000000400300043d00000020063000390000000005040433000000000705004b000010fa0000613d000000000700001900000000086700190000002007700039000000000947001900000000090904330000000000980435000000000857004b000010f30000413d00000000046500190000062c0600004100000000006404350000000204500039000000000043043500000041045000390000000005c4016f0000000004350019000000000554004b00000000050000190000000105004039000005e30640009c000013ce0000213d0000000105500190000013ce0000c13d000001c005100039000000400040043f00000000045d034f00000000051f00490000001f0550008a000000000404043b00000000020f0019000000000f0c0019000005e406000041000000000754004b00000000070000190000000007068019000005e405500197000005e408400197000000000958004b0000000006008019000000000558013f000005e40550009c000000000607c019000000000506004b000013d20000c13d000000060500002900000000060504330000000205000029000000000705043300000005050000290000000008050433000000040500002900000000090504330000000305000029000000000a050433000000000114001900000000041d034f000000000404043b000005e30b40009c000013d20000213d0000000005020019000000000b450049000000200e100039000005e40c00004100000000010d034f000000000dbe004b000000000d000019000000000d0c2019000005e40bb0019700010000000e001d000005e40ee00197000700000004001d00000000040f0019000000000fbe004b000000000f0400190000000704000029000000000c008019000000000bbe013f000000060e000029000005e40bb0009c000000000c0dc019000000000b0c004b000013d20000c13d0000000006670019000000000686001900000000069600190000000006a60019000000000646001900000000070304330000000006760019000000400700043d000005e306600197000000380860008c000011740000413d0000002009600270000005d30860009c000000000906a019000005d30860009c000000000a000019000000040a0020390000000208a001bf0000ffff0b90008c00000000080aa019000000100a900270000000000a09a019000000ff09a0008c000000000900001900000001090020390000061a0a70009c000013ce0000213d000000000898019f0000004009700039000000400090043f000000000951034f000000020280003a00000000022704360000000009900350000000000909043b0000000000920435000013d40000613d0000061b09900197000000f80a80021000000000099a019f00000621099001c700000000009204350000000302800210000000f80220015f00000000022601cf00000021067000390000000000260435000011840000013d0000061a0870009c000013ce0000213d0000004008700039000000400080043f000000000851034f000000010200003a00000000022704360000000008800350000000000808043b0000000000820435000013d40000613d0000061b08800197000000f806600210000000000686019f00000620066000410000000000620435000000400200043d00000020062000390000000008070433000000000908004b00000002040000290000000505000029000011930000613d0000000009000019000000000a6900190000002009900039000000000b790019000000000b0b04330000000000ba0435000000000a89004b0000118c0000413d000000000768001900000000000704350000000007280019000000200970003900000000080e0433000000000a08004b000011a20000613d000000000a000019000000000b9a0019000000200aa00039000000000cea0019000000000c0c04330000000000cb0435000000000b8a004b0000119b0000413d00000000099800190000000000090435000000000778001900000020097000390000000008040433000000000a08004b000011b10000613d000000000a000019000000000b9a0019000000200aa00039000000000c4a0019000000000c0c04330000000000cb0435000000000b8a004b000011aa0000413d00000000099800190000000000090435000000000778001900000020097000390000000008050433000000000a08004b000011c00000613d000000000a000019000000000b9a0019000000200aa00039000000000c5a0019000000000c0c04330000000000cb0435000000000b8a004b000011b90000413d000000000998001900000000000904350000000007780019000000200970003900000004040000290000000008040433000000000a08004b000011d00000613d000000000a000019000000000b9a0019000000200aa00039000000000c4a0019000000000c0c04330000000000cb0435000000000b8a004b000011c90000413d000000000998001900000000000904350000000007780019000000200970003900000003040000290000000008040433000000000a08004b000011e00000613d000000000a000019000000000b9a0019000000200aa00039000000000c4a0019000000000c0c04330000000000cb0435000000000b8a004b000011d90000413d000000000998001900000000000904350000000105100360000000000178001900000007040000290000001f0740018f00000020081000390000000509400272000011f20000613d000000000a000019000000050ba00210000000000cb80019000000000bb5034f000000000b0b043b0000000000bc0435000000010aa00039000000000b9a004b000011ea0000413d000000000a07004b000012010000613d0000000509900210000000000595034f00000000089800190000000307700210000000000908043300000000097901cf000000000979022f000000000505043b0000010007700089000000000575022f00000000057501cf000000000595019f00000000005804350000000001410019000000200510003900000000000504350000000004030433000000000704004b0000120f0000613d000000000700001900000000085700190000002007700039000000000937001900000000090904330000000000980435000000000847004b000012080000413d000000000354001900000000000304350000000001210049000000000114001900000000001204350000003f011000390000000003f1016f0000000001230019000000000331004b00000000030000190000000103004039000005e30410009c000013ce0000213d0000000103300190000013ce0000c13d000000400010043f000005d301000041000005d30360009c000000000601801900000040036002100000000002020433000005d30420009c00000000020180190000006002200210000000000232019f0000000003000414000005d30430009c0000000003018019000000c001300210000000000121019f000013c70000013d0000061a0380009c000013ce0000213d0000004003800039000000400030043f000000010300003a00000000033804360000000006100350000000000606043b0000000000630435000013d40000613d000000f8095002100000061b06600197000000000696019f000005e40660016700000000006304350000000006080019000000400300043d0000061a0830009c000013ce0000213d0000004008300039000000400080043f000000010b00003a0000000008b304360000000001100350000000000a01043b0000000000a80435000013d40000613d0000061b01a0019700000620091001c70000000000980435000000000807043300000000085800190000000009060433000000000898001900000000090304330000000008980019000000400900043d000005e308800197000000380c80008c000012780000413d000000200c800270000005d30b80009c000000000c08a019000005d30b80009c000000000d000019000000040d002039000000020bd001bf0000ffff0ec0008c000000000b0da019000000100dc00270000000000d0ca019000000ff0cd0008c000000000c000019000000010c0020390000061a0d90009c000013ce0000213d000000000bcb019f000000400c9000390000004000c0043f000000200c9000390000000000ac0435000000020ab0003a0000000000a90435000013d40000613d000000f80ab0021000000000011a019f00000621011001c700000000001c04350000000301b00210000000f80110015f00000000011801cf00000021089000390000000000180435000012850000013d0000061a0c90009c000013ce0000213d000000400c9000390000004000c0043f000000200c9000390000000000ac04350000000000b90435000000000a0b004b000013d40000613d000000f808800210000000000118019f000006200110004100000000001c0435000000400100043d0000002008100039000006160a0000410000000000a80435000000210b100039000000000a090433000000000c0a004b000012950000613d000000000c000019000000000dbc0019000000200cc00039000000000e9c0019000000000e0e04330000000000ed0435000000000dac004b0000128e0000413d0000000009ba0019000000000009043500000000091a0019000000210b900039000000000a070433000000000c0a004b000012a40000613d000000000c000019000000000dbc0019000000200cc00039000000000e7c0019000000000e0e04330000000000ed0435000000000dac004b0000129d0000413d0000000007ba0019000000000007043500000000079a0019000000210a7000390000000009060433000000000b09004b000012b30000613d000000000b000019000000000cab0019000000200bb00039000000000d6b0019000000000d0d04330000000000dc0435000000000c9b004b000012ac0000413d0000000006a90019000000000006043500000000067900190000001f0750018f0000002109600039000000050a500272000012c30000613d000000000b000019000000050cb00210000000000dc90019000000000cc2034f000000000c0c043b0000000000cd0435000000010bb00039000000000cab004b000012bb0000413d000000000b07004b000012d20000613d000000050aa002100000000002a2034f0000000009a900190000000307700210000000000a090433000000000a7a01cf000000000a7a022f000000000202043b0000010007700089000000000272022f00000000027201cf0000000002a2019f00000000002904350000000002560019000000210620003900000000000604350000000005030433000000000705004b000012e00000613d000000000700001900000000096700190000002007700039000000000a370019000000000a0a04330000000000a90435000000000957004b000012d90000413d0000000003650019000000000003043500000000021200490000000002250019000000010320003900000000003104350000004002200039000000000342016f0000000002130019000000000332004b00000000030000190000000103004039000005e30420009c000013ce0000213d0000000103300190000013ce0000c13d000000400020043f000005d302000041000005d30380009c00000000080280190000004003800210000013bd0000013d0000061a0370009c000013ce0000213d0000004003700039000000400030043f000000010300003a00000000033704360000000006100350000000000606043b0000000000630435000013d40000613d000000f8095002100000061b06600197000000000696019f000005e40660016700000000006304350000000006070019000000400300043d0000061a0730009c000013ce0000213d0000004007300039000000400070043f000000010b00003a0000000007b304360000000001100350000000000a01043b0000000000a70435000013d40000613d0000061b01a0019700000620091001c70000000000970435000000000708043300000000075700190000000009060433000000000797001900000000090304330000000007970019000000400900043d000005e307700197000000380c70008c000013400000413d000000200c700270000005d30b70009c000000000c07a019000005d30b70009c000000000d000019000000040d002039000000020bd001bf0000ffff0ec0008c000000000b0da019000000100dc00270000000000d0ca019000000ff0cd0008c000000000c000019000000010c0020390000061a0d90009c000013ce0000213d000000000bcb019f000000400c9000390000004000c0043f000000200c9000390000000000ac0435000000020ab0003a0000000000a90435000013d40000613d000000f80ab0021000000000011a019f00000621011001c700000000001c04350000000301b00210000000f80110015f00000000011701cf000000210790003900000000001704350000134d0000013d0000061a0c90009c000013ce0000213d000000400c9000390000004000c0043f000000200c9000390000000000ac04350000000000b90435000000000a0b004b000013d40000613d000000f807700210000000000117019f000006200110004100000000001c0435000000400100043d0000002007100039000005e90a0000410000000000a70435000000210b100039000000000a090433000000000c0a004b0000135d0000613d000000000c000019000000000dbc0019000000200cc00039000000000e9c0019000000000e0e04330000000000ed0435000000000dac004b000013560000413d0000000009ba0019000000000009043500000000091a0019000000210b900039000000000a080433000000000c0a004b0000136c0000613d000000000c000019000000000dbc0019000000200cc00039000000000e8c0019000000000e0e04330000000000ed0435000000000dac004b000013650000413d0000000008ba0019000000000008043500000000089a0019000000210a8000390000000009060433000000000b09004b0000137b0000613d000000000b000019000000000cab0019000000200bb00039000000000d6b0019000000000d0d04330000000000dc0435000000000c9b004b000013740000413d0000000006a90019000000000006043500000000068900190000001f0850018f0000002109600039000000050a5002720000138b0000613d000000000b000019000000050cb00210000000000dc90019000000000cc2034f000000000c0c043b0000000000cd0435000000010bb00039000000000cab004b000013830000413d000000000b08004b0000139a0000613d000000050aa002100000000002a2034f0000000009a900190000000308800210000000000a090433000000000a8a01cf000000000a8a022f000000000202043b0000010008800089000000000282022f00000000028201cf0000000002a2019f00000000002904350000000002560019000000210620003900000000000604350000000005030433000000000805004b000013a80000613d000000000800001900000000096800190000002008800039000000000a380019000000000a0a04330000000000a90435000000000958004b000013a10000413d0000000003650019000000000003043500000000021200490000000002250019000000010320003900000000003104350000004002200039000000000342016f0000000002130019000000000332004b00000000030000190000000103004039000005e30420009c000013ce0000213d0000000103300190000013ce0000c13d000000400020043f000005d302000041000005d30370009c000000000702801900000040037002100000000001010433000005d30410009c00000000010280190000006001100210000000000131019f0000000003000414000005d30430009c0000000003028019000000c002300210000000000112019f000005e9011001c700008010020000391747173d0000040f0000000102200190000013d20000613d000000000101043b000000000001042d000005e70100004100000000001004350000004101000039000013d70000013d00000000010000190000174900010430000005e70100004100000000001004350000003201000039000000040010043f000005e8010000410000174900010430000000000001042f000000400100043d00000044021000390000061703000041000000000032043500000024021000390000000803000039000013f30000013d000000400100043d00000044021000390000062403000041000000000032043500000024021000390000001f03000039000013f30000013d000005e70100004100000000001004350000001101000039000013d70000013d000000400100043d00000044021000390000062d030000410000000000320435000000240210003900000017030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ff011001c700001749000104300000001f0350018f00000005025002720000140a0000613d00000000040000190000000506400210000000000761034f000000000707043b00000000007604350000000104400039000000000624004b000014030000413d000000000403004b000014180000613d00000003033002100000000502200210000000000402043300000000043401cf000000000434022f000000000121034f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f0000000000120435000000600150021000001749000104300000001f0340018f0000000502400272000014250000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b0000141e0000413d000000000503004b000014330000613d00000003033002100000000502200210000000000502043300000000053501cf000000000535022f000000000121034f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f000000000012043500000060014002100000174900010430000000000403004b0000143f0000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000014380000413d00000000012300190000000000010435000000000001042d000000e0021000390000000201000367000000000321034f000000000303043b000005d5033001980000144c0000613d0000004002200039000000000121034f000000000101043b000014610000013d000000800320008a000000000331034f000000400220008a000000000521034f000000000403043b000000000505043b00000000634500a9000000000605004b000014580000613d00000000655300d9000000000445004b000014620000c13d0000008002200039000000000121034f000000000201043b0000000001320019000000000221004b000000000200001900000001020040390000000102200190000014620000c13d000000000001042d000005e70100004100000000001004350000001101000039000000040010043f000005e801000041000017490001043000000040031000390000000202000367000000000332034f0000012005100039000000000652034f000000000303043b000005d504300197000000000306043b0000062e0630009c0000154f0000813d000000a005500039000000000552034f000000000700003100000000061700490000001f0660008a000000000505043b000005e408000041000000000965004b00000000090000190000000009084019000005e406600197000005e40a500197000000000b6a004b000000000800a01900000000066a013f000005e40660009c000000000809c019000000000608004b0000154d0000613d0000000005150019000000000152034f000000000101043b000005e30610009c0000154d0000213d00000000061700490000002008500039000005e405000041000000000968004b00000000090000190000000009052019000005e406600197000005e40a800197000000000b6a004b000000000500801900000000066a013f000005e40660009c000000000509c019000000000505004b0000154d0000c13d0000003f05100039000000200600008a000000000565016f000000400600043d0000000005560019000000000965004b00000000090000190000000109004039000005e30a50009c000015610000213d0000000109900190000015610000c13d000000400050043f00000000051604360000000009810019000000000779004b0000154d0000213d000000000782034f0000001f0210018f0000000508100272000014b70000613d0000000009000019000000050a900210000000000ba50019000000000aa7034f000000000a0a043b0000000000ab04350000000109900039000000000a89004b000014af0000413d000000000902004b000014c60000613d0000000508800210000000000787034f00000000088500190000000302200210000000000908043300000000092901cf000000000929022f000000000707043b0000010002200089000000000727022f00000000022701cf000000000292019f000000000028043500000000011500190000000000010435000080060140008c000014df0000c13d0000000001000414000005d30210009c0000154f0000213d0000000002060433000005d30420009c0000154f0000213d000000c0011002100000060a0110019700000040045002100000061404400197000000000114019f00000060022002100000061502200197000000000121019f00000616011001c7000000000203004b000014f60000613d000080090200003900008006040000390000000105000039000014fa0000013d00000000020604330000000001000414000000040640008c0000154c0000613d000005d306000041000005d30750009c00000000050680190000004005500210000005d30720009c00000000020680190000006002200210000000000252019f000005d30510009c0000000001068019000000c001100210000000000112019f000000000203004b000015450000613d000005e9011001c700008009020000390000000005000019174717380000040f000015470000013d00008006020000390000000003000019000000000400001900000000050000190000000006000019174717380000040f000300000001035500000000030100190000006003300270000105d30030019d000005d3053001970000003f03500039000005d406300197000000400300043d0000000004360019000000000664004b00000000060000190000000106004039000005e30740009c000015610000213d0000000106600190000015610000c13d000000400040043f00000000045304360000001f0650003900000005066002720000151c0000613d0000000007000031000000020770036700000000080000190000000509800210000000000a940019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000015140000413d000000000600004b0000151e0000613d0000001f0650018f00000005055002720000152a0000613d000000000700001900000005087002100000000009840019000000000881034f000000000808043b00000000008904350000000107700039000000000857004b000015220000413d000000000706004b000015390000613d0000000505500210000000000151034f00000000055400190000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f000000000015043500000001012001900000154c0000c13d0000000001030433000005d302000041000005d30310009c0000000001028019000005d30340009c000000000402801900000040024002100000006001100210000000000121019f00001749000104300000000002040019174717380000040f00030000000103550000006001100270000105d30010019d00000001012001900000154d0000613d000000000001042d00000000010000190000174900010430000000400100043d000000440210003900000617030000410000000000320435000000240210003900000008030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ff011001c70000174900010430000005e70100004100000000001004350000004101000039000000040010043f000005e80100004100001749000104300009000000000002000000400600043d0000000003020433000000820330008c0000000003060019000015920000613d0000062f0260009c000016960000813d000000c002600039000000400020043f000000820200003900000000022604360000000003000031000000020330036700000000040000190000000505400210000000000553034f000000000505043b00000000025204360000000104400039000000050540008c000015760000413d0000000002060433000000400220008c000016c80000a13d000000600260003900000000030204330000061b0330019700000630033001c700000000003204350000000002060433000000820220008c000016c80000413d000000a10260003900000000030204330000061b0330019700000630033001c70000000000320435000000400300043d0000000002060433000000820220008c00000000020600190000170e0000c13d000005fa0430009c000016960000213d0000008004300039000000400040043f0000004105000039000000000953043600000000040000310000000204400367000000000600001900000000070900190000000508600210000000000884034f000000000808043b00000000078704360000000106600039000000030860008c0000159c0000413d000000400a00043d000005fa06a0009c000016960000213d0000008006a00039000000400060043f00000000085a0436000000000500001900000000060800190000000507500210000000000774034f000000000707043b00000000067604360000000105500039000000030750008c000015ab0000413d000000410420003900000000040404330000004005200039000000000605043300000020052000390000000005050433000000000059043500000040053000390000000000650435000000f806400210000000600430003900000000070404330000061b07700197000000000667019f00000000006404350000006106200039000000810720003900000082022000390000000002020433000000000707043300000000060604330000000000680435000000400ba0003900000000007b04350000006007a00039000000f80220021000000000060704330000061b06600197000000000226019f000200000007001d00000000002704350000000002030433000000410220008c0000169a0000c13d0000000006000415000000090660008a00000020066000c9000000000205043300000041033000390000000003030433000000ff0330018f0000001b0330008a000000010330008c0000000005000019000015f50000213d000006320320009c000015f10000213d00000000030a0433000000410330008c000015f10000c13d0000004103a000390000000003030433000000ff0330018f0000001b0330008a000000010330008c000015f10000213d0000060d050000410000000006000415000000080660008a00000020066000c900000000030b0433000006330330009c000015f50000413d0000000006000415000000080660008a00000020066000c90000000005000019000300000006001d00060000000b001d00070000000a001d000100000005001d000006320320009c000016a10000213d000400000008001d00000000030404330000000006090433000000400400043d0000006005400039000000000025043500000040024000390000000000620435000000f80330027000000020024000390000000000320435000500000001001d00000000001404350000000000000435000005d3010000410000000002000414000005d30320009c0000000002018019000005d30340009c00000000040180190000004001400210000000c002200210000000000112019f00000634011001c700000001020000391747173d0000040f00000000030100190000006003300270000005d303300197000000200430008c000000000403001900000020040080390000001f0540018f0000000504400272000016260000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000746004b0000161f0000413d000000000605004b000016340000613d00000003055002100000000504400210000000000604043300000000065601cf000000000656022f000000000741034f000000000707043b0000010005500089000000000757022f00000000055701cf000000000565019f0000000000540435000100000003001f000300000001035500000001022001900000000506000029000000040400002900000007050000290000000607000029000016ce0000613d0000000001000433000005d503100198000016b60000613d00000003020000290000000502200270000000000201001f0000000001050433000000410110008c0000169a0000c13d000700000003001d0000000001070433000006320210009c000016a10000213d000000020200002900000000020204330000000003040433000000400400043d0000006005400039000000000015043500000040014000390000000000310435000000f8012002700000002002400039000000000012043500000000006404350000000000000435000005d3010000410000000002000414000005d30320009c0000000002018019000005d30340009c00000000040180190000004001400210000000c002200210000000000112019f00000634011001c70000000102000039000600000002001d1747173d0000040f00000000030100190000006003300270000005d303300197000000200430008c000000000403001900000020040080390000001f0540018f0000000504400272000016740000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000746004b0000166d0000413d000000000605004b000016820000613d00000003055002100000000504400210000000000604043300000000065601cf000000000656022f000000000741034f000000000707043b0000010005500089000000000757022f00000000055701cf000000000565019f0000000000540435000100000003001f00030000000103550000000102200190000016eb0000613d0000000001000433000005d5021001980000000703000029000016b60000613d000000000100041a000005d501100197000000000113004b0000000001000019000016950000c13d0000000601000029000000000101041a000005d501100197000000000112004b00000000010000190000000101006029000000000001042d000005e70100004100000000001004350000004101000039000016cb0000013d000000400100043d00000044021000390000063503000041000000000032043500000024021000390000001f03000039000016bc0000013d000000400100043d000000640210003900000610030000410000000000320435000000440210003900000637030000410000000000320435000000240210003900000022030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ed011001c70000174900010430000000400100043d000000440210003900000636030000410000000000320435000000240210003900000018030000390000000000320435000005ec020000410000000000210435000000040210003900000020030000390000000000320435000005d302000041000005d30310009c00000000010280190000004001100210000005ff011001c70000174900010430000005e70100004100000000001004350000003201000039000000040010043f000005e8010000410000174900010430000000400200043d0000001f0430018f0000000505300272000016db0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000016d30000413d000000000604004b000017070000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000017070000013d000000400200043d0000001f0430018f0000000505300272000016f80000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000016f00000413d000000000604004b000017070000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005d301000041000005d30420009c000000000201801900000040012002100000006002300210000000000121019f000017490001043000000044013000390000063102000041000000000021043500000024013000390000000e020000390000000000210435000005ec010000410000000000130435000000040130003900000020020000390000000000210435000005d301000041000005d30230009c00000000030180190000004001300210000005ff011001c70000174900010430000000000001042f00000000050100190000000000200439000000040130008c000017270000a13d000000050140027000000000010100310000000400100443000005d3010000410000000002000414000005d30420009c0000000002018019000005d30430009c00000000030180190000006001300210000000c002200210000000000112019f00000638011001c700000000020500191747173d0000040f0000000102200190000017370000613d000000000101043b000000000001042d000000000001042f0000173b002104210000000102000039000000000001042d0000000002000019000000000001042d00001740002104230000000102000039000000000001042d0000000002000019000000000001042d00001745002104230000000102000039000000000001042d0000000002000019000000000001042d0000174700000432000017480001042e00001749000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000020000000000000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000a28c1aed00000000000000000000000000000000000000000000000000000000e2f318e200000000000000000000000000000000000000000000000000000000e2f318e300000000000000000000000000000000000000000000000000000000eeb8cb0900000000000000000000000000000000000000000000000000000000a28c1aee00000000000000000000000000000000000000000000000000000000df9c1589000000000000000000000000000000000000000000000000000000005270972400000000000000000000000000000000000000000000000000000000527097250000000000000000000000000000000000000000000000000000000073688914000000000000000000000000000000000000000000000000000000001626ba7e00000000000000000000000000000000000000000000000000000000202bcce7000000000000000000000000000000000000000000000000ffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000e1239cd8000000000000000000000000000000000000000000000000000000009cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f394e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000002000000000000000000000000000000000000000000000000000000000000007261746f720000000000000000000000000000000000000000000000000000004661696c656420746f20706179207468652066656520746f20746865206f706508c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000000949431dc000000000000000000000000000000000000000000000000000000008c5a344500000000000000000000000000000000000000000000000000000000dd62ed3e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000800000000000000000095ea7b3000000000000000000000000000000000000000000000000000000005361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65641806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000440000000000000000000000005361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f000000000000000000000000000000000000000000000000ffffffffffffff3f6f742073756363656564000000000000000000000000000000000000000000005361666545524332303a204552433230206f7065726174696f6e20646964206e416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000000000000000000000000000000000000000006400000000000000000000000054686520617070726f76616c4261736564207061796d617374657220696e707574206d757374206265206174206c65617374203638206279746573206c6f6e670000000000000000000000000000000000000084000000800000000000000000556e737570706f72746564207061796d617374657220666c6f770000000000000000000000000000000000000000000000000064000000800000000000000000546865207374616e64617264207061796d617374657220696e707574206d757374206265206174206c656173742034206279746573206c6f6e6700000000000000000000000000000000000000000000000000200000008000000000000000004f6e6c7920626f6f746c6f616465722063616e2063616c6c2074686973206d6574686f640000000000000000000000000000000000000000000000000000000000000000ffffffff0000000000000000000000000000000000000000000000000100000000000000000000000000000000000024000000a00000000000000000202bcce7000000000000000000000000000000000000000000000000000000001626ba7e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000001000000000000000075650000000000000000000000000000000000000000000000000000000000004e6f7420656e6f7567682062616c616e636520666f7220666565202b2076616c000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000ffffffff000000000000000000000000000000000000000000000000ffffffff00000000000000000000000001000000000000000000000000000000000000000000000000000000000000004f766572666c6f770000000000000000000000000000000000000000000000009a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b0200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000ffffffffffffffffffffffffffffffff81000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6b656363616b3235362072657475726e656420696e76616c6964206461746100848e1bfa1ac4e3576b728bda6721b215c70a7799a5b4866282a71bab954baac8000000000000000000000000000000000000000000000000fffffffffffffe1fc2f8787176b8ac6bf7215b4adcc1e069bf4ab82d9ab1df05a57a91d425935b6ead7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a519b453ce45aaaaf3a300f5a9ec95869b4f28ab10430b572ee218c3a6a5e07d6f000000000000000000000000000000000000000000000000ffffffffffffff5f19010000000000000000000000000000000000000000000000000000000000008080000000000000000000000000000000000000000000000000000000000000456e636f64696e6720756e737570706f727465642074780000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff401b00000000000000000000000000000000000000000000000000000000000000496e76616c6964206c656e6774680000000000000000000000000000000000007fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a07fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1000000000000000000000000000000000000008000000000000000000000000045434453413a20696e76616c6964207369676e6174757265206c656e6774680045434453413a20696e76616c6964207369676e6174757265000000000000000045434453413a20696e76616c6964207369676e6174757265202773272076616c020000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d448c295e929e696b285e58d46eeef7df7814594a3c50b601ee9abfe479ae5d", + "linkReferences": {}, + "deployedLinkReferences": {}, + "factoryDeps": {} +} diff --git a/test/wallet_test.go b/test/wallet_test.go index 1dd3309..75249f4 100644 --- a/test/wallet_test.go +++ b/test/wallet_test.go @@ -48,7 +48,7 @@ func TestIntegrationWallet_MainContract(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") mainContract, err := wallet.MainContract(context.Background()) @@ -66,7 +66,7 @@ func TestIntegrationWallet_BridgehubContract(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") bridgehub, err := wallet.BridgehubContract(context.Background()) @@ -84,7 +84,7 @@ func TestIntegrationWallet_L1BridgeContracts(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") contracts, err := wallet.L1BridgeContracts(context.Background()) @@ -102,7 +102,7 @@ func TestIntegration_EthBasedChain_Wallet_BaseToken(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") baseToken, err := wallet.BaseToken(nil) @@ -120,7 +120,7 @@ func TestIntegration_NonEthBasedChain_Wallet_BaseToken(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") baseToken, err := wallet.BaseToken(nil) @@ -138,7 +138,7 @@ func TestIntegration_EthBasedChain_Wallet_IsEthBasedChain(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") isEthBasedChain, err := wallet.IsEthBasedChain(context.Background()) @@ -156,7 +156,7 @@ func TestIntegration_NonEthBasedChain_Wallet_IsEthBasedChain(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") isEthBasedChain, err := wallet.IsEthBasedChain(context.Background()) @@ -174,7 +174,7 @@ func TestIntegrationWallet_BalanceL1(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") ethBalance, err := wallet.BalanceL1(nil, utils.LegacyEthAddress) @@ -197,7 +197,7 @@ func TestIntegrationWallet_AllowanceL1(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") bridgeContracts, err := client.BridgeContracts(context.Background()) @@ -218,7 +218,7 @@ func TestIntegrationWallet_L2TokenAddress(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2Address, err := wallet.L2TokenAddress(context.Background(), L1Dai) @@ -236,7 +236,7 @@ func TestIntegration_NonEthBasedChain_Wallet_L2TokenAddress(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2Address, err := wallet.L2TokenAddress(context.Background(), utils.LegacyEthAddress) @@ -257,7 +257,7 @@ func TestIntegrationWallet_ApproveERC20(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") bridgeContracts, err := client.BridgeContracts(context.Background()) @@ -289,7 +289,7 @@ func TestIntegrationWallet_BaseCost(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") baseCost, err := wallet.BaseCost(nil, big.NewInt(100_000), big.NewInt(800), big.NewInt(500_000)) @@ -307,7 +307,7 @@ func TestIntegrationWallet_BalanceETH(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") balance, err := wallet.Balance(context.Background(), utils.LegacyEthAddress, nil) @@ -325,7 +325,7 @@ func TestIntegrationWallet_BalanceToken(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") balance, err := wallet.Balance(context.Background(), L2Dai, nil) @@ -343,7 +343,7 @@ func TestIntegration_EthBasedChain_Wallet_AllBalances(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") balances, err := wallet.AllBalances(context.Background()) @@ -361,7 +361,7 @@ func TestIntegration_NonEthBasedChain_Wallet_AllBalances(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") balances, err := wallet.AllBalances(context.Background()) @@ -379,7 +379,7 @@ func TestIntegrationWallet_L2BridgeContracts(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") bridges, err := wallet.L2BridgeContracts(context.Background()) @@ -397,7 +397,7 @@ func TestIntegrationWallet_DeploymentNonce(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWalletL2(common.Hex2Bytes(PrivateKey), &client) + wallet, err := accounts.NewWalletL2(common.Hex2Bytes(PrivateKey1), &client) assert.NoError(t, err, "NewWallet should not return an error") deploymentNonce, err := wallet.DeploymentNonce(nil) @@ -417,7 +417,7 @@ func TestIntegrationWallet_Withdraw(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2BalanceBeforeWithdrawal, err := wallet.Balance(context.Background(), utils.LegacyEthAddress, nil) @@ -462,7 +462,7 @@ func TestIntegrationWallet_WithdrawToken(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2BalanceBeforeWithdrawal, err := wallet.Balance(context.Background(), L2Dai, nil) @@ -503,21 +503,17 @@ func TestIntegrationWallet_Transfer(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - ethClient, err := ethclient.Dial(EthereumProvider) - assert.NoError(t, err, "ethclient.Dial should not return an error") - defer ethClient.Close() - - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") balanceBeforeTransferSender, err := wallet.Balance(context.Background(), utils.LegacyEthAddress, nil) assert.NoError(t, err, "Balance should not return an error") - balanceBeforeTransferReceiver, err := client.BalanceAt(context.Background(), Receiver, nil) + balanceBeforeTransferReceiver, err := client.BalanceAt(context.Background(), Address2, nil) assert.NoError(t, err, "BalanceAt should not return an error") tx, err := wallet.Transfer(nil, accounts.TransferTransaction{ - To: Receiver, + To: Address2, Amount: amount, Token: utils.LegacyEthAddress, }) @@ -530,11 +526,11 @@ func TestIntegrationWallet_Transfer(t *testing.T) { balanceAfterTransferSender, err := wallet.Balance(context.Background(), utils.LegacyEthAddress, nil) assert.NoError(t, err, "Balance should not return an error") - balanceAfterTransferReceiver, err := wallet.BalanceL1(nil, utils.LegacyEthAddress) - assert.NoError(t, err, "BalanceL1 should not return an error") + balanceAfterTransferReceiver, err := client.BalanceAt(context.Background(), Address2, nil) + assert.NoError(t, err, "BalanceAt should not return an error") assert.True(t, new(big.Int).Sub(balanceBeforeTransferSender, balanceAfterTransferSender).Cmp(amount) >= 0, "Sender balance should be decreased") - assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Receiver balance should be increased") + assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Address2 balance should be increased") } func TestIntegrationWallet_TransferToken(t *testing.T) { @@ -544,11 +540,7 @@ func TestIntegrationWallet_TransferToken(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - ethClient, err := ethclient.Dial(EthereumProvider) - assert.NoError(t, err, "ethclient.Dial should not return an error") - defer ethClient.Close() - - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") tokenContract, err := erc20.NewIERC20(L2Dai, client) @@ -557,11 +549,11 @@ func TestIntegrationWallet_TransferToken(t *testing.T) { balanceBeforeTransferSender, err := wallet.Balance(context.Background(), L2Dai, nil) assert.NoError(t, err, "Balance should not return an error") - balanceBeforeTransferReceiver, err := tokenContract.BalanceOf(nil, Receiver) + balanceBeforeTransferReceiver, err := tokenContract.BalanceOf(nil, Address2) assert.NoError(t, err, "BalanceOf should not return an error") tx, err := wallet.Transfer(nil, accounts.TransferTransaction{ - To: Receiver, + To: Address2, Amount: amount, Token: L2Dai, }) @@ -574,11 +566,11 @@ func TestIntegrationWallet_TransferToken(t *testing.T) { balanceAfterTransferSender, err := wallet.Balance(context.Background(), L2Dai, nil) assert.NoError(t, err, "Balance should not return an error") - balanceAfterTransferReceiver, err := tokenContract.BalanceOf(nil, Receiver) + balanceAfterTransferReceiver, err := tokenContract.BalanceOf(nil, Address2) assert.NoError(t, err, "BalanceOf should not return an error") assert.True(t, new(big.Int).Sub(balanceBeforeTransferSender, balanceAfterTransferSender).Cmp(amount) >= 0, "Sender balance should be decreased") - assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Receiver balance should be increased") + assert.True(t, new(big.Int).Sub(balanceAfterTransferReceiver, balanceBeforeTransferReceiver).Cmp(amount) >= 0, "Address2 balance should be increased") } func TestIntegrationWallet_PopulateTransaction(t *testing.T) { @@ -586,7 +578,7 @@ func TestIntegrationWallet_PopulateTransaction(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") nonce, err := wallet.Nonce(context.Background(), nil) @@ -597,10 +589,10 @@ func TestIntegrationWallet_PopulateTransaction(t *testing.T) { GasTipCap: big.NewInt(0), GasFeeCap: big.NewInt(100_000_000), Gas: big.NewInt(154_379), - To: &Receiver, + To: &Address2, Value: big.NewInt(7_000_000_000), ChainID: big.NewInt(270), - From: &Address, + From: &Address1, Data: hexutil.Bytes{}, Meta: &zkTypes.Eip712Meta{ GasPerPubdata: utils.NewBig(50_000), @@ -608,7 +600,7 @@ func TestIntegrationWallet_PopulateTransaction(t *testing.T) { } populatedTx, err := wallet.PopulateTransaction(context.Background(), accounts.Transaction{ - To: &Receiver, + To: &Address2, Value: big.NewInt(7_000_000_000), }) @@ -621,16 +613,16 @@ func TestIntegrationWallet_SignTransaction(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") signedTx, err := wallet.SignTransaction(&zkTypes.Transaction712{ - To: &Receiver, + To: &Address2, Value: big.NewInt(1_000_000_000_000_000_000), // 1ETH }) assert.NoError(t, err, "SignTransaction should not return an error") - assert.NotNil(t, signedTx, "Transactions should be nil") + assert.NotNil(t, signedTx, "Transaction should not be nil") } func TestIntegrationWallet_SendTransaction(t *testing.T) { @@ -638,13 +630,13 @@ func TestIntegrationWallet_SendTransaction(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") tokenAbi, err := erc20.IERC20MetaData.GetAbi() assert.NoError(t, err, "bind.GetAbi should not return an error") - approveTokenCalldata, err := tokenAbi.Pack("approve", Receiver, big.NewInt(1)) + approveTokenCalldata, err := tokenAbi.Pack("approve", Address2, big.NewInt(1)) assert.NoError(t, err, "abi.Pack should not return an error") txHash, err := wallet.SendTransaction(context.Background(), &accounts.Transaction{ @@ -664,7 +656,7 @@ func TestIntegrationWallet_DeployWithCreate(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") bytecode, err := os.ReadFile("./testdata/Storage.zbin") @@ -685,7 +677,7 @@ func TestIntegrationWallet_DeployWithCreateConstructor(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") bytecode, err := os.ReadFile("./testdata/Incrementer.zbin") @@ -715,7 +707,7 @@ func TestIntegrationWallet_DeployWithCreateDeps(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") demoBytecode, err := os.ReadFile("./testdata/Demo.zbin") @@ -743,7 +735,7 @@ func TestIntegrationWallet_DeployWithCreateAccount(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") _, paymasterAbi, bytecode, err := utils.ReadStandardJson("./testdata/Paymaster.json") @@ -770,7 +762,7 @@ func TestIntegrationWallet_Deploy(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") bytecode, err := os.ReadFile("./testdata/Storage.zbin") @@ -795,7 +787,7 @@ func TestIntegrationWallet_DeployConstructor(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") bytecode, err := os.ReadFile("./testdata/Incrementer.zbin") @@ -828,7 +820,7 @@ func TestIntegrationWallet_DeployDeps(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") demoBytecode, err := os.ReadFile("./testdata/Demo.zbin") @@ -859,7 +851,7 @@ func TestIntegrationWallet_DeployAccount(t *testing.T) { defer client.Close() assert.NoError(t, err, "clients.Dial should not return an error") - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, nil) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, nil) assert.NoError(t, err, "NewWallet should not return an error") _, paymasterAbi, bytecode, err := utils.ReadStandardJson("./testdata/Paymaster.json") @@ -893,7 +885,7 @@ func TestIntegrationWallet_DeployAccount(t *testing.T) { // assert.NoError(t, err, "ethclient.Dial should not return an error") // defer ethClient.Close() // -// wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) +// wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) // assert.NoError(t, err, "NewWallet should not return an error") // // tx, err := wallet.ClaimFailedDeposit(nil, common.HexToHash("0x2b870d89f1060463091ed1ed47fa156b37c602d954ee0e41d05a5d5344f3ac23")) @@ -931,12 +923,12 @@ func TestIntegrationWallet_DeployAccount(t *testing.T) { // assert.NoError(t, err, "ethclient.Dial should not return an error") // defer ethClient.Close() // -// wallet, err = accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) +// wallet, err = accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) // assert.NoError(t, err, "NewWallet should not return an error") // // tx, err = wallet.Deposit(nil, accounts.DepositTransaction{ // Token: L1Dai, -// To: wallet.Address(), +// To: wallet.Address1(), // Amount: big.NewInt(5), // ApproveERC20: true, // ApproveBaseERC20: true, @@ -957,7 +949,7 @@ func TestIntegration_Wallet_ClaimFailedDepositSuccessfulDeposit(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") tx, err := wallet.Deposit(nil, accounts.DepositTransaction{ @@ -993,12 +985,12 @@ func TestIntegration_EthBasedChain_Wallet_EstimateGasDepositEth(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") gas, err := wallet.EstimateGasDeposit(context.Background(), accounts.DepositCallMsg{ Token: utils.LegacyEthAddress, - To: Receiver, + To: Address2, Amount: big.NewInt(7_000_000_000), }) @@ -1015,7 +1007,7 @@ func TestIntegration_EthBasedChain_Wallet_EstimateGasDepositToken(t *testing.T) assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") bridgeContracts, err := client.BridgeContracts(context.Background()) @@ -1029,7 +1021,7 @@ func TestIntegration_EthBasedChain_Wallet_EstimateGasDepositToken(t *testing.T) gas, err := wallet.EstimateGasDeposit(context.Background(), accounts.DepositCallMsg{ Token: L1Dai, - To: Receiver, + To: Address2, Amount: big.NewInt(5), }) @@ -1048,7 +1040,7 @@ func TestIntegration_EthBasedChain_Wallet_DepositEth(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2BalanceBeforeDeposit, err := wallet.Balance(context.Background(), utils.LegacyEthAddress, nil) @@ -1096,7 +1088,7 @@ func TestIntegration_EthBasedChain_Wallet_DepositToken(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2BalanceBeforeDeposit, err := wallet.Balance(context.Background(), L2Dai, nil) @@ -1143,12 +1135,12 @@ func TestIntegration_EthBasedChain_Wallet_FullRequiredDepositFeeEth(t *testing.T assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") depositFee, err := wallet.FullRequiredDepositFee(context.Background(), accounts.DepositCallMsg{ Token: utils.LegacyEthAddress, - To: Receiver, + To: Address2, }) assert.NoError(t, err, "FullRequiredDepositFee should not return an error") @@ -1176,7 +1168,7 @@ func TestIntegration_EthBasedChain_Wallet_FullRequiredDepositFeeNotEnoughBalance _, err = wallet.FullRequiredDepositFee(context.Background(), accounts.DepositCallMsg{ Token: utils.LegacyEthAddress, - To: Receiver, + To: Address2, }) assert.Error(t, err, "Should throw error when there is not enough balance") @@ -1192,12 +1184,12 @@ func TestIntegration_EthBasedChain_Wallet_FullRequiredDepositFeeTokenNotEnoughAl assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") _, err = wallet.FullRequiredDepositFee(context.Background(), accounts.DepositCallMsg{ Token: L1Dai, - To: Address, + To: Address1, }) assert.Error(t, err, "Should throw error when there is not enough allowance") @@ -1213,7 +1205,7 @@ func TestIntegration_EthBasedChain_Wallet_FullRequiredDepositFeeToken(t *testing assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") bridgeContracts, err := client.BridgeContracts(context.Background()) @@ -1227,7 +1219,7 @@ func TestIntegration_EthBasedChain_Wallet_FullRequiredDepositFeeToken(t *testing depositFee, err := wallet.FullRequiredDepositFee(context.Background(), accounts.DepositCallMsg{ Token: L1Dai, - To: Address, + To: Address1, }) assert.NoError(t, err, "FullRequiredDepositFee should not return an error") @@ -1247,7 +1239,7 @@ func TestIntegration_EthBasedChain_Wallet_EstimateRequestExecute(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") baseClient, ok := client.(*clients.BaseClient) @@ -1280,7 +1272,7 @@ func TestIntegration_EthBasedChain_Wallet_RequestExecute(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2BalanceBeforeTx, err := wallet.Balance(context.Background(), utils.LegacyEthAddress, nil) @@ -1328,12 +1320,12 @@ func TestIntegration_NonEthBasedChain_Wallet_EstimateGasDepositEth(t *testing.T) assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") msg := accounts.DepositCallMsg{ Token: utils.LegacyEthAddress, - To: Receiver, + To: Address2, Amount: big.NewInt(7_000_000_000), } allowanceParams, err := wallet.DepositAllowanceParams(nil, msg) @@ -1363,7 +1355,7 @@ func TestIntegration_NonEthBasedChain_Wallet_EstimateGasDepositBaseToken(t *test assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") token, err := wallet.BaseToken(nil) @@ -1371,7 +1363,7 @@ func TestIntegration_NonEthBasedChain_Wallet_EstimateGasDepositBaseToken(t *test msg := accounts.DepositCallMsg{ Token: token, - To: Receiver, + To: Address2, Amount: big.NewInt(7_000_000_000), } allowanceParams, err := wallet.DepositAllowanceParams(nil, msg) @@ -1401,12 +1393,12 @@ func TestIntegration_NonEthBasedChain_Wallet_EstimateGasDepositNonBasedToken(t * assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") msg := accounts.DepositCallMsg{ Token: L1Dai, - To: Receiver, + To: Address2, Amount: big.NewInt(5), } allowanceParams, err := wallet.DepositAllowanceParams(nil, msg) @@ -1444,7 +1436,7 @@ func TestIntegration_NonEthBasedChain_Wallet_DepositEth(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2BalanceBeforeDeposit, err := wallet.Balance(context.Background(), utils.LegacyEthAddress, nil) @@ -1493,7 +1485,7 @@ func TestIntegration_NonEthBasedChain_Wallet_DepositBaseToken(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2BalanceBeforeDeposit, err := wallet.Balance(context.Background(), utils.LegacyEthAddress, nil) @@ -1545,7 +1537,7 @@ func TestIntegration_NonEthBasedChain_Wallet_DepositNonBaseToken(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2BalanceBeforeDeposit, err := wallet.Balance(context.Background(), L2Dai, nil) @@ -1601,7 +1593,7 @@ func TestIntegration_NonEthBasedChain_Wallet_FullRequiredDepositFeeNotEnoughBase _, err = wallet.FullRequiredDepositFee(context.Background(), accounts.DepositCallMsg{ Token: utils.LegacyEthAddress, - To: Receiver, + To: Address2, }) assert.Error(t, err, "Should throw error when there is not enough balance") @@ -1617,12 +1609,12 @@ func TestIntegration_NonEthBasedChain_Wallet_FullRequiredDepositFeeEth(t *testin assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") msg := accounts.DepositCallMsg{ Token: utils.LegacyEthAddress, - To: Receiver, + To: Address2, Amount: big.NewInt(1), } allowanceParams, err := wallet.DepositAllowanceParams(nil, msg) @@ -1656,7 +1648,7 @@ func TestIntegration_NonEthBasedChain_Wallet_FullRequiredDepositFeeBaseToken(t * assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") token, err := wallet.BaseToken(nil) @@ -1664,7 +1656,7 @@ func TestIntegration_NonEthBasedChain_Wallet_FullRequiredDepositFeeBaseToken(t * msg := accounts.DepositCallMsg{ Token: token, - To: Receiver, + To: Address2, Amount: big.NewInt(1), } @@ -1699,12 +1691,12 @@ func TestIntegration_NonEthBasedChain_Wallet_FullRequiredDepositFeeNonBaseToken( assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") msg := accounts.DepositCallMsg{ Token: L1Dai, - To: Receiver, + To: Address2, Amount: big.NewInt(1), } allowanceParams, err := wallet.DepositAllowanceParams(nil, msg) @@ -1744,7 +1736,7 @@ func TestIntegration_NonEthBasedChain_Wallet_FullRequiredDepositFeeTokenNotEnoug assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2ChainId, err := client.ChainID(context.Background()) @@ -1793,7 +1785,7 @@ func TestIntegration_NonEthBasedChain_Wallet_FullRequiredDepositFeeTokenNotEnoug msg := accounts.DepositCallMsg{ Token: L1Dai, - To: Receiver, + To: Address2, Amount: big.NewInt(1), } allowanceParams, err := randomWallet.DepositAllowanceParams(nil, msg) @@ -1822,7 +1814,7 @@ func TestIntegration_NonEthBasedChain_Wallet_EstimateGasRequestExecute(t *testin assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") msg := accounts.RequestExecuteCallMsg{ @@ -1859,7 +1851,7 @@ func TestIntegration_NonEthBasedChain_Wallet_RequestExecute(t *testing.T) { assert.NoError(t, err, "ethclient.Dial should not return an error") defer ethClient.Close() - wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) + wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey1), &client, ethClient) assert.NoError(t, err, "NewWallet should not return an error") l2BalanceBeforeTx, err := wallet.Balance(context.Background(), utils.LegacyEthAddress, nil) diff --git a/types/eip712_tx.go b/types/eip712_tx.go index 21bb3ba..3abc23c 100644 --- a/types/eip712_tx.go +++ b/types/eip712_tx.go @@ -73,11 +73,7 @@ func (tx *Transaction712) RLPValues(sig []byte) ([]byte, error) { PaymasterParams: tx.Meta.PaymasterParams, } if len(txRLP.CustomSignature) == 0 { - if len(sig) == 65 { - txRLP.CustomSignature = sig - } else if len(sig) > 0 { - return nil, errors.New("invalid length of signature") - } + txRLP.CustomSignature = sig } res, err := rlp.EncodeToBytes(txRLP)