From e1a8353388296a6bbdbda28fb4f81d9681c27d33 Mon Sep 17 00:00:00 2001 From: Ansh Date: Thu, 22 Aug 2024 14:18:43 +0530 Subject: [PATCH 01/10] feat: evm-swap example --- docs/additional-examples/evm-swap.md | 656 +++++++++++++++++++++++++++ sidebars.js | 5 +- static/img/mgb-flow.png | Bin 0 -> 113948 bytes 3 files changed, 660 insertions(+), 1 deletion(-) create mode 100644 docs/additional-examples/evm-swap.md create mode 100644 static/img/mgb-flow.png diff --git a/docs/additional-examples/evm-swap.md b/docs/additional-examples/evm-swap.md new file mode 100644 index 00000000..000b6528 --- /dev/null +++ b/docs/additional-examples/evm-swap.md @@ -0,0 +1,656 @@ +# Cross Chain EVM Swap +In this section, we will demonstrate how you can use PKPs and Lit Actions to perform a cross-chain swap. There are three parts to this flow: + +- Understanding Lit PKPs as escrow +- Lit Action +- Implementing Mint/Grant/Burn with SDK + +## 1) Understanding Lit PKPs as escrow + +A Private key is meant for signing transactions which are executed on the blockchain, a network verifies if the transaction is a legitimate one and then executes it. With Lit Network we can generate a special type of private keys which can be programmed to sign transactions only when certain conditions are met. With this, we can create several escrow mechanisms, and we will look into how we can execute a cross-chain swap. + +### A swap example would be: +Suppose Alice holds 100 token A on Base and Bob holds 100 token B on Chronicles and they both agree to a swap of, +- 4 token A from Alice to Bob on Base +- 8 token B from Bob to Alice on Chronicles + +We have an [example code](https://github.com/anshss/lit-evm-swap) for the below solution. + +### How does this work? +When you generate a PKP on the LIT Network, a PKP NFT is first minted to your wallet, representing your ownership over the underlying private key residing on the LIT Network. This PKP NFT is responsible for managing auth methods over the private key. + +Lit Actions are programmable code written in Javascript which can run on the LIT Network. We can program a Lit Action so that if certain permissions are met for a pkp, it must sign specific transactions that can be sent to the blockchain. We need to grant a Lit Action as a permitted action to the PKP to allow the Lit Action to generate signatures with it. + +We can create an escrow pkp in the following way (Mint/ Grant/ Burn) + +- Mint a PKP on Lit +- Grant a permitted Lit Action +- Burn the PKP NFT so that no more auth methods can be modified + +This approach will allow us to create scenarios where a private key can generate signs based on conditions and unlock robust opportunities like cross-chain swapping, messaging or bridging. + +For a Swap Lit Action, both parties need to deposit their funds to the PKP and based on the conditions the PKP should be completing the swap: + +- Alice (or Bob) creates a Mint/Grant/Burn PKP +- Alice deposits 4 token A on Base Sepolia to the PKP +- Bob deposits 8 token B on Chronicles to the PKP +- Alice (or Bob) executes the Lit Action. + +Lit Action execution, checks conditions and executes the swap from the PKP + +If the swap conditions aren't met then the Lit Action execution shall revert the funds to their depositors. + +### Architecture for Mint/Grant/Burn + +![accessControl](/img/mgb-flow.png) + +## 2) Lit Action + +Now we'll dive into the depths of the Lit Action and explore how we can conduct conditional signing. + +Below are the parameters that decide the swapping conditions. + +```js +const chainAParams = { + from: "0x48e6a467852Fa29710AaaCDB275F85db4Fa420eB", + to: "0x291B0E3aA139b2bC9Ebd92168575b5c6bAD5236C", + tokenAddress: "0xad50f302a957C165d865eD398fC3ca5A5A2cDA85", + chain: "baseSepolia", + amount: "4", + decimals: 18, + chainId: 84532, +}; + +const chainBParams = { + from: "0x291B0E3aA139b2bC9Ebd92168575b5c6bAD5236C", + to: "0x48e6a467852Fa29710AaaCDB275F85db4Fa420eB", + tokenAddress: "0x2dcA1a80c89c81C37efa7b401e2d20c1ED99C72F", + chain: "yellowstone", + amount: "8", + decimals: 18, + chainId: 175188, +}; +/* +deposit1: wallet A deposits on chain B, if action executes, funds are transferred to wallet B +deposit2: wallet B deposits on chain A, if action executes, funds are transferred to wallet A +*/ +``` +:::info +On the chains section, we can specify any of the chains [supported](../resources/supported-chains) by LIT. +::: + +You can find a generator which takes the above params to generate a Lit Action for swap: [swapActionGenerator.js](https://github.com/anshss/lit-evm-swap/blob/main/lit/swapActionGenerator.js) + +Remember, once a Mint/Grant/Burn PKP is created, anyone can execute the Lit Action on the Lit Network. This execution needs to define the parameters needed by the Lit Action to run. While generating a sign or checking conditions on the action, we need information around the pkp for which we are doing it. Due to this, we need to construct our Lit Action in a way that works with any PKP. + +Our Lit Action primarily focuses on three factors: + +- Access Conditions for checking funds on both chains +- Transaction objects for transferring funds between swap parties +- Clawback Transaction objects for revert transferring funds to their owners +- Lit Action conditions which decide which transaction object to sign and return + +We'll use [Lit's Access Control](../sdk/access-control/evm/basic-examples#must-posess-at-least-one-erc20-token) here to verify if the conditions are being met for the swap. There need to be 2 conditions for a swap to execute, + +- Have token A funds reached on Chain A? +- Have token B funds reached on Chain B? + +If yes, then forward the funds and complete the swap or else revert them. + +A condition on Base Sepolia for checking if the PKP contains the exact amount of token A in Wei will look like this: + +```js +const chainACondition = { + conditionType: "evmBasic", + contractAddress: "0xad50f302a957C165d865eD398fC3ca5A5A2cDA85", + standardContractType: "ERC20", + chain: "baseSepolia", + method: "balanceOf", + parameters: ["address"], + returnValueTest: { comparator: "==", value: "4000000000000000000" }, +}; +// parameter field would be later replaced by the pkpAddress in the action +``` + +There need to be two transaction objects, each of which transfers funds between the swap parties. Each of them will be calling function `transfer(address, uint256)` on the token's smart contract. This information is captured in the "data" field of the object. We can get that in the following way, + +```js +function generateCallData(counterParty, amount) { + const transferInterface = new ethers.utils.Interface([ + "function transfer(address, uint256) returns (bool)", + ]); + return transferInterface.encodeFunctionData("transfer", [ + counterParty, + amount, + ]); +} +``` + +A transaction object would then look something like below + +```js +let chainATransaction = { + to: "0xad50f302a957C165d865eD398fC3ca5A5A2cDA85", + gasLimit: "60000", + from: "0x291B0E3aA139b2bC9Ebd92168575b5c6bAD5236C", + data: "0xa9059cbb000000000000000000000000291b0e3aa139b2bc9ebd92168575b5c6bad5236c0000000000000000000000000000000000000000000000003782dace9d900000", + type: 2, +}; +// "to" field specifies tokenA contract +// "from" field would be later replaced by the pkpAddress in the action +``` + +Clawback transaction objects are transactions that transfer funds back to the depositors if the swap conditions aren't met. These will have a different value for the `data` field and can be generated again using the `generateCallData()` function, with the `counterParty` value set to the depositor. + +Let's start with writing a Lit Action, + +```js +const go = async () => { + const chainACondition = {"conditionType":"evmBasic","contractAddress":"0xad50f302a957C165d865eD398fC3ca5A5A2cDA85","standardContractType":"ERC20","chain":"baseSepolia","method":"balanceOf","parameters":["address"],"returnValueTest":{"comparator":">=","value":"4000000000000000000"}} + const chainBCondition = {"conditionType":"evmBasic","contractAddress":"0x2dcA1a80c89c81C37efa7b401e2d20c1ED99C72F","standardContractType":"ERC20","chain":"yellowstone","method":"balanceOf","parameters":["address"],"returnValueTest":{"comparator":">=","value":"8000000000000000000"}} + let chainATransaction = {"to":"0xad50f302a957C165d865eD398fC3ca5A5A2cDA85","gasLimit":"60000","from":"0x48e6a467852Fa29710AaaCDB275F85db4Fa420eB","data":"0xa9059cbb000000000000000000000000291b0e3aa139b2bc9ebd92168575b5c6bad5236c0000000000000000000000000000000000000000000000003782dace9d900000","type":2} + let chainBTransaction = {"to":"0x2dcA1a80c89c81C37efa7b401e2d20c1ED99C72F","gasLimit":"60000","from":"0x291B0E3aA139b2bC9Ebd92168575b5c6bAD5236C","data":"0xa9059cbb00000000000000000000000048e6a467852fa29710aaacdb275f85db4fa420eb0000000000000000000000000000000000000000000000006f05b59d3b200000","type":2} + let chainAClawbackTransaction = {"to":"0xad50f302a957C165d865eD398fC3ca5A5A2cDA85","gasLimit":"60000","from":"0x48e6a467852Fa29710AaaCDB275F85db4Fa420eB","data":"0xa9059cbb00000000000000000000000048e6a467852fa29710aaacdb275f85db4fa420eb0000000000000000000000000000000000000000000000003782dace9d900000","type":2} + let chainBClawbackTransaction = {"to":"0x2dcA1a80c89c81C37efa7b401e2d20c1ED99C72F","gasLimit":"60000","from":"0x291B0E3aA139b2bC9Ebd92168575b5c6bAD5236C","data":"0xa9059cbb000000000000000000000000291b0e3aa139b2bc9ebd92168575b5c6bad5236c0000000000000000000000000000000000000000000000006f05b59d3b200000","type":2} + + chainATransaction.from = chainBTransaction.from = pkpAddress; + + chainACondition.parameters = chainBCondition.parameters = [ + pkpAddress, + ]; + + chainATransaction = {...chainATransaction, ...chainAGasConfig} + chainBTransaction = {...chainBTransaction, ...chainBGasConfig} + chainAClawbackTransaction = {...chainAClawbackTransaction, ...chainAGasConfig} + chainBClawbackTransaction = {...chainBClawbackTransaction, ...chainBGasConfig} +``` + +Here, we are substituting the `from` field in the transaction objects with `pkpAddress` and replacing the `parameters` the field in the conditions object with `pkpAddress`. + +We then, extend our transaction object with the gas configs which will be received during the execution of the action. We'll look into this later. + +```js + const chainAConditionsPass = await Lit.Actions.checkConditions({ + conditions: [chainACondition], + authSig: JSON.parse(authSig), + chain: chainACondition.chain, + }); + + const chainBConditionsPass = await Lit.Actions.checkConditions({ + conditions: [chainBCondition], + authSig: JSON.parse(authSig), + chain: chainBCondition.chain, + }); + + console.log("chainAConditionsPass: ", chainAConditionsPass, "chainBConditionsPass: ", chainBConditionsPass); +``` + +Now our action checks if the conditions are passed on both chains, it takes `authSig` as a parameter here and then logs the result of both condition checks. We'll look into auth sigs while we learn to execute lit actions. + +For generating signatures inside our Lit Action, we'll use `Lit.Actions.signEcdsa`. This method allows us to use a pkp (which lets an action generate a sign) for generating signatures. Our Lit Action will now decide based on checked conditions and generate appropriately signed transactions which we can send to the blockchain later. + +```js + if (chainAConditionsPass && chainBConditionsPass) { + await generateSwapTransactions(); + return; + } + + if (chainAConditionsPass) { + await Lit.Actions.signEcdsa({ + toSign: hashTransaction(chainAClawbackTransaction), + publicKey: pkpPublicKey, + sigName: "chainASignature", + }); + Lit.Actions.setResponse({ + response: JSON.stringify({ + chainATransaction: chainAClawbackTransaction, + }), + }); + return; + } + + if (chainBConditionsPass) { + await Lit.Actions.signEcdsa({ + toSign: hashTransaction(chainBClawbackTransaction), + publicKey: pkpPublicKey, + sigName: "chainBSignature", + }); + Lit.Actions.setResponse({ + response: JSON.stringify({ + chainBTransaction: chainBClawbackTransaction, + }), + }); + return; + } + + const generateSwapTransactions = async () => { + await LitActions.signEcdsa({ + toSign: hashTransaction(chainATransaction), + publicKey: pkpPublicKey, + sigName: "chainASignature", + }); + await LitActions.signEcdsa({ + toSign: hashTransaction(chainBTransaction), + publicKey: pkpPublicKey, + sigName: "chainBSignature", + }); + Lit.Actions.setResponse({ + response: JSON.stringify({ chainATransaction, chainBTransaction }), + }); + }; +``` + +As everything on the blockchain works on hexadecimal hashes, we need to hash our transactions as well. + +```js + const hashTransaction = (tx) => { + return ethers.utils.arrayify( + ethers.utils.keccak256( + ethers.utils.arrayify(ethers.utils.serializeTransaction(tx)), + ), + ); + } + + Lit.Actions.setResponse({ response: "Conditions for swap not met!" }); + } +go(); +``` + +A must `Lit.Actions.setResponse` needs to be set before we are closing the execution of a Lit Action. This is the response which is shown after the execution of a Lit Action. + +Complete Lit Action can be found at [swapAction.js](https://github.com/anshss/lit-evm-swap/blob/main/lit/swapAction.js). + +## 3) Implementing Mint/Grant/Burn with SDK + +### Installing Packages + +```bash +npm i @lit-protocol/lit-node-client @lit-protocol/contracts-sdk +@simplewebauthn/browser @lit-protocol/types ethers +``` + +### Imports Declarations + +```js +import { LitNodeClient } from "@lit-protocol/lit-node-client"; +import { LitContracts } from "@lit-protocol/contracts-sdk"; +import { LitNetwork, AuthMethodScope, LIT_CHAINS } from "@lit-protocol/constants"; +import { LitAbility } from "@lit-protocol/types"; +import { + LitActionResource, + createSiweMessageWithRecaps, + generateAuthSig, + LitPKPResource, +} from "@lit-protocol/auth-helpers"; +import { ethers } from "ethers"; +import bs58 from "bs58"; +``` + +### Create Wallet instances + +These wallets will represent the two parties involved in the swap. + +```js +async function getWalletA() { + const provider = new ethers.providers.JsonRpcProvider( + `https://yellowstone-rpc.litprotocol.com/` + ); + const wallet = new ethers.Wallet( + process.env.NEXT_PUBLIC_PRIVATE_KEY_1, + provider + ); + return wallet; +} + +async function getWalletB() { + const provider = new ethers.providers.JsonRpcProvider( + `https://yellowstone-rpc.litprotocol.com/` + ); + const wallet = new ethers.Wallet( + process.env.NEXT_PUBLIC_PRIVATE_KEY_2, + provider + ); + return wallet; +}c +``` + +### Create Lit Action and upload it to IPFS + +Once we are done with our Lit Action, we need to upload it to IPFS so we get an immutable CID which will always point to our action. + +```js +export async function createLitAction() { + console.log("creating lit action.."); + const action = createERC20SwapLitAction(chainAParams, chainBParams); + const ipfsCid = await uploadViaPinata(action); + + console.log("Lit Action code:\n", action); + console.log("IPFS CID: ", ipfsCid); + return ipfsCid; +} +``` + +### Create a Mint/Grant/Burn PKP +We'll create a single function to perform 3 calls at once + +- Mint a PKP with the user's wallet +- Add the Lit Action as a permitted auth Method +- Burn the PKP NFT by transferring it to itself so auth methods become immutable + +Now, our PKP will only be used to execute the Lit Action we permitted. It will generate signatures only when the Lit Action is running and not in any other situations. We have already designed the Lit Action to create the correct signed transactions based on the conditions. +```js +export async function mintGrantBurnPKP(action_ipfs, mintedPKP) { + console.log("minting started.."); + const signerA = await getWalletA(); + +// instantiating Contracts SDK + const litContracts = new LitContracts({ + signer: signerA, + network: LitNetwork.DatilDev, + debug: false, + }); + await litContracts.connect(); + +// minting a new PKP + const mintPkp = await litContracts.pkpNftContractUtils.write.mint(); + const pkp = mintPkp.pkp; + console.log("PKP: ", pkp); + + console.log("adding permitted action.."); + +// adding a permitted lit action + await litContracts.addPermittedAction({ + pkpTokenId: pkp.tokenId, + ipfsId: action_ipfs, + authMethodScopes: [AuthMethodScope.SignAnything], + }); + + console.log("transfer started.."); + +// burning the PKP NFT + const transferPkpOwnership = + await litContracts.pkpNftContract.write.transferFrom( + signerA.address, + pkp.ethAddress, + pkp.tokenId, + { + gasLimit: 125_000, + } + ); + + const receipt = await transferPkpOwnership.wait(); + + console.log( + "Transferred PKP ownership to itself: ", + receipt + ); + return pkp; +} +``` + +### Deposit Methods + +To deposit swap tokens along with some native tokens for gas + +```js +export async function depositOnChainA(action_ipfs, mintedPKP) { + console.log( + `deposit started from wallet A on chain A (${chainAParams.chain})..` + ); + let wallet = await getWalletA(); + + // chain provider + const chainAProvider = new ethers.providers.JsonRpcProvider( + LIT_CHAINS[chainAParams.chain].rpcUrls[0] + ); + wallet = wallet.connect(chainAProvider); + + // sometimes you may need to add gasLimit + const transactionObjectToken = { + to: chainAParams.tokenAddress, + from: await wallet.getAddress(), + data: generateCallData( + mintedPKP.ethAddress, + ethers.utils + .parseUnits(chainAParams.amount, chainAParams.decimals) + .toString() + ), + }; + + const tx = await wallet.sendTransaction(transactionObjectToken); + const receipt = await tx.wait(); + + console.log("token deposit executed: ", receipt); + + console.log("depositing some funds for gas.."); + + // gas value differs for chains, check explorer for more info + const transactionObjectGas = { + to: mintedPKP.ethAddress, + value: ethers.BigNumber.from("1000000000000000"), + gasPrice: await chainAProvider.getGasPrice(), + }; + + const tx2 = await wallet.sendTransaction(transactionObjectGas); + const receipt2 = await tx2.wait(); + + console.log("gas deposit executed: ", receipt2); +} +``` + +The deposit method needs to be called each for token A from wallet A (Alice) as well as token B from wallet B (Bob). + +### Executing Swap Action + +Now, we will execute the swap action we wrote earlier using the PKP we just generated. To do this, we'll use the `executeJs` method on the SDK. We'll pass the Lit Action, Session Signature, and the parameters for the Lit Action. + +```js +export async function executeSwapAction(action_ipfs, mintedPKP) { + console.log("executing action started.."); + const sessionSigs = await sessionSigUser(); + const authSig = await getAuthSig(); +``` + +Session Signatures are used to authenticate with the Lit nodes and create a secure connection to the Lit network. This essentially informs the network about the user attempting to use the Lit Network. In a Session Signature, we also include the resources we are requesting from the Lit Network. For us, that would be: +- executing the Lit action +- signing with the PKP + +```js +export async function sessionSigUser() { + console.log("creating session sigs.."); + const ethersSigner = await getWalletA(); + + await litNodeClient.connect(); + + const sessionSigs = await litNodeClient.getSessionSigs({ + pkpPublicKey: mintedPKP.publicKey, + chain: "ethereum", + resourceAbilityRequests: [ + { + resource: new LitPKPResource("*"), + ability: LitAbility.PKPSigning, + }, + { + resource: new LitActionResource("*"), + ability: LitAbility.LitActionExecution, + }, + ], + authNeededCallback: async (params) => { + if (!params.uri) { + throw new Error("Params uri is required"); + } + + if (!params.resourceAbilityRequests) { + throw new Error("Params uri is required"); + } + + const toSign = await createSiweMessageWithRecaps({ + uri: params.uri, + expiration: new Date( + Date.now() + 1000 * 60 * 60 * 24 + ).toISOString(), // 24 hours, + resources: params.resourceAbilityRequests, + walletAddress: await ethersSigner.getAddress(), + nonce: await litNodeClient.getLatestBlockhash(), + litNodeClient, + domain: "localhost:3000", + }); + + return await generateAuthSig({ + signer: ethersSigner, + toSign, + }); + }, + }); + + console.log("sessionSigs: ", sessionSigs); + return sessionSigs; +} +``` + +The parameters for the Lit Action we mentioned above include the auth signature and gas configurations. The auth signature is used to verify conditions on the Lit Action we discussed earlier. An AuthSig is a signature created through the user's wallet and is used for authentication. + +We can generate an AuthSig as shown below: + +```js +export async function getAuthSig() { + const signer = await getWalletA(); + + await litNodeClient.connect(); + + const toSign = await createSiweMessageWithRecaps({ + uri: "http://localhost:3000", + expiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), // 24 hours + walletAddress: await signer.getAddress(), + nonce: await litNodeClient.getLatestBlockhash(), + litNodeClient, + }); + + const authSig = await generateAuthSig({ + signer: signer, + toSign, + }); + return authSig; +} +// this remains valid for 24hrs +``` + +Gas configuration may vary from chain to chain but for the current chains, the configurations below work well. You may need to sometime specify more parameters while constructing a transaction object. + +```js + + const chainAProvider = new ethers.providers.JsonRpcProvider( + LIT_CHAINS[chainAParams.chain].rpcUrls[0] + ); + + const chainBProvider = new ethers.providers.JsonRpcProvider( + LIT_CHAINS[chainBParams.chain].rpcUrls[0] + ); + + // sometimes you may need to configure gas values manually, try checking test minting methods for more info + const gasConfigA = { + gasLimit: ethers.BigNumber.from("54000"), + maxPriorityFeePerGas: ethers.BigNumber.from("1500000000"), + maxFeePerGas: ethers.BigNumber.from("1500000000"), + chainId: LIT_CHAINS[chainAParams.chain].chainId, + nonce: await chainAProvider.getTransactionCount(mintedPKP.ethAddress), + }; + + const gasConfigB = { + maxFeePerGas: ethers.BigNumber.from("1500000000"), + chainId: LIT_CHAINS[chainBParams.chain].chainId, + nonce: await chainBProvider.getTransactionCount(mintedPKP.ethAddress), + }; + + await litNodeClient.connect(); + + const results = await litNodeClient.executeJs({ + ipfsId: action_ipfs, + sessionSigs: sessionSigs, + jsParams: { + pkpPublicKey: mintedPKP.publicKey, + pkpAddress: mintedPKP.ethAddress, + authSig: JSON.stringify(authSig), + chainAGasConfig: gasConfigA, + chainBGasConfig: gasConfigB, + }, + }); + + console.log("results: ", results); +``` + +Based on the results returned by the nodes, we can execute the signed transactions by sending them to the blockchain networks. + +```js + + if (results.signatures == undefined) { + return; + } + + else if (results.signatures.chainBSignature == undefined) { + console.log("executing clawbackA tx..") + await executeTxA(results, chainAProvider); + } + + else if (results.signatures.chainASignature == undefined) { + console.log("executing clawbackB tx..") + await executeTxB(results, chainBProvider); + } + + else { + console.log("executing swap txs..") + await executeTxA(results, chainAProvider); + await executeTxB(results, chainBProvider); + } +} +``` + +These two functions will handle sending individual transactions on each network. + +```js + +async function executeTxA(results, chainAProvider) { + const signatureA = formatSignature(results.signatures.chainASignature); + const tx1 = await chainAProvider.sendTransaction( + ethers.utils.serializeTransaction( + results.response.chainATransaction, + signatureA + ) + ); + console.log(tx1); + + const receipt1 = await tx1.wait(); + const blockExplorer1 = LIT_CHAINS[chainAParams.chain].blockExplorerUrls[0]; + + console.log(`tx: ${blockExplorer1}/tx/${receipt1.transactionHash}`); +} + +async function executeTxB(results, chainBProvider) { + const signatureB = formatSignature(results.signatures.chainBSignature); + const tx2 = await chainBProvider.sendTransaction( + ethers.utils.serializeTransaction( + results.response.chainBTransaction, + signatureB + ) + ); + const receipt2 = await tx2.wait(); + const blockExplorer2 = LIT_CHAINS[chainBParams.chain].blockExplorerUrls[0]; + + console.log(`tx: ${blockExplorer2}/tx/${receipt2.transactionHash}`); +} +``` + +A signed transaction returned by the Lit Network has a different structure for signatures that we need to reconstruct as follows: + +```js +function formatSignature(signature) { + const encodedSig = ethers.utils.joinSignature({ + v: signature.recid, + r: `0x${signature.r}`, + s: `0x${signature.s}`, + }); + return encodedSig; +} +``` + +You can also explore other methods, such as checking permissions on the PKP, checking the fund status of each wallet, or the PKP itself [here](https://github.com/anshss/lit-evm-swap/blob/main/lit/utils.js). \ No newline at end of file diff --git a/sidebars.js b/sidebars.js index 5ba87079..875357f9 100644 --- a/sidebars.js +++ b/sidebars.js @@ -523,7 +523,10 @@ const sidebars = { type: 'category', label: 'Additional Examples', collapsed: true, - items: ['additional-examples/intro'], + items: [ + 'additional-examples/intro', + 'additional-examples/evm-swap' + ], }, ], }; diff --git a/static/img/mgb-flow.png b/static/img/mgb-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..9dddcaff0e250c09669ae9c9028e2ceb98ca8b45 GIT binary patch literal 113948 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
R-`Gls7T_^vE2sDagg_2_28uAb z?;I|&sCLn`dQSX!A!l!>#Ctw7R7vX|hsfI2b2z$)l8Wl`1K{-?)+jJYgyOlVxt}gi zh1riEvK5|s9gV|qr|ifY4$V5pwrbgKH^-j*t9bbObsuy{QHtsXVU)KwU*ir~{dFav zqp%uoPcxnRqkc%L1ogxFf${Rvlwk1|7E<$JQ{lk&15r3&>bZ6rUf^{AL(Q$j*FIVlhfu5ffPfeWg4jv?o-$g(#ADrlIOXib!MpSEbZFv zY?u^ZVY)O9u(pdN_N`rN9#jysG3^$|peyulLDr*#8cpr&7sFJrg@vce!ERM)(<5Z4 zN&fFRzD3oC%rMsLxB7##lryR;XnEY_-g7#BW z{_9+Yis9?b|NiVh?^5vSkSOv#pF!=e|F2vYZyl`VL~39(A(N;4r9nRn{h3ec|7#~m zZm`q#5rRzG)qEq7{?oV}x#azM3;09r9sXPLy&*j)4EVcj`~Q8~|DT_;O{xAvzdyEd zoB4H(%-x3OO8)bDffVJCe=Yj2qTV* zX`HJuxtkH{F_MPk2`*ZF#%qPQAesLFlE10c#*R1YP-6^U@?jZjm*B1g& zc(j7j?SLcjx~**bA43E6Y33wGJl}BS^(^U5x>J6cl@$z3 zs}}7ZmS}2hNxYFy`bF}K>z=Z(IQd!mEZmEce-Bi=`$Ro&-mU~yCu2&A2Dri$sj5!( zr1U`ErHrz0oNXf+LaqORXac$>h%UEDq{AvyeS}uD@9*iL2jS(o^$)q!4002(;CF+6 zbNzdk$CTsdfwz#*Itb$R3oUEc#MlXPh3&YgO-fmbU3rl8J=>~F4<5Rj~EKwb?LG2oZnN}r;0xN-TMK+(Rnq{rrD98A^olRZB3<1Hx? zfJ#hs6&6&SN-dGYy0PKXb!9X4BCS%vmW8i%o~DQ8B?YI>iRQY`ARe4wC*a6*ur9CE z5_u9kfBKAd$xO{Fx94$|Hs?pPv6rFg>P2v;7*7~bP9?Lmu#vJApt#vSMuM`-v!97; z`T{%_Gs#tcaBO;WTNJuhbAZM?3+U`dLDw>?-zEb=EZ3B#os~Xr5YpKTRa2`E9o3W$ z{=wq>M^y01rf^w)(F(Xq0gL_;xAN_wn(@z`Yb;4xS#}Q5*U{P(-aAi=lz{$yQ!G+g z6N+9xG{KU#{_@lyzfW5DV1I1qmoHNwSbuKvxqmQc9G9TTa;rQFwDa*OVi1CYQatk@ zIr-99rgX+KNSlp%guHp zPXnz#TF(Iak0-jNffUW>a=t^a_r1`UshZosW!820s|(7Qj+lFzTJ8be4`A&gGS-LHZ@HKW!e;ar6+nklUTvq8A4S?~6}pS-Rh#?#EAby;86wvRGV02q22hB?tH zX}sG?>M9q)E^|?rjWuArYSg-mhlR8fyRg^y5ZCD5j$5$WH)ya9gGqA~fip=bF#LNq zsUQEG<1-ZNU|Jlts+7(@-Y_VjB$n^F^K^kABO{bQp2Vh)qhS z8*%o#leh5z`v{Gw$;lJY`ur^J{0?n2HQEh&z>0RyNCc58xfb<=+{-sAqUsm)?O@ru zWgFpo5*8-Zo)Aq^|6LvEuVZ(Hn%V6WPqlt~^5UC56`u_?YET5QCZ=&3;*ymZBR(e1AJyfchmbCbiz|x&wV19qe4Kn8!Ch zniSh=*7i*Tv}A7r&>qdkZHtmn*9U^w=1$O;zG*CI^?lOtLHpGA=whHcz7;OK4a8#H zS|}Lz{+Myo$Z`Us^Z9CJeA`;DyMvTR%XRgHTW;m$LSV364j_^~R1At?$>46WX8~mEye36Sthu9z!h8D9q}LUa-umz^R?MVu`bnk)F6+~L z1^6^5ur>*SXVI9r{Q1R_rGkRxoR-%>NSDuq`5qr0DxuY9Q&aSiTqAB7PRsO2Xj2h2 z$O3=`n9iM+(x>z@xAek34V!x5>+ZG(etF>Za0#G81ar9a6Et6jH{K$#H3A@U!+p;)_UK+fWejSTcWSO3J85C~zd_sl0 zaBQSHi~B){i<}-O(miUX7!R-prCqt02^6=3+vny(HtPF6gH{r|9nLfZ8hK`jKi8^gby z(AH-Q>qY+8_5D`Hxsfvem($U&lo?7in!X!G>4>Vw`OiiB+fC{3$=xr2c)LdO=TkrX z1zG)lbpOD;XUzK2K@ml+<#djldkzZA0xqk0Hgm+FtyN3cE^U++76j{0phn?<`;d&- zuz@tVnPc=Po$P3)jSF;-R@Jm+sHuh zT>1GC^e%C?{B38NT{j7pDNJbd(M zxCc%&GE!253l@dI>2RDZUV!#sGVbwN1DkmnJ5*o{BQB^#_&j6(PP!EO>9Jh0AUIj5=WNRUq4}$rgUl1t`jq}X$T+bf-+Q96(!~sX^ zkf|wij~^pJ06Q{eej{9K+L-q38UZtyEAm>zfYh0^i|M5n2xXz8Sk`KA&+7HU&<;VJ zFRy^cfb^_P00AyG-!gvX8xd-C@kcmnJ&>(&2jTwx4ULT?#|6IJ1AD)1l`_!EZc0d0 zR#X&N4DL^oZQL!wCjz23u-1z;zBDA~|5M%!0z2N=1`~_@&anlAO<%^w#^6B{YyodM zW?~Ms3FtUB0S$8#ln1h8oL7NX0WIfmBRm-Y>sPx7-S;egE%zA-0v>`!kzKv>%zZE_ z6&(O@gnjMM8w;)?7wS%Wy7B^PV(1!2oDCLL$b$FU+7CyA`!@V7tAK>?y$?u;mnunx zxQ7>3mu4P3cmNHP0}JFLYo;nJpxNVKfj zq5CNXX(iO@+XYmL)Sn00 zvoou@s;a~Ctl`2-A}s}lYx!0{RWl9%aW;7UODx?8Tr+$489095PmnHRMeDvkV+h+z zM1*kQkOroFJCkB&5Z7GZX;51-B{aMymcD&!xTGGRPvdu{)@wh{N%m2E-7c8-hH01< z$VBfh4(Hw`?7HA7?Ht)FXxMPtRwdK$E`~^2AKJ&(R8{GaBnVdIp7y=1T=MOGi5Qqg zu09e}7|^l9+&@btW~;Km)W(97j|hj-J>0gpLZK%&MfVul0n+9PG|olb%eS8~BLh#G zu_Nh%gtT;g1+=|>%W`y?NDEZb9pDVG_>DNN41I|1`eS$ZMD!=gL%takU=ILx4^{1k zPao<+)AO4*i9*3heBJl-za-Rh;a9L-=?%`&gkU*n#W;8X1?+%|y)qo&5d2{TT6(`N z$;-Qi)sXDDvhZ>MiCiEOmz0pWt7eMLi1mf(-Gxw-&hFWo`6&G0Zd z42eim3cIXcB@t`_6N9-4A_feV=OgTmg31D5{9V(P=&-Xk!2`wSw$tE0&W|B!Cg9+? zK&9IED{w}H^s0_Q6JZ+uxNi3b8pTww7t%mhL4^yjLecg~qm1irZf<};0E13k1MRdl z4Z#fZ(+dW5+TBI=BZ^_S@-5DUPCx_bxEXL!O)0B}(s^g1e3mg*j@Rw>nb9i_4h02- zcy1lJBF?9G^tt_|J&#f82i5)E1gMf*EIaw(cy23vimPsFxRzsTZzz z39%5!QOiZ*!{9Do!hNqvTT6aH9Gnb|(uzOV7|kc-6^@aTT5-qMDI}uB&A->3%#k!T zO`V0RRTB%=$V!{*=4n*A0PVyeGP|&!wNf>tV2d}1M zY@#!St)+%1V7cg^NhQyDd6usWKtn^Lfp&2w(`x=RgNve`)X$zjzkBuk-Oognw=z3E)c+V}ZIZH%wV&RpYDQWPv-dFRtQw`A#F16|M(2(fq`oY zmM{DJ`-_SM=65*eGgdTwt`MxP_VxD%{N#eLFbX)w?bhGk5(BYwWq!QSVJ=axIp1=~ z!qT!CZJic!CDezQg`2S=W0J6QrxYQDt|nAm$;rrUX2dzDgrGt~^8a%h7LTodS7 zkl2ODJMccfe*OB;kt2<8G5|?9adZixT_9-jWbPl_sp-PWlE&0M$e+~9yg(Mqr)e1S2;QlWy0XKNETzxC5A1~gmP&6pr>d)~0}C9;?CvDAsm}&C!ocr5F0DV3 zYsFVERPGS5-Q6vO?EX(StEY5ybUuFiL=5L0@Zv`te))L*Mpye2lHE4C9eZR;{Ojdg z$n2K-1{teO1Jv!i90Gd&>6!X}0IRqCM4wN`lm7iyv`rQL`xWAU`KF$uPC9w@I0rks zl2!+v%<%v4O?|2fT>zH8M>~T{DK!2#y{$I?&Alz(Z5NbYP^1Ok(&1RoV7^dINx;J=!~pz ztflL|F3_7Ug^y_xjj zZ|0@1EnG@Rpq6S@t!l9(UQ!T-exNMcsGQh=8n)0>n)e}zBq5w{= z?_4lwkNKF!-a3Qyll|14m{I{JoyJcR`No0n50x}5k1~r2Z8B~;+KeM^MY0Vqjs*2z zr2q&n&x)r0!cF-_3Qb{rcAuQ#!U$3f3)bxziA=&@))E6I7br+NU*11`ss|;4rcFh6 z)yVM4N^Owt1b|-mCxazTQ-nklHy&^XEC-f^Hu#Y#MR^@_hl zYnfM3j&iIAtq)9>-!$y6^{DJz&SS)_SGG7Rln($4r+feu6@98VFU9h!2Tr2{5!m&zTo!MP@LGYl1&1t_S9G!oL?BGM=# zNR7f!QV!h=L)Y-1H>jYGd%xfNf9rFtz4qP;Gk08ZUdMUFHZkQZaRQT40XZEsspc;A zeyy=J4-cL$s2n@Z8gyxJjNsQ!&F@UQ6CWTnBIt6{9V^Tnyr*DDI;+mcWXV;87wj(K zl=cBMCwK2#o?5)9W+B}pl4WJ2Z%)xCH@1u>yh`n2CqMi}Gz`bhKdZ;Ciqk_&l%3Tb zX7Mecqj^~D0uBmP>G^LcWCf?U=CgD<72f~ssp;0FPG8&Hqli!Z?nm?ed5I#1H@)d{ z>5MAahwKH(rG7QEw;kg`PnOC`&N1gp%fHx+`>Oj&Jq)N9x=BsdvGr$)gdsyAJlecr zbe2vmR>()uSxi#vlLTz_=PgvlK7YZa5u)dsvaA{<1gks^wxl`KCtJ7ExEM4V4@oTC zA8lJMo_3t8*d9O(uJAPIud5vSRu~DjKZja0E5_gJ zv>5D#m56iY9i?uC-CrQ+Dc8H6N(*gETQmM{-ULMEsOAf$ImVRJ7z?47GKTJ!vu6|!=n5Z{ z(f{xW6=QwI!Ug{Y6CAE9>1uh(wG<>R;u?2od{Zxo&>vYTYO}#MWOT0#8(Z`-4W@Pk z-#TR9Ul*BihZfUX{Y~z9uOXV8%EvD~{j{WitzM2xOOX<1X}~+VgA=7ma?WW&WJ|8&S3c`o^=VqOoQ64y zRd3C7=cqd-%cASzWcx2Y46~u!q3f`-hHSh}m0>Vmsl)m1R_THp*@*;UJgf90&U5w= zpR$eH{lX^bP!o2W$mobJCr<1!vJFn^siQlx+Hl;thnluTe&iL7(aF{Q!sKLKI#LGX7wvM~yB4AnW!u3q8eGa1cFjinh?x zV`!gS3>dExt>F7=`rY0l*pDzV-jdJ3#8hD34*4Y5NP%KDyJIG=b57Iml`Xnuf99?A zc*p%u)Q1}NK2?iDQjVd^Tj?|_a;p04OEwM=+PjA|(Qdr(KAjXzQ~-{fN`jAx(!qM@ zzQKt!U)ie`+5`n_tIk&zdy^E(ye>OKdkZ{lbyrTl&Xr(Y&RFeD-}?f^=+UweFe116 z7NjB*DpOOb88yEtEmFPUjfq8HVpe}$G!5Ty$$JXEP**h@92Y(vUWiD9z-Qv?;G8m_ zTGgNnE)KVEJJ}RQqKg7AkXmJ0H4ZJ$+%JfyN~9<&z5g|SrZ-hr*!(zUEmIK3d1d&% zv7L@aFRZlFT-`>q4saA41B!SR#H0$&w^}kB^8HB9DHOKUSEsKfEjeeR{k?rxy~W}; zTM8@Sc9a~u9~bt=Z$gEu)RJY_3ooIoD{n6~A!Lfunn7O)FR|yg==X&Fqs=A}Hy4v1 zky-2jNdX5y>mprENcY=-=YCE`b&LYP3zL05)6j{gMzj!2q^yWb0c6eLaCNQ0X5^YQXrj971 z&su+iq!Fs!+Z6Co3|hG3l{__FZ{}(4XG7v=SW4~v!b3D~F%lJcTZke!yPECg?jb@Q zry6oz>r^@t+M3ny$C~~E=M+@mXR@`C^dbfNE#L1;BN;~lo7FeRXC*fv*%YJPU!u8t zPpcul9-1F~_x*w0qc8I+ZNCaLiTwALp+6pEAGA4&z(Vv+aGB90_hysToQ2RWcUibh z!~I_1M!|yj?>ul)gkx>sd9!beWfYBDgEfFp%sqr+Kt_B%Zl-T-<;Po$}2Jh<*q*KZi^+z1%TA{{D>+DP{Z0A5uB9bLe)EAZ}kg9_QFl6Q zs^#4sU5^PuFks;zLPZgR>js-My4!NCT1Fvm{;H^Gr*lZTZ=oCiw)N+`7P?Dub;J8R z*V_^t7#R5C#W}#-MBMCh)hV13px=ET{D5iCn;vdA2acw^y!XgRXKzo>KX9QjG41c} zJZzAw0ss}(qWQWQ$tC|_zp2-VHD?ZBGhy(@+xvuYFZe2AzXK8q_!Fq_{f81VFT0Y$ z+27mPyrbZ=dBq|GT6IBp0TR6~ib6sZQ#Q^JJVm){6Hkg+>uy8YrgOR+d zrHr(+8R*L4c)gFBx+PgP3-X0Bw<~d?@!E+I{s46@FHK@pmjPtB6$099eY@UhAx4y9 zq&cK!Jp&*u0!xITFMTtp_BwdD4To51I{>mtSO(DZ4fJl{rB02u&d$oTkDUPDQ2^64 zOK)~*KAc{!`e237>iaPvU7ui-ZQNEsw5?hLg5CBqI`gc2IEWWJ3#S~8Sq8W1!O2lT z#@?x?!ibhL*5`&Jd&FU>Jy;fQS;Gq|9jr`D9*-X%=C?hYbQIpLh|W-_#?hCIl8`Ls zZO*2W{u;V2b%ukGz=WTi9B#?#hlseV%UKe$DMB#nz{rxro}gzp(T~G6`;eva$`l6W zdAf_fCyumajmVjrnmRfP}HzEZ;Z#ij6N z{>?2AH`Xp_+4DG`=N}NKr!RorW1_I_NT4-e*jJmZkA>TZH>~1+S$qzL zrwoxH8bW0&fK2lw_Xo6VfWPZ_TzjTvZzYUdh!eYD_RX5OH1BJ~tQ7yH*LK7mPl>z> zzq1x+&YVFdDv3M120X6r@LTitA=bU00U`2l8gI>!HD**Tbl{%G1KgQ!F)d!2q*<7U z{r>&^LjoCeZV=bgL576uNsXZQ9B!mJV;D=oc~?}3l?l6?RY@lrsxLU%isl zI0g_|_UGzq-!X?koOqT&jS!gQ!pI;$#&`7@^oyG1CHe?toe7F@&}D$0Q@i9I zyY8n76Os}hWM@UVq9o-J@2cwZ)eQ_zA7f%*m;*Z!v73IzOiJ+=#jj7Gx(<`R0Z0^S z5bEju(>_P2VoTs)V@rc&5ZVY5cL4$hEj^;|t(=4| zaPoakHw*?77owG*5K~f80_fplYW~>EA}N`n$&XJCf|5242MAhC2yYg=Wb76bE7-}P z8=D1oeb7}-f-R@YpG8qov3;Q%80&CTv!+)?&QS{d;9t%=xRAb?j#x}Hs)A#vK7reXb%JVtEuV8X!)j+t*}2o z*O7rZBj%$Uw=4WoOCG@D@Qz&F-IG@G@;O;lGxflA7;Xfzx1etqf|%cmP&b1dwTi8{ z+8p*3K0(3dnQnowaqi}Q>kHCqF(b?Pm_sIu$E@g@b_&T=`K~N(z>%Rd11>V)FzpQS zgZsbJ!`g8Sk~yH;2O>v*R*ggfQ(^is?q=%s58Jr9eHT!J#fmVJg#m~A7j<_ZZr}6a z!-sv}T|c#$qzkXtDnKd-;QjH<5zcQV=nB9rzf%qjUh26wtr|Iui%;;Wc2&h@l2-qy@nG~aoLb6xMTkOv2{wwdIqbCK8e))tF@=;vlUw(7p%ro#u9Y8 zWWodzfCuuO`Nx@ntrEqv;eD8TB0o&=$PHz%v7knlVxsSZKkjp0^wKS~{>Ex`!#jCf z=92$enDlZfbJhk#Wy9W@&O&UJCd%)l(G1#nNZ3$Tm`!w=6TBXL!B?LBz25vkzG$e& zIXGg9MF?1y{{Bd- zk}gDjm;7}T@{UpIN&DH0uKwkr7C3N{7HwS{BLLu*UGT8xKKW@9e6)U+T4wgs1{99F zem*ngtLGaYAI98Y-|OG@!lmQsf4v!oB6$kbDV+jvFZ@~8q=UKM(+6zt*WL}2Cz%!; zB0q>|70rC}e7IeZe`5J-zHORZ4xxK@NSPm5n(LFCF zhaQNp7qWzuoA{%pJY1IhrzabxV|_CR+PaqO3TXCsH^2;ovDfNZ*vNWor#E|5k8u;{NFSE5d1# zVflA4m65L&RceB=TB9OA#7Q|VR(yRnqFy`L!fVoW+NoI3tY!L03&BB|AY+>Az@j*G zpRZuBvNt4Yo?$4L!6T2ZFqP{_lF5Ml!2TG;R1J)Tq?SJ*3id0eN)+ko*7!|1Mnp&2bLZ{rzK$G?N*a+DPV)U?pTV4D zfZhE3bz=Vox`ZeSza6xX5A&R3Wr**%LN3CpKBaHaIP~Sq3q0On^qb((!{}L;0E|ve zytL2h_Zb;pZjZRYj(U-Ck3#ReJ85%^s3xYctlS zDfo2zo}rW*%g6Gi#WNwCl;ZewZG$64fH5n9$i4V=SfX7;qg2MCozI~UH8C>t7W?tq zvj?}xyuBlkW?#l+ab5g&a_8s9@pk}h5L#T)m@na?lWFJG9|R2Ktudv@6+nmWZ-mzu z6F&^Ll_EDjE#Uw#6LZ3shIrJcXLqw8+*3eZd?|vYlIvzDnJ0pK?8}MN>MuQCV3Z@%x+oFhBEe>&p zBXf+$OSBfm=9gTLjkpyIxQb8bI(T*EIk9>~j+OV;+-u+-aihrE?P&>;IN&TiY9K!{ zvpGgGy|2wlV%xG zTl)chbmq}WfN`ketz)|exn@ivkZW~g$TgASPeVouN-k5)r|r+s+ZLJ3dO!uP#n@ar zloNBhlC!{|KWrpG(xruxd2s%+J&Zy6)gt@t)%6p;Hdy;nZ_|3PwgKpwyTv(*Y&zT9 zZ@+dwoi$+}%oW9wu%~(LY7W zywZ?8tV<*|1fSm%c0sE$h## zq;FO=ilnxRmJM0W(0|^ctkcg`JJhfo^J&N4*oxn7qT#YV1kSA9#37~sb`Nz0_T3Rz z!ck56=CUR`$d{9ezRlN{5;#P7X125{ot8phuY3gb81Z7GG`l<{nB9?Ls=!T2U`}}C z%B`AdeL8=+Y9t+JkNSQhmE#)uu|jIloKp-5v9Y7A2P->;vTD{bqFe)9%&f<{54AJ zrSp5WNo$FFsx2le;4$iwtdbGAAnObH)%IUr8)}pprE3+BDFk8#P?PfNiMasO3$uFd zfLsHKn);YPq=ZM}-0br%2~Lf77CJ2|Cl?x28`!DJ3x`BnF&*Q36QR#*Wy{ZP-g@3G z94FYxR;Z6ki+0}~)1fN!KFI?pt3T^3)8Do~DG01O#6lFkbxRCRLgR%OV4zz9o|?Pp zqmlT=R=|SuSfXZov503Z0JfCJoah!G-qih6pq_H0;qhbWbzPw4Hh$r|i!m2a+NiyZ zDlk{f0IO(8#}&c?W!*ilRg^}n`RRE$=mL*WD0#WfzK>@Aai3T#Z>k#SsnsEuUf;`p z7t;a4a2(j>!2#+}@4Qp)unOGejGif>c2dR^>}$3><2;-E`Du{PExH6|nSOYS9hpgB z>gxJ3TtVl*-Dc&<(k#oV=Gf}whPs@nK|jv`+tC_zn;G@s0s?jrn>@lja?rwAK3vA| z7*F8kxU8N8Rp|QY^(S9nIrp|BcSsaRRp_jKV|Ai)?bg?*Y#nlNo=CS+?yCu>J*uvy zk;brkF(!v(4^>V+Kv6#VAGTpX4L8yKZ~kEonwaRh5Wu=<49m`zE#oqQ#OHa>Zf~R3 zgu;Kd21O=6$?f9+l8XERxUyJBQt6?0ZCtUzHNR{Z{PJ&WAi|Npe90{U0Rr!(Ams{4 z$$e0Dg+PGP|FqnIe|*=Y2V`srYL@vr@@f6qAJ}9oVW@^-?mz*@5A2fS3`Ier*gEc6 z@^)kC^jXYprN>8{A=Ve%g%X(MrC89{=fMKw@8u82OWgajYp`)q^%~5ntp>IDQq*y- zUthQimac+%+4LK)tE;%Zhi+R0Zmrr`??wUW`}!#!sb8T)Ty5;EJ&)Cr_J8+R0Go@< zlkSlJWOV2U-u7P#W1y03D8&w~jGkU$*tzFtMY+}j-1ykwNb&!qjQ?L;G*sJi*H*7% z(`tsphSScx=>N%IO+N>+v?-kH!BA?PY7+nA5-=wNST$ZYLA(X9T`d7yg*bC9NP=2= zu^(K(;M5zI*~sZ|g~=uy_&9=hXY_Kk94E>E9_VmBN>X_g0kZ#o2Sdl4x}ROB{ES9d zyao^#@_@zdwCsB+X*z)687mu3{AQ8{0KjqwHt-joTtcmoun0uG-=X4ysb5EeA2|9f z>#DHw_xC(>47hPpVq$?jcOv=Xt@b7WllczVenMahD9rl6E^4qixhOvV7VxjYg2-P8 zEqr&zR7nX7P;f#EV3uj>xe5`NU7_j_(-7~^%a$<&1{6Sib#-;-ZSUSE=q+cpHl=CF z%F1FYDqe(JLK=?oZ3IB`^+oLcB#1A1oQ7(?rO;Gwz=g5BmfLph06qocEZ?@=_6!HtW77p))17pExm+|v`-<$xS0LVP%Yn$t`Of{f&J z<#`7Oe*+R6@ZXPfaAd+u0?=7+PrL#65Gq|^0m>tix1~sLC}yr2?vT}Zv>IL>Sfw+M z8&z(+ulu`aIwBsr(>hnoqv_|D z^Z@icV!vqmuwwmENuxFc?n8-A5<20y# zE&A{4A1Jb$@L&i?{?`$n_fn|Uzev$-7%4*duLLS@+S>hLemDLjnq;w27bW6Y^Ded9E<&ZT3nkg^h90# z+xlnufUkew6?PyU4%M{-`!bVDa+;D!X}~fcxRbfr90hvt*g;XTKwKQ>MW#U}&^C!g zBK&Kpu!|7CeAdg}(ViZ?Aw`GB2qL@_xN<|RwfJ>J__Np*9Xn)%7}zyDeDd^Z2)nKu zwgZq9VHZUK_unCsym1XUsE*u2@DtyISYG!)px=M}3d~8{fG%dqtYpmv6}438UvxT7 zKFgf(H>e4A0=|1leGs5IAk;1d0DI&Nj+-AE4-HlCqlfQ;V+13w0-L;X{h zg&r9_)x6O#-F~92F9B>di{UzQX9PgEv3)aJ!8&>CFfY#Bu z8-i=zIbe?4?;-K!{snfbbr-i|`6X`piCE`?dol5ZD@bCXGY(|lp_?~vf|><#w*-1` zCSt0phQCJbXn^*6BNb7&4i=kYK#wfF_ZK(#REx z_$nvFOi>YTo#cA?<_%YZ8c90I&pzk9l-2D#_!caekOxMfAx-sN!i4glNmF8AV5s=~ znb&$i?&i&it``ea0Ni?f1mN~8rxg<=SPV0unN4hNyG6$aX7_2s+Ot?jrIp?aXtC$B zXMTG(-9s3pNYnmLG-(x}!@j1M^p^rGy(Lp0c;;}gV6lvPix=sr1>(#yTk#S{z93j} zgPn7$R{-r#wCGnGe%119Lv^)U#c+bdz(OLT+*p)}q z$=;-Bj{^3SG66IH2&VcO8hzn&WY2LJw{n&+q z_zC1oo{k`|WxV13`Yolj!H`*=YoO zJ=n7EhCUT3sWH&x!KaSr5cuYJtr^>qT-2^BCqP3V$lC14zwP_+Z~wyVe?Dm;Fh4%D z;)G^Ubhx|ca>hZ)iOb#M@&oO^` zs1M>VWD-0?knzn|5TbEL`WXtH0>p*o&wmh;W%!8Bz$@~tF#LF@K>zT1prhk09I>x^ z+Xv+K!Q$~RrQz1w0&Ji2!2|MRK)-**I}(hXD@*RB?i)sK}Ij*vLkJt3^j4C2ur zvwvfs2Y1sA;1X$d4&9!L`z{OhoEF7`UBbf4KE~LZWXAHz^I8ROBsDDD>!5c>*C&l? zdZkbqY2`^Z2?S2ILM)p=fhssGG>8f^dTg>Ao|%g*TamkvCH~d%vLEXom${K@^TCJA z1=m$uPG{kS5zGc{W?4e`bC=;19PmDo_y8M86A4IrvM_K;PR+RzM6t4f8SYOSmS)ud znp@@>bZ$A+ovz4b<$jMA#uP<29nG+PsbtH3fZrm`4SXW!A6fb_{r7K&+*m8=SKGq{ zvZWJq0WZp4;2$(!2gZq;7_*BV_3eoBPkVgn_8!w@8-GzxRCjh*!_YG;AG$kh1_%J$ zuQYE+flS>fMgMT2he%X{f|HR}b9 zdVZLnf6-aNZeczEs`)c|hq9%BWb$CBguE7RW5$)k(4B!(qX?l z-NZH!Rt8kjyKJ`n{_lbFI|(TA2>>$;oD_5?3D1DV}GJ6|{Xe$~* zo(+ocBJrKcs!@$8QE*luwDgbrH#>hXc?YyqazTpR+g}5euGqce+V%XI6W2e{xKi>? z+4*NokX}>PSxnRL@#CB5?GDEjq@H;WOB4d-kCkshXj<0XG8B?C<68^P6NfBfEkd3?kI*IwfBsFj=ij$Y@ZIUpZUY=QzDRVL;ldDEJ`Gx`LXe81099 zzqb66d{`v}+)v*xKbaz@NC^2vYME{B}XpT4#7w!y+5alX`0%e0XV)oU)SkRS= zz8-n^Q5r_dd3w}BoF?4Ur)B4H%Ecl>f-iuL5;1&^De$* z$P?3wv7N6pm*BB-5qm9xy7M6oaQSVQ5nTR$5>K<3)_G;X)3f7J1xzs#n6P7Xj`$+G zj$_E`LZyigK5#ZEAdW}IomrWfWYSc=w4B6kMk8QR^rxRef(Tqf-B|iD}XXR6b@v zLY`574q)8)9NqGjrq+(?>vbA6et=nP_M2A1N}qM!_k5L~FHTThis|M}Y5%jKpUqb? zof3SFdfRDKt?b=qZ$F_BVb`vi&l5QO53|FhzKGDj-az@kYH}bk*nN{%eKSW#p(_-~ z<>o{+D~%eP!gMgALU0KmKM8%y8CMKoT^axKEqWXpQ0fb~N}m}eSaW6LM%uF5t}kVg zK%&;EvRci;u%m(t^n-R4-2BlW{rn2uxSP`_%7JvlR1~D1b-#aYl!eK7Juwou_cNC} z^OGkHYli}3#^l~(-=>C}maAJvv6*JAfd@DX`aN5IlBCN~t0ZZr(cpX-fyfJD*q+R* zWs9;}8*LZ%7w+Ya>ZOA4Mq;@!{pxG_S??7(NEbi+jTX{lQ6;Y$!V?8pJ%BZFbN%C5 zEGHx9lU<|@+@JTGjeR}!*1^WbST3ni13Hfx#bq&6sRBlr%0PBDFs|{VO|qZ-1pa(4 zbIG=4i$R^VKyFDt{FSWHe!1*`O-nC&BwC||Im!BRN82<>e zME);4r5}Q;19_j!xGv!A#&9|YBXbF0hjQuC^jP5q{6leFpa%Buj$t5>jT1~)-*@4B zp7q*N;&AZmFfvRhhF1JExwk)Dt#4Lq`VG{ENc=f~_ebVpHS$p*Jh|7M2B1TJmlG8# z7!WHIttw#ZGGuM6JVP^G9yb&@_M(>W_BmIX076RS05?7z7DJne@1ovn8W=WOTN(Y1 zrNQ^_ry)DD3#Ze;Pz{@E5|JHkGjTgY;%toCNpeqz7aozkTD4atM!rmTHLNff8k24R z50%b!i1ZQ{SLf)4t|hC+Ov9T;#oM=cgq~YIW^;sMkt&U-HF#b3+~f7KcKs}OoKz3J zzbdSd86qz!sG4jlUi3$&>0Q~Mik@DPNTYdpX}v04MZqceZa~51(S%T2IPvPs7kDtt z(Ixq z)vx`zoI^8A5b9SG()IQ5FSGH!VbV|f_-~bMJ4WaK$x~79_dH{jc`!l&;5-X0~}kme>}0jyrp%1_l7eF&=f(|4^QNryZUY=TA0J%}o1FQ}tDEEfyQ2u}#kq^|lssMYiYUD*HH^?g~ecaxdZGxKT zLGsT{Z@fG}X9sF1+SGe_%tZe?@fXV8DX1SI0doH@PWt*a2XSEV76lX6c&XuF?^UHZap8>6lfy-7=sn|YKamwq_+A+EP z7>C~DOe1j#$2O3m1GjW=x=9N~D<^MP*2%GVI`%Ni!(EyT{w ze&WPUkXjFsbwcj}%xjD+TQd(Mmqy;l;q0o*ktoP7T(t zGQWWf9^~T#*(Hus1Mitp&P1Wx98CMIJ**sTL% z8ILuLC_e8yLPaGys3D(bm#V|aMTdf*3o8%;A|T-~e4>g9gK%_UumOs|5+yCZ)=?P$ z0PWTI_aOd<@dqq zOGWd2M??hSKI=wDMofp|fR751U9X#xKYqNLbG9^`*Q$@)Wv&zg#2KscXa^y{FI%)_k zLgh5g8XCE_819I$@@Gf-$H!%t%Yof`l;=f#+yeu*CIOTcBi1Vk5A6iux$h6(y!6Ed zoK-#9kQ5i&;`c@$UM08^L<)L5eQF8<{Mt}{)h&tC0_bzV06dxodL0^?X{Q8FZqo>66pREWJ!iq<4BgeHVV`!tC?|P6bfML>|K;T^cuQ;F z<*YI-A|U|ivRM*^2?_Z+YS;FhJbCid^JA-tS~Fj+kjtML>(cOi{=5i1ak5=AUHcL| z7M1WJY4+5QCWlE(H|SEFVybvb5AQle|bxgs2@q7t~P^3ENvRmMK0kk|~B6 zazg{{^+YuM=~Mt_HLyw4XM0{v~>UyQc>-K0)A8nV56Av=x-auW-jdn^6G zgkgGi*5ccnL3p*j?o+pjX9ch9@_Bh145^}NXk=YUDf8N((FPBxayu+O0~+_>!Gn%m`s2s7D}5Qqy4=5n1m`io)d$}n!VKb&p_=8g^`@}kiL}lf zi*W3L-!7a(DPVsMne68R2o+PBhovbiJhTxD$s^E3U^4Mc;9P?L5r1W2d~}bCxRBY`P=!t0lhhJA^_j2B{1;VxpyxSL_aF@N4ys5bqnu+?Es5L zo^N{xBs}=y)Uu7~ofz+Fh6htn7k#v%lsw_0o(sfm$kT(R%C3h6c-9tRcBAHEJe1la z%y(yL?v65uhZx&MkZOa3VgHXk6V?(o^>^uTpI!n4v0NSKf{>{~(U}NuRHB+CSWDhN zFi^~!VBxZOWYNs5(m&jhuxl~DYluwtLKwR13HU&`Ej#ja8wg`->Rwm%(g-=C!CwPB zPTI+b$e*U0q}2FS7&#RI%R z_p^mn`UVDdCnUx_7C?f?fMI(JDxfc4z5qF_-sDAixE3(B!5nqG@iQLCnS;)>!fREEz%zwv-(?*s+{kDgOYv=CW&@M6qN!a84r`BtWjc1i#YC%87L*0xa7fhS+ z;I{Sp2*InD@&zvC{#v`DmYDGThYudWK#P8iSdIvjlFYcTNd%8? zC&k0&yF}grek_0+j{tie`MrxIBL@+!3gntfXnG-9!Btw~e-Iu*tcU=wVeL`bB74LH zMKl8YL)ZQXdx8OPYV$Ac=T8dIU!<0QeQLjS^M5b=*9kv=Y7IARX+NZvP?1CX3DT#I z-Tx_vg#QO{`i|Sa9G~&9^stjkQ2T+i4uE7*_BF^R!UN{)_o95o-NJvM_r9477G8Ao z9}mhNM?5`9&iznrpd1l15s4PcygW!>x#{qbv)eW`B53MdpT6Zc(Csnl__6pGWn=}*-ZVxEu8}xOamRGUf`|Go&c<<3Q#KHWj zTc2v0wN(RLcS>!`|WX~cd+JMP)_w@-mK!2>>h`FZEDH-1S)*PD(ow&w{J-I@@_ zPRB6+1nygs#h{2yMBosq6@1G{fzf5+(GV~s+x5z zMNJgC{k>V3&X~%ymH8ZS4p6u&Q2<)kXh*ReU=$;+0fq>Et;%mpL=Cy?&q1?drIe1A zhHIeZh%4`3!1b!@Ap+f9dE2)&fLWggsOKS121N!vIuxLfu8+8$J~86Gt$nls-Ql&M zZXXeRTKa*mE?vxaa$(2fsc{P6v&Or_nZ|nHOJB#`EmUV}?zBMMvY9KY!0G9vw?_Ie2U!v{mli{%)=UUw;O8SKws%&2dN zg!^=7;!?k`yyRf%(DDvv{@@V8l^Y8j%Epb!8TM6|EByh$J5yF17Mi6j#ANSnC}XiG z-+w(pj!&b|;Czi;*J2dX^}4Ymu`M9~`GRm*j_Owxw$e$eOIGaA(4n%muEgdrK2m%c zCxEd?yI^3!S>T=Pt0EDKlXN;sqC)m_hyAsXC!X-l?|;A5Bx4 zPfOLHo19H+d}D+!n5XG{&WZ`?n2D-QQW*R&2HyfmAsjp13 zb#&)69kEhT@u8PA%xo<-)nd{|PY0(D9uAUx5`#?(ixJvSa@KAAl>TFLXl5=|v|k+E z4|4QG<&>ef*sID{-V3dI*kkJVRE7X39k-p}9Pd1bU-5iOrmuC6>d4})&LUZjyrtHh zg!+hV@y>cxUx6%e0?9gWx|E?)<}oDP-;vbh6D3;w&+_KCsAYy)ze*st8`<*PvBb4< zmBR$ONgY;sQ1*>;Ul1#p$$T**ogXp8BKKGHQA9gu+A^(AePCv8;uJVwM6oA#;>Yii ztV}&!!MB<`&y@|Y1!2=L6VdJ&V8N2qnuVuL`L_3eV2g2{K0Ez{M4Npbq**sM(DE36 zQ}1bP{cud-ctCi*;do_yJRSnp0aftq>IB1;A?Hs|?RmMldSGRzID2>Mamq&adM5~q zd_m;C%1_5~wy!#aEE>9gd$j5?()QMjtbIC>t}K^uc?&cejjvt>{?8FF8g8*lyt|hv zoF?{6(;aGjly@U{NXH;q^7IE&%JZ;k_lRZ6Wss&%{>ATNz!2I4s?X}XCb56Xt_hk@LLeHM@?X! z(eVVn^ec@0-q;y38y#4ONvKc2hB^7BFi_ZWW+_*#>=YQga5FaFh-FHzYpt$=0Jm= zkUEIwnf~**h?N5P`N;+i>%Xg~e{+ZbQXs7g#Np|*?MG_3wdVo}Ex#ynBqaL||74oM zk0GFViTr5r@k{`w*{}XKX%J42fmm4J)|c1dza1ABSLM}lXN|V4&{#=9Ntq$eC>6{l-r_4cc^~q}FKNI5 zO-?>d{Oc9KQTl6Mo#EHyFiNYht8+*zo<~R00Fo>YEjePw{zyagp@t(U~yE@MF77RVVb2BZM^$$62Q zK9TNglC$`f=Z@YEKm|hE1Dy-^5l(9^0JV8}gKlI7 z!zZcd+dgZLUBzX;jskFbO+-W*{Jf22!i8A4zl`{U7o)rbN@*xNj{TQq$d$?a06C&! zB>c#Qm(sx<7ntb;s|H26*^4W{HznnF04y9hf)IZ0a5ljQFfRFrll>U5LOm+vsFE1> zEM6o3?VIC|lpnrzqm@bAbbDQE?|!2IoxxXHwTvToc^w5>@<_tPjO65GKo#(KJm5v! zwr^+EDhgqmoSXy#x6tyGB2tcpf#1Pb6RFIsEP#ms(P@jgvco|)6hIh1IL@ko0fWg! z>cCGI+v`RFSeaj3R9pd&91LK3tgE1#Y;afNJC=iiAs#N3D-iB2iSDr@alW5iXzqB7 zT_qmOH@p|HArJE0fjZ{`9xc|VxVf|8NJ=h%zX&i40DXYxeO`zN23n`$o^0@3XA(S` z6n^gJW$^D^nbpoAgXEVvJkCRcr2I1C(bIl`73N-%G+QYqTsZuJ9f;ls_mzDEIRP`x zJ5OO!gydZ&X&b=7La#Q%I|*M426upEoCm)M(hQ2?X&OZ*SlSs3B!Y&;t;kfpk zm3w)bIU}i{{-6Ff-kkAp``J)5?!&g6p))wuJ&QR{iovrTdJhJE4vN~4L7fhk2!G(I z8Q~nS$>_k!eWFVwuTcB_12FVW7XowA?(Xgw=Rj&s1G&2*^!IdE7hb|M$-&2ePRTjb zhAOhzH!{ zg@S^D*1Q>@-q=(<&$~{onIA@IIlww|rs1Age9;}oW4}w$FH)QqQk&)wumXz&up#^M6=Y(}Ub*eQj~ILGa@!$C zy!k6&KJrZFVA@;E-k^AnSXi$nP>pwJ&x`^`iT*cQxt97639!7p3@PS(E=0#1ru(o7 zgNMXGs2W5NA;#Ots8Va#QicBooVH}R48A5q#1{6;uPlnhb55N)Wmp|}BJ>0JfspWi z?2~d#y!_-xEpct}nP<+`T)mAxPHUDd$dt5D)z#8U3zA2CJ=}Y=w9bILv%}IvxfUAd z`u+QNm|Y)IIs+S^oSOzVB;tCL14{=h1`mMALfH{3W1jlTSbnia>H7DIqb zA4eWAE&CY9}$=^AbZoKgUlTdof$ayc)}fm8Lu z{JbAC(GT4_Uk0xBjE$N_jx8EXCOF7~_w5)wA1XQTzr1VV-o1OU{K#~l0lYQHFf8Je z^{bbhixE@Mm?5L#s?a!^xHvt027~9S1*uDx7DYcS1jY3-S%UO<=m9lqgI@$3NDHh7 zUoPFhl?%FvOSw0O5Rxs{6dD@lp^WdYU(u%yqvbk%+5ieF>xZ;?F!rEwHQY1B;ppgC zu;f+B3HCdOISrm7ckCO-g#HhAEWCuj;@{EB!O6)OeBQiG1woNX^+ghu!nB@#Fa``Y z5tY^f{ZTOa5CJnNaEk)PG=&|sNUOfVUiRdN?b^rB z&+izYJ+zygT=d=!lK#Itw5?i!Fcj9iz}}UN_-H6qq78g_%`#U_~6(8|&`*+;rY&VSiulld_~TAwm-6HwhZ@K+H>4n=2cXkeeZ z_ViX`vMP*f*iiR%i~J!#S?6-Bsuzc%fc|{x(xt}}|APfbt^7=eKvA2F`Y*$XpYPxg zCzv%yk0Dl~iZfvAXJo^aXh~ZCu=iN4X)jXaR#lNCw>SSPW)Xb{2qphlfAwz)1EMGR ztK9OBdiVdYx5yvQeS;H<-anQL3 zR}+uoaDFquaC&>eCDMk|s%oO3hKg-eq3Ny~#j^EJRy4C`BzoYdO-Rt7h{Nl;nnG(s zqeFR?%Bc&=@{C$LYFV?ASXUg~lqRQzSKcBSzmkQPK$q(Nw5K*qQjxBX8Q8`w>QlWC zl)!WAOV-o?7?EgC6WEWmhysf++)lF$jZnv3g#NQ)I6NhwGXw1ym*vo>N)ebL??`!_mB+Tx?*2+!rvIRpeVmbul6Bw3L)W`a`YOv)Dl;=Wr|z zc!oJ~Ect*tYs!kWlS@VehWK*Lq9n4g<4Q#pc%szL0iMh#?N3>T#ga>}6gukXV2Qsl zYj5(!o&+=OH4C)TEo}vc82>tsx+uwE46T?T39(IeVkr4QfaGMQcjKjH6%Q*qr>XY< zwjh~yboBds3{XqY3LYIc?oaJaZRIS`q2tbPXcMh< ztGvgNU@1d3(Z``vFFgY@h~166uZXO2hDCX6{DEogxu3!K<8a--T7T6+a+vz@uZq z-2Xx4et#99aBbU>CAOq~GA}>8JhP)Yq5|`Jt@}@HPp1L15w#KkFTuL;5{ufKTYT07lL~HZcisfB zjuR%6mcSlZ0h@KQGk>MC!~UMQe9y{}o0r62UVXXq!Ew@)k3-@QUlifJ_~1chg7E%> zabdIu)|V_PC}p?G%9HIR-C;ogaO&NmhpF6@Jkl|EuS-cg1R+OfCqu$GO?0Iplqd8nBMb3LikXLF#1hx6>R zad!z*{~2JzyR4Mb@H$%&IDt6DRoQL3OU=A-wvgW@Zv^Ll_i+E| zc;hmrgKUMz7uy~?IQE><`A{b2xsBuUNAo9C!TjUXl+2y%O0iOdW#Ll$TN!a$BbugF zZJzFSRf=_zcu?*jrwPY(Ie*6 zcUNy*+uWYm*N1De2s|-ZBdci9L0F8j`*`SMyQg78ZhsiB!AOZ!c_&Z)VjA5M#s3djvEXF&qG^`+#bg; z0!1T4r{RN$54`|$(qqmYY_uILvQHN9Q30&QOAijvdq8TGQ&;p>+1+-03X{9c7M)ek z1XQ(fsX6UR`j(v!GV%Ha0oz%{s0Hg$2iIoa?zTtQttRn0R4IecbPlgEKyu^6|!d z2Q(9vc5ynk&dj^H&nnz75)>D(AYL_jov`6m@1un+dg^onY^)cz?y4yT*whN=YUt^g zqFGp395!gO6=KEbx2NrAbuk0Ok+7-8Rt$A{IIBzR6dw3}T*Vytx^3V^?2*}LYJ2b^*HSjwssFgKc0r} z=gfACqZ;98j#i!+yYc+!-62#26}wjjA-yrVU96|dhuqDYGDA(!X!+SO4R~hFQ>z2n zXUpV?ZCx3=dmYeTF@p0wG&$|IDVzdhUF$Co2k-8p#mjHtb$0cI5*j^mzROjLTK1*O z)K`8QuK2~tB8;#m{u-##5yy3c|-YE8s=)3BIf#3v$PK8u$5D3SlhU zQk^k%oGZ{RS8mVKpu|k$H1ggsPQ|%fbP`{N3Fg1jYL*F%3yj}$#E@p!p|g%zV%{ff zMW444?r@@DNE>83m6yNlK+ENZTu-RGvRsz`JZm6tP1Wabn)?50d+V?$ z*RE|GJ5WavK|u!<5orPG0Zb4OkQ5j~TBLhuMPdsgNF$|EA|>6RbhmU3NP`SL^tT3e ztIyu=^S!_CIDYewhs?}<-*a8-T6wN>;Znniy?I8*q34wXsoMNRH$rhc!Y;4e935{t zMSK)NwIbgg-&#S&^qK=xwWq?mJBG^L8`FuW!xMxc2^~c@nec}Uh`745SX>%bJ47U9?;=S|!*L)if(aHji=*zRgY6r7x z0=+|X&GKECvSDOkE@nEw;NI7r%Ce#4Y#@#MdM^^e!=m2WF~I0o z%QH~!Mf>5k(h!lg)9Q0}W$KYGWjeW%{iNhf#|H3vM4_latFh!eE#9NgC>Q)I4HlAo zQ1%f)A}9aH=g}L&p1Aq+O5@T=L}c~9J~0O4!X{#q9Eri-yZm@*X^-JPpR7xnXI$?& z2Po=~7hU~aO6@OFW4>8ds>>#okV5r{;YkJ!s0%HU#5$#0E3Su-$hY^T|L+C^hdZe4 zdvl(^iAQ(wySmxAbO}I9p7g^V_YwVde&=B@5Cb%Y!m1Jxohb8mr()GOee+7ai#tRB z;RIVvbo|B!e5UE;LsS8?H&b&=*o_mJYim!lcHc#}^@v+CK05l{m^-^m9yq;loZ>SE zj~e(U`Nt}eEm_H&BUUP{N#w9l3m(L_?y5k!>_-atJ^yL#CTC)K$uiu2u0q_N7d8iv zqUFLLP^jzCpJ4f}D@FAi zebC%R^o|ILJTE;6Up$|*b5SB9DIx^oINkq;n_8~Y?Ng~aL;7>C?-1_h-2OwpF?fq7 ztcbTy-5a&u$*T!A$rI^$?mS_V`ggwohnpbMMBd!YMJw=zva(n zxhv&Bb*6lbvXaUXuMPwQFJE*J{kfea2Kpe;EeDpYTA8c>cnl*=WFd(|VvC2YC1Elk zkm=gk;(_D?Y6|u+_G{E`82D~_GWCN(24S)v%pDyAC@RTiPM^-OurT?0mF~A4`;7E6Yz`+snDI}@BRBQ`sDXLI_1_1xa2rwAd1~BNV-ed#f zj6Bj$_Yg!OdkNCenau$YsOL)9CE$s8d=ueRdX(#|c^xa{A7$(a(=eeX90w&9sNDcn z{Sb@`HR0~q?nqQz0Jz=NmJFy)K^EHRxhr6RIU!96yx)M4^l6a@6vtka2E zZATjefPVr&$$`T_D&fzlXg1Lj1MLtwc*E2IqvtdQFhLjawp;`6w_!Jr<=f#)g&hO? znR-ge5XH7jkLg~VxMB}L^7(9F2?oeK+sz|@{I;t&qpNU>=)5Kzt=orDkSdGjAn1bj z32gD^au2=ShcLTuxf&n7Ac0LgiG%}M83LT7A=3_H6UzQN2NP%UCajG^W2c@&X96RZ zFm3Xpek1sWgxj*jku%8OJ8LH)@zON#K5P{{eZRd8cQzfpeBz_Om*9UouM!AB0NUEv z^jUT+0YMTlfCx=P?t4mkZy66{wee}xiZI0WL_Ty|m^Q$EKA;W6L1}9{av~A~Zc`Uh zV16A3A#XFJU{&AUeh&FwKtzh%1kO1iLsy_~e+WcClUbs-!oqh`+#o3Tzm?Iy>IGi@ z4H!ji=+b#wz&>ZBV4w>?&@N~yHC;1k{~%^5_z1EC%@t0gA-c!%X*o+qQkY;+$2K`Kw%XMW@jK&Lt3F)CGa!Z10Z2?K;{64?kyzd9oCmKD@4n;=YxtBZnaST zdH#M6-7`Gqj zf;M5h^pA=-DTHLYeIq`JvgiF2?B4Y0H{%Kl*TNG@#viebNkA*z|5|9%0dr%+3bLnS z0rZwNbaDOw`G?9N4CaNt5gm~EjwG~h^cilGH)S4%62S^2Wg4kuOiFh#fRY2Hzy+1d z(p<#51So6)byduU@2v}-?&MUeAbtQ}35Q{#M%vtA>kG3`YkcxbHH{zZauOth9r_}r+*k> zuN}K@()6Ep-#~~>yT<<|a8EHRwyfsZF`%;ya#u$~y@p|UEA*nzS7DC+h+cnKDeBV* z$V2*EBzO%5LIe`-rskUechHy zq^yfoP7t4BA~37MaELbS;pqu@ z##2@6I3MXBIwMo;LFLW+1Yh!(^1Du6*OjML?Ta?b1!jQP8l$OmXAb?ilhwqe!okDf z-u}}e8h19#0@QW~23-UkwxFpiD|CPO_0PLw5`M_o_ic18$Djqi4uA`K_dpx7$~j`9 z?j3)$P93%(rD$yu_EX!Nh^R{Ww|BwyXgW=J;N4HG2!1KNt_jVwd`TsGa}F-6g2cWN z<9T-Rd*JbgIID}-{lVTd_RXzmZ4&P?8UUtl; zx8#hV)DM2IlJ_s?<%zrSmE&j3Y5%XE2{EU=^B>pwm%}oMiG}j$+l?w-Yiaf2+*G%J ztn=<&2=Dt_TA_ULALou!5T52dB2(6@;9)rQS|0X#mWE-gMGv#I*Pi(%?6kdZ2^fmHhN6Xd zDTi-)Q*L>dl4h}{t)FhJ)Nf;a*?T{{nM7J^jf_mL%0DU3(pw3NBn2Y8&~3-Z#FAOO z?VrzA>V}z4p0id4uk~DQAb*y4D4F|EsF%sqBXW1DmGWKY+_dmliFN^@j91M>Cvvk#fIzlxof(SPFiG3 zJ%tP-X6-Uo4ykuP3+V)%{WPexiq;C(Zz=qM)e`BmZ@)0pt^fyzPLt_$WDN|^F$jy!| zIe6e#Ku4s4o4>~wm+*XSE#WnX9*d)mU8- z#1B8Kggk{o+js^@N#>*GL>Tuh6XzB136dw`k#lLUu1`lQ&{gL?NGT4wBBeZU+!Fm6 zByS=RxSbeM3JSp04^r(`HZ%G%X^*}zEKH`F#yb%`$%Kxe=83dypK!Bu+H$?no-J2? znw(Dh_Pr?d8su_)ZWb*qn>XmwBo3a@4WnPZd!Z4PzU9A-vRm%*idbJcPhEI>bH;dv z#ynnjZm9Cexn-Zdyi-OpCDJqndF%`elVU;Qd~;bU% zrIF@!&63+wth&2MIP({jJj4_zFR3?rjMjzUkG-c?J>xI)xX-F5^ALYQ66*qEZm7GU z$yH%qhmtADu9Bm4w!QQrd`7l89pRv0URDmb=LRzNDwN(PD777ZzT=(<#{8kzR2|V0 z%Jndt@}fXZo44TRmg5Ai*p^J1)^i%MxR;oMpkS`KeiF=;qFlxF3dr|Tj7iw(8$e!b zb8$hJq(4Ki6twi|S#=Nn?)AP8IiBv&Nb}hs8wHs*$-@tePOkT@BzWyfNDQpAH&(7` zif`3M2=?B3S-h?872F80-&BqE=Gaj{%GMNwCI9%aZkMB)3s;$Y%D~qt5td^Fc#z8&8Bb-w} zg!v8$n%VGTrLlx#EZ|rgR>JyT_u1}9s_B$s?)&J8j^emiqp$V5ZRc<{fxY#m-VR2C zQo`r7?QfMWE3QF_;CcQcMta@}y%@O%BmDOw{+4KI+UJej3NxobQ!Oq*#@6e7rLe%o z%gSfN@ix?2a1u1K%U*e`{;V`~W!SuQaZ0sIWisE%#fz{sJRW?r&N*6_rmbJ|_)FQ* zhTzp2Kgp#)dS%mc8WL?6HEWdvtRZvCV~UxNW4QV^f_NQJ9flsC`9}Peq(6cTD@#}; zyupYKAGNy0+0*6pX_oVgk8BraMPUYeGO%W5@(};V+EMmPsjJUdAYEwOe=c?3T<=AZ z2B91a7Z-Fft9n&ZS5k+xT8Y8&>ZTKEN$dVsebc$g_3P*eA*N}`gpaNX{~WrLDb*&?>CQo+*uegyTMp^Ayq_U>@}BQ z?U56L^1z?TQ~tr#^RgI5UjBscF;!FnI)Y>gE6k$exVjH=%PDdRYh@ybkWxlW_W4%i zTt@avk(J*ZAInB2tE3!1@W{oJh8gN9YK|(~TL)MIS=5$01~}ihqG?=%Yzx=APa2&f zHC~-(@D61$%vu;|L~urRXBiUAP1(7Mo>-R{vwYi|2tlZ)=npv*C;I7dZ4qlSC7p;! z*UMt>aj7>d46GE(SxO8eR45h}4SUAycI1Qi^j8HXSj5@7TwFhr5J zrf|yJFl;S_30pW<(_3F`UXvg$yJbCUW*m-clMitnD9}#syu*IOYB@ZXR*-bSe(1Se zxu>eRcn{yVoc@Ed(b@5^L+gm~3HckD?p%UG%)9^#jX1}C-chU1(2OCV=Zm4@nFn0` z83Rk@R5N-76NUwgLoVW=w{4lcgG>l#!6j7f`tgLw!-z-|*?d>D_F@jZ@;`stzbS0| zz5E`deEGBfbi*R^-U7D5&-Pn7^{=c}68B$GOe?FAo28gQXQATE$BHQiLdfk<`pfzi z2fSJG#-}C1nb`&0S&|#^gTPXelxLYwAEAFR-$GB*7QZ~h0u3Vhs{x}fHXeI=KbpqA zdic47%afFDXv4v*)z=Vgk5-Y+%z-&&PX#Di$V+ZjQCo*OIkpa!dn@J{ygo4$xK+H3 z7I=i)RCCNMySogvp=wJns?(ARuu3WNNxs;J+w7Kgtd(aCbCl72NoEXky(5!Zi7yhw z_5e-e^)=aJ(PvVM^1Rym?hck8%IC;mQbMwvu%1waexkaymEKmS2)?UI*+n0T_zT`u z7Sn#5-HH$j+|EXs2!ZE8j9Y?NapS-G-2_*|f z<+b>@2>bbJjxs7G{(`xRl&_lnTdXGQ~?r{NXhmyk|_&30( zQHv7ds4l+!e5kSbYT3c;FMT^FCyxmXSc~aV%67gj{NYpd{-@Fl^%l;i-?iaY&(_IS zsja0MV&-SS);=hZNm8Q81v0_@!dZG*6R7_T_d}uc)^}HyC}R&Hex>khDjky?8tX`k zG(uVQ(VO0$;;OqE`Ix!e>AbFH1LIibV7S?+&EP|5%39zw2-DkomoLttAAxIoFECo0 zQmlCSd7+?B9n)sxxM6l|7Iv7f}VOJ5Kh`Cp-DZoy9~vf-MiKY7p<42qf`~ zYuO1?Xn(}vY~K>J9Z}OULI&>9y~{TE=EmjOzIEpE#)eZl1Xr@l{4#f`)aW5Z3i*Hc zc3gZUS66WVFw)zu0%w0KoLGFWHLktjVqddu*z9y{@Z7(LSy0AsJ^x=7(x*~tQs<2U zvduA~eyMy5OU9ir^0$Pz1;N2T_z#o!&$Px)Ov9>izD9Ow(lUkpxGPPuk;@-}3IrIC z#ex`n_l+Mx6(Qn=m)Fjne+1LeN1*w;gZx`e_K*C;6XvVvs67rzgsRA|fC%ohvW;u` zJ?GN2Pe))3uIH~z*(GFPP-!=EcETIEyN`xBIzc16%E{b#G`h?oae>hj( z|MPQXm%lvSOcispt80aCPgImdIPY|KW-V{adCTvr0)m(8cWX)!RC9MXaAYpda#qWN zN|||kDXEVAT)EGsQM-d)Bp9zGmsGg#AtWOR>xaX=|D^qb!N8vTXBfL5;eA+nGzUI( z{U2C~@!jbhyiFZH>SL#J5{C~{Mm{EFbvOK-e)g58{fIDjA%AKxJ$t=gki`nzEXCHLpNq?*C`1H!q)rFCtft=!b-t}pr#!WjPcGQ>d%@JCl_gEV(j^zF09{FCd zg7iB!u9M{VpyZb<94afFU9~E27AB{>hTjqmc-iB0zLLTc*AxqI5%AHE_vGGJ-7;>R zcRM=8FED??W_5|Hb|`nYehXY>oi#ureAF1>V|Y-w-m~SUGx$J_CE%J}F`C1=f2zmY z-k@HMEs|qBbA+KkHI_?z33tex%wfCqwKsV|s`ivJ-3Ncst`sAUX6Hb|{^TMYn-B3w;xGPydbrG0k^bin1ZGE}cRE0@T*{%dSTIeaJSj zd71G^Q8%1fqVpiw{MoL{jK18uxiwX^NDinQ?Sz%26T{Ef#0YhwYYr8)Lc2|;rHQJ$ zy1b2SZ0U-X?61-)5K;>8qB!}NJGr|Krrc?3A@5s#ZZZ-erel@b05l$Dco9n8Cz=M={pRNIbGcWJuQxzq|^ZVbF|t% z^M5(a5Q3L22wpB6Sw=qQK`ko%gD5>zt>o*Mu&w9guM zqlAz2kmr;4wB+01Aq>B3yYQ?lG`lV!h);ufD3@%dI?k37t8t#j9?Jhiw1A`FHED97 zG}q~3R+@4pU_)3P|KhW95G z7ho{is6u~1Ni6o+K7w08NCR#0Z}6{J0Mbx8QegY)B`Z@v$z6iT3}dHj%k|y;Ujz65 zWU(%{WNHpe@q7*kO1IU3XX_vMsK!VxHtSkNQH34E5`ZIiwgp$>O6<9k^%(oE+U$`2 z8XP{_YY8*mD!p)49FY0zkWyj_mB$j1#hfTx!o02RPhDYlgYuF3XPBwEm zf}lA?l$0J2`)_Lcxg=s66b5)|v%RY+kUxuh%W0@|?a_U%tvGeR;w+ihoQC+4oVTN5 zt)-N+dk83|%8zG^u@o$QjLB~a_@}@eLO78=E`KH@f5gDQ$$o6L)LWGe4wU~1BM14g z3v}Ktp##R`l2g|bU~5lB>65YXtv8_f3xW*#JV+ZiQ9v&g(U&=O3i7b49qbNYCi>PA zAbRPyUFR9bw~iQ-ueFw<*PEFnSw) zVkPP5yRRVGPy?l`@IFWoRM57R=TijcIIN37AEJ@K`MyOs6QMA-*#z`J&C}ql@*~mj-gQwhBD1f#7jZ+ecn92sNr;?~3#ab~(9VxcGn&(Zy znP|N+2eUY?FeKX%FqW8`o(!vZBWT0!=Q?iknq6J%+RD;UV7IQdfm9`wE=#UpJID4T zE!(6koNB>*jz%*Y@!`vCb<9sZRoNmg z%h95?Rc!T(#*KqyzaS~UyJV5be$TS`q=BoYYt*>M&nZc_r;k`qLi#hQXVkEhyLIgb zk!u@|WZ1P2P_S>nxkzcaL4Z&+)^n=;x@po-h*xE9{=}4VpvY6NmG}HLVp*m^7wNtR z_IIhRBfc8cg^X-`aF&74UBQtn_55DqU%;8)Tpy8xNP%#IMlE#{TwLbccASszhXdyH zSeA-K>dHO%-hVxkB4zv=V^acoV-ZFVRBcw1vQ;$&a+w;hkjCP0pGp4qd@l?kkuk;a zC+F|JaMNiNO4R&!HHE?WkHYyU{^iSEsRykb_z(QhZwu%bjoSF@#HJLzf4D<2`|(XW zl)VqZS)Mrc?{14oP3bL<|12^5n=AeA4%V;I#_y?}UtZ*&RRR?x`rYqklV46CArSgr z>iFgF-X{bhe}@9#%p!hRTp}XdC*Ri$B7$fCsH*;24TdX^R-K&#|Ftyvx60YKk4f!* z)BK+$$)8X50N#NQ{DB<$2%Hg2qf>L`$TyYvFNa;tAYNaHJ52J z$h$wosOt44%E7t|Uk+y#Avv_FK34nD_Jn@A@sWQ@ZC{K0;iKnx4S+9hS$@w!SLoR~ zRpmP(HNlBaYOxq4YZIrJjL}s?AQMLnneAhAS6mZ!caiSvnV%@`6Q_cId27}m?TUn@ zlUY3IPGE)GTBia|MNP(K72C;HNv?kDfoIYZcFjz{47xoMG++`D`q_64+RPgJkCR20 zNB2c9g^gX5Nh#vB+1l`)F+AX-0b@~meNQE-IxLA7>LfFE3|F=eSBoeyHui)WJj|(o ztMD!MZkF@%1&s@vTzAq=1eqZabqeqli&I>WDqj{hoMcy!h8C>@-IOII&`8$0s>ZH&QLh3z8GCw;oiD#_Qhivy zyS}#)NqN_smO+nIkIPO*=``OmPgfPMNeStRYrL*|>VAZ;RXSJ9J|pug`b>8! zw%gv#YzCcI;VK_}&nLJcsEnvC9=~!3wb7*;*#|S8^s68fEB*fdTQ$eka*ETt*D#nb z?*PVKGFlO}Xtvwu%;FSzISqrt1c!N-&6wn4DBAAd?;3S)4oCl>Lex2tLI5S#D7t44 z%ATmCln+k-ZCjpQRY!2Rt(cBF?Xhq{EcTT(7Aw`};x5S{VuuG(Q)mUx1Y`=J{Q>9G z16VD+%XTY$);*y00ki-u+>q1hJ$Ux&!%xuhvs}mCNWcYg^;!6ZbQ0(F?w-R*V6l5% zsY(#B?Lied{dh18=Bo+@L&|~0%7~jGw*V2szl9$L{1YoIEZ7AWK0ZEL+RD4^(6$5S z>L@gIkJg0%f`d-A01so>X*Pg-Fd3j!03rhd+DmZ?>Gda7jGkgJaX8%5yDYRsA-jJGk zMmTlr#f{9`VE&hnuUcRWuqkM^wgD7XV=${Gv_=a#!_tX5_ZSx!5@ti$tu!<=7=itR zB0XZv7LVk&RWM(8$((&1RRBKB_2{6JPwI#evud{W%2xfWCy_`SawPJOI0i54_o-CP zteOVO%9$Krp~03;KCu&^a$oTTL=C&nJ@;ehUh*$@LV4VOnmtuHr8?MP2A%3feJ zHteG3mpn_p`s12!`}3BZ8p<9YJ&VVGRF~u{4L3s{P8^Z-=Q$4B-)Ge?wDMeF!{l>! zW{;s%*5|9b4J|7Jk+j*g<%$xymVsn7?(PFco9HOhFr@-KyY5@SGFMz!!+zWq2-;L9Z(4zTZNAVf&IVBKpf3=q7;3-0Fi1$#Y= z1;f_&%mWY!1}>#B)nol_@CnIzS&Hcki5FyI?G@hNztAPbeKJmIbph8ve>!i-gTXj= z>7)7bX8kC6_2DTz53;N`9WkqJ=&`uGt95&6>7YdziK=YBi3O(-o!&SyL3kMj^_xA zWMLSQ)_&OK1cPB^2|9FE*geSwhiHFW%#!rOC7eLOm_@t(D6e(DTOz-JemiX?m6{?d zi+%Fxfi%xke74h_55lCf(i5ev4!k5RJOYxKIz>f*IM+mG^K?RA) z!pU>oTGbu)2Y7Bg;NXCT7#f~g6w{(N&cP~RofmM_LMUpXm5f#ji%E<6ja7y^t(Af8 zaR3VnKK%3-dn3>>>ZOybg~8?5I<#Tx+PGNtuVgh#ussupcrD8pNB z%fnJQ7;{uJk6=oCmv9~gITy9;w;|tJN}2I0lYm-}ZG~C!wM#sarf!LC^${427hg*A zljzWZjLifQDI3!F`r@dWw>$tSB2Jmty>@Ykz7inkabw6}Z?=9p zNkH%Yk~8Pb^+H^pw%5?pXF9BB1D%ROshgLV_6MhJtZ&_mOnOUXf0C(mYTwb`Qo8|V zI@=5C2>LV+9wCVj2kh&by+?x^+jdcvmc~VtA-7DvMU4VeH%qKaT`tpOXgVY*(rrYd za{$mMc$aWO5J=P`Z!u&!)BVfOjwB|bw{<7Ixcb@2Gm9MD37F$F+2Q!!ZtULwnI=i+)jTf{fE*h*QQ0T!X)5wzx{4rIGgzZ5K*&oZ>ra)u#_(4fmw ze-cC%+U6D;_-4bes=qE<9ygUNxtB<(Xn9L6NomG|AsK|HgUbG+HOPLbB_>q(HR?eMpJs$eeT+$11IfkcQ7ploNLiVd#Lt+2S$W(fpQVbZw-AVUv-^~G`W znD#R#Ky&AT}}m_2vl6Sa8rn3vq(H;ZlnmYu}F}o}Ei)KK4NwvE9IzuI(#o zP>03##m0?e-PdbKXnRPz!mEsgviQKyL5BcC!w1#FiDHpUolK?Cfd@mu#vAb&qrGd5 zQgrH-bo>+ToYv9Vn%+#B>$ii47-c3Kq+cAK4c96A9=_qU-(E zY^2CDg%oRxNTt^GLQ~}i)Lbq z&-AEiGd+tZwZSXAYg`5bUwl^2H{WMq!|7Gl6c$d9qO-Ri93Ds?D{VMp2nT(v>wen1 z5M$pepg2E6x@>YVChDKVfBNa)v_4(6s+D!rRFctu&t5xeZRH2owF|yoh=i{ z*Trx}US~=AxcMB;q!Yc#Bl2eD zFC;qI4(-uACg%51TEiV+d*FS`2w@}|9%y9uGI~)Vw%5P4-*{?ZEd#PtVNbu`o-t$< zIrzjo*L(HeIUFm>ezLil6$w6Z9K%5#DTA!7bJ@5ELc( zf|}wx+a-yqzV(&OgfQk1W$Qk1!VzSv*Vp$J)`i?7{xXu>*s>nu?MjzJty+q#tqP}Jy9d#WF#!`@ zmyPH>Md9qj6=&fb1@0Xs;FbqWg&WNq`PKH{>&sixV&Ma|&e~WwnEFHELJKN1KoIg; zV61B=v8P(i`wK>Lr&g&3-jP=yX0+Q^UX!SLSc4fF-PEPUT*Se}%nr}CP-}iy4o<~I zPr26EdJwa;rA8JoYR~rTRvndnXV4fVAEqtZtmq+iLM&Fsz|)Fx)snAKRl?PMML~z! zv?SIfzxYyJP13j2+h11FY)lve#650k=!3$|4NzwNesF?ITP`K~8*q;(wR<;bJ~E9D zjhP$9w(91GLIyV`XY4 zTldu3Ci(34T+=Owdy2*O8gh@2MRqI5G(;d9C19|+)94*G=0u;{j)iwg53UBL)CZdp zw#+~5A}vMbREHBQ26r+@r9D|=z20k^QzVwzRITATlO#|uf=+X(@VGNN-jd=lu z(6O%CcpMH{JAE%~jGtFs-pJCM=0j0X{j+zn@^D(14*b{;O=c#)t4%t3B=R*MLHyr@SyYsw(5u9W$DysLHe53KIl_? zn+=BNTl);>FlMTKTmHRC@0SN^EBN6k@oYpN@I?Ie9P zz(n2G^$j@QX;z&jnsm#!EQ;zHbW-=BP%bA!apMBnHYuqa=&h_W4MDBw`tbGmIq73x zV@!>4{lu}PhNoNW4_((8tSs%R$o*34S?_mLdF31b;mrv+B{JVGlPt~G`qjS&KPs@$ z*;ZSgaUZKNkC)~hHxZ^2oZmwgBYq<y#eV>}yC5 zl9|Dt(zd!RKM>WIW|m;bD793t7&T7K65~O4;MeLWiDJew_bUYvXNwwke&l0d(60-g z6T%a0^WA*K*P!vTD_CF3r1pu&yIWJnH2AXyy$u+9;!VRou;(l;_4ekYD>4V{k02s# z=ZCRC=?fNjvrmAi0Aex(f1BMz%gA!8udpexg~a};XS_Yx#iD_Yv5ed*HY7PG|^t3ra5`}9=nWEfHA@e`g}y6iZdyuFP2Cl z?#@(}+S{29&qpHckU+H7y*x8eW9oh^T)&N5Z?sNQBR4Ye)qYc*G>8}VxB4k-!b&~K zQyfMD=qgTW&-gH0-q@!ih!lv|c|}n@shqc%3SA7o0v;pno0%Q4?I{CI_%L7exjy>w zx`99pcqi#;9>*xIu?6Nk6%INF`o`IW&b1JOsLuU#6aX_c-J4;HX%^?|W47aNEv@X0 zi+e8~dJJY!yz&xbTsb3{wsz)+zDpd*K;~=zc9senFTe2B{%AU!u62&R;@J>m0%>^6 z=~MlD<$-KeQ&tg$VUR6hPDjgJDiCH!6IEDIcsFU+h057+2~tOnn->S7tNU~;N&-br zpI*?>(WaMWZ zwpq_^x1;&_7OQA^dHJri5v|~wfzQt(KdLs%7V+D^rDo;KZ-1Wg@H0K#TiF{Lz)G;1 zJEr=uwhTY^?p~F`H>cU|teGq65Op2~0{DFHm3-c;d(jSwt9Hg$%#TS%7LDf&zYN-d z?E2-}Iqjg#Q~}BXe=2aU(@*m=d%h;k!Oa%CVeY-Ucn4avwDL5vdGqA1s>8uEWAG*O zNr1L9Ha@#IM-U7BgE26gPTe_(^TovI-t+ADF?g-9*!ohK-%SXUT^W)6hPEDoOg;A@ zwn;-U$iybzyFQ%0m|7sOQ!f3GDeh0lZp@*bX>y@aGuG=tn6@7pl%MO0gz2{zekwb@ zf*pq13l08%$qaHPP_E=pUm^XwuaJEv{G&F>{t6VDV$Ke7=w8?2m1Bgx^G6mTerdg@ zC+7jUz~Qp9<;S%0L!}YM(IVWUFkgs&P?MROHfE1N;Crf*qp<(-B^s5z`7G+SmyW!M zdHAUk(n+*>h=CNf;+dY4#e0mu1Tqbv@Pkpyetwr4(QlN}LVP|?j=n^Rj=s=J!_0LX z_AGO29vx{cjk}xhz<6^!%5{{i%X7Z@eg$1cqsk@N#saD&m3$S^rHMGoFsaq|QA%mL z;jEgeOZk`NZ6;h%KOC}8^`&tVMy=+M^E4l2MCX`fE|4zOBq|*4jc&NA2zu)a->htH zQhKkDE7hu6cGCO=mS0pwhl{45_)3~+);BllW?>_<{9oc6ocQ(TmxPY1{p*(W15h#P zrJ$wD%?y@vL=_0r3B}($WOqLtY_!xBAFJgnU{Fr=B(0MWJY%gGir?e75FaTTBsT%q~BW`e>ul2X_32c2pbM1mWw;73k+r(BHFZthDaQ)Dj$ct^0=fl z?)6s`YPOV?^j{xWq_DJEd(X3y6F*abVeXR4>ySjiIbcxsyTQ)K{Fgjon0sS&^%+5d zg0U6^#bTxR#n@aNP9mOvxn-bUd49aXV%i zw`c!2s}kWsgG{IhFV=E;3 zn0{#!5IfUHO)r^`*7>!YN4z`&Dbw@0BTkU9U3S}Zmz8Z&i-9a0GUwHGFcU0Cl^r^> zW`VoANxY^wI*Cxzm=?FWl$)Kq*!Ss;$>Lb-6>p9U;aqpv+_W#jQ1AiOacXs%8(qcT zfls~pIZgTtb_xc12o^A$AAlSKqO%UYK21>go=?^CEOIxm5wHXB!rgF$rS7#Rv_nJ7 z6AQrUTP0ajd8;OsA9}HOUb{KkxLu=&D>xmQS zW$@)Vpq1I~5i<#M>hk^X?-1dHK_;NG0nwc6lw#;%J_wcJB&A7u)FPh_n5EuSDl{^NM!sKi&e9qD~ERGu3HPPU#WAuZtXP0 p!2}CRo4-Zz?#chPEDUb%@}=H0o}!>YXz?c!xg&8q`Q}6C{{y6oZA<_F literal 0 HcmV?d00001 From 33206fef388adf2470cc858a99b5fa9b6d22bad5 Mon Sep 17 00:00:00 2001 From: Ansh Date: Fri, 23 Aug 2024 04:21:26 +0530 Subject: [PATCH 02/10] fix: changes as per pr comments --- docs/additional-examples/evm-swap.md | 79 +++++++++++++--------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/docs/additional-examples/evm-swap.md b/docs/additional-examples/evm-swap.md index 000b6528..c3da35b7 100644 --- a/docs/additional-examples/evm-swap.md +++ b/docs/additional-examples/evm-swap.md @@ -1,18 +1,18 @@ -# Cross Chain EVM Swap +# Performing a Cross-Chain Swap with PKPs and Lit Actions In this section, we will demonstrate how you can use PKPs and Lit Actions to perform a cross-chain swap. There are three parts to this flow: -- Understanding Lit PKPs as escrow -- Lit Action +- Using Lit PKPs as escrow +- Using Lit Actions to define swap parameters - Implementing Mint/Grant/Burn with SDK -## 1) Understanding Lit PKPs as escrow +## 1) Using Lit PKPs as escrow accounts A Private key is meant for signing transactions which are executed on the blockchain, a network verifies if the transaction is a legitimate one and then executes it. With Lit Network we can generate a special type of private keys which can be programmed to sign transactions only when certain conditions are met. With this, we can create several escrow mechanisms, and we will look into how we can execute a cross-chain swap. -### A swap example would be: -Suppose Alice holds 100 token A on Base and Bob holds 100 token B on Chronicles and they both agree to a swap of, +### Example: +Suppose Alice holds 100 token A on Base and Bob holds 100 token B on Chronicle and they both agree to a swap of, - 4 token A from Alice to Bob on Base -- 8 token B from Bob to Alice on Chronicles +- 8 token B from Bob to Alice on Chronicle We have an [example code](https://github.com/anshss/lit-evm-swap) for the below solution. @@ -21,34 +21,32 @@ When you generate a PKP on the LIT Network, a PKP NFT is first minted to your wa Lit Actions are programmable code written in Javascript which can run on the LIT Network. We can program a Lit Action so that if certain permissions are met for a pkp, it must sign specific transactions that can be sent to the blockchain. We need to grant a Lit Action as a permitted action to the PKP to allow the Lit Action to generate signatures with it. -We can create an escrow pkp in the following way (Mint/ Grant/ Burn) +We can create a PKP "escrow" using the Mint/Grant/Burn approach in the following way: - Mint a PKP on Lit -- Grant a permitted Lit Action -- Burn the PKP NFT so that no more auth methods can be modified +- Grant a permitted Lit Action to sign with it +- Burn the PKP so that it can't be used to sign anything else other than what is outlined in the Lit Action logic -This approach will allow us to create scenarios where a private key can generate signs based on conditions and unlock robust opportunities like cross-chain swapping, messaging or bridging. +### Architecture for Mint/Grant/Burn + +![accessControl](/img/mgb-flow.png) + +## 2) Lit Action For a Swap Lit Action, both parties need to deposit their funds to the PKP and based on the conditions the PKP should be completing the swap: - Alice (or Bob) creates a Mint/Grant/Burn PKP - Alice deposits 4 token A on Base Sepolia to the PKP -- Bob deposits 8 token B on Chronicles to the PKP +- Bob deposits 8 token B on Chronicle to the PKP - Alice (or Bob) executes the Lit Action. -Lit Action execution, checks conditions and executes the swap from the PKP - -If the swap conditions aren't met then the Lit Action execution shall revert the funds to their depositors. - -### Architecture for Mint/Grant/Burn - -![accessControl](/img/mgb-flow.png) +When the Lit Action is executed, each Lit node verifies that the conditions are met before provisioning their key share and executing the swap using the PKP -## 2) Lit Action +If the swap conditions aren't met, the Lit Action execution will revert and the tokens will be returned to the initial depositors (Alice and Bob) Now we'll dive into the depths of the Lit Action and explore how we can conduct conditional signing. -Below are the parameters that decide the swapping conditions. +Below are the parameters for the cross-chain swap. In the example below, we'll be transferring 4 tokens A on Sepolia for 8 tokens B on Chronicle Yellowstone. These tokens are minted by a custom contract. ```js const chainAParams = { @@ -71,26 +69,26 @@ const chainBParams = { chainId: 175188, }; /* -deposit1: wallet A deposits on chain B, if action executes, funds are transferred to wallet B -deposit2: wallet B deposits on chain A, if action executes, funds are transferred to wallet A +deposit1: wallet X deposits on chain B, if action executes, funds are transferred to wallet Y +deposit2: wallet Y deposits on chain A, if action executes, funds are transferred to wallet X */ ``` :::info -On the chains section, we can specify any of the chains [supported](../resources/supported-chains) by LIT. +You can use any of the chains [supported](../resources/supported-chains) by Lit when setting your own swap parameters ::: -You can find a generator which takes the above params to generate a Lit Action for swap: [swapActionGenerator.js](https://github.com/anshss/lit-evm-swap/blob/main/lit/swapActionGenerator.js) +The following code can be used to generate the swap Lit Action based on the parameters above: [swapActionGenerator.js](https://github.com/anshss/lit-evm-swap/blob/main/lit/swapActionGenerator.js) Remember, once a Mint/Grant/Burn PKP is created, anyone can execute the Lit Action on the Lit Network. This execution needs to define the parameters needed by the Lit Action to run. While generating a sign or checking conditions on the action, we need information around the pkp for which we are doing it. Due to this, we need to construct our Lit Action in a way that works with any PKP. Our Lit Action primarily focuses on three factors: -- Access Conditions for checking funds on both chains +- Access control conditions for checking funds on both chains - Transaction objects for transferring funds between swap parties -- Clawback Transaction objects for revert transferring funds to their owners -- Lit Action conditions which decide which transaction object to sign and return +- Clawback transaction objects to revert transferred funds back to their owners if the swap parameters aren't met +- Lit action conditions which decide which transaction object to sign and return -We'll use [Lit's Access Control](../sdk/access-control/evm/basic-examples#must-posess-at-least-one-erc20-token) here to verify if the conditions are being met for the swap. There need to be 2 conditions for a swap to execute, +We'll use an [Access Control Condition (ACC)](../sdk/access-control/evm/basic-examples#must-posess-at-least-one-erc20-token) here to verify if the swap conditions are met before it is executed. These conditions are: - Have token A funds reached on Chain A? - Have token B funds reached on Chain B? @@ -111,8 +109,7 @@ const chainACondition = { }; // parameter field would be later replaced by the pkpAddress in the action ``` - -There need to be two transaction objects, each of which transfers funds between the swap parties. Each of them will be calling function `transfer(address, uint256)` on the token's smart contract. This information is captured in the "data" field of the object. We can get that in the following way, +We need to create two transaction objects, each of which will transfer the funds between the two swap parties that have been set. Each party will call the `transfer(address, uint256)` function on the token's smart contract. This information is captured in the "data" field of the object which we can fetch in the following way: ```js function generateCallData(counterParty, amount) { @@ -142,7 +139,7 @@ let chainATransaction = { Clawback transaction objects are transactions that transfer funds back to the depositors if the swap conditions aren't met. These will have a different value for the `data` field and can be generated again using the `generateCallData()` function, with the `counterParty` value set to the depositor. -Let's start with writing a Lit Action, +Now that we've covered all of the relevant background information, let's write our full Lit Action: ```js const go = async () => { @@ -187,7 +184,7 @@ We then, extend our transaction object with the gas configs which will be receiv Now our action checks if the conditions are passed on both chains, it takes `authSig` as a parameter here and then logs the result of both condition checks. We'll look into auth sigs while we learn to execute lit actions. -For generating signatures inside our Lit Action, we'll use `Lit.Actions.signEcdsa`. This method allows us to use a pkp (which lets an action generate a sign) for generating signatures. Our Lit Action will now decide based on checked conditions and generate appropriately signed transactions which we can send to the blockchain later. +To generate signatures inside of our Lit Action, we'll use the `Lit.Actions.signEcdsa` method. Our Lit Action will verify that the conditions we've specified are met before generating the appropriate signed transactions which we'll be able to send to chain later ```js if (chainAConditionsPass && chainBConditionsPass) { @@ -256,20 +253,19 @@ As everything on the blockchain works on hexadecimal hashes, we need to hash our go(); ``` -A must `Lit.Actions.setResponse` needs to be set before we are closing the execution of a Lit Action. This is the response which is shown after the execution of a Lit Action. +We need to remember to set `Lit.Actions.setResponse` before we finish executing the Lit Action. This defines the response that will be shown when the Lit Action finishes executing. -Complete Lit Action can be found at [swapAction.js](https://github.com/anshss/lit-evm-swap/blob/main/lit/swapAction.js). +The complete swap Lit Action can be found [here](https://github.com/anshss/lit-evm-swap/blob/main/lit/swapAction.js). ## 3) Implementing Mint/Grant/Burn with SDK -### Installing Packages +### Installing and importing the relevant packages ```bash npm i @lit-protocol/lit-node-client @lit-protocol/contracts-sdk @simplewebauthn/browser @lit-protocol/types ethers ``` -### Imports Declarations ```js import { LitNodeClient } from "@lit-protocol/lit-node-client"; @@ -286,7 +282,7 @@ import { ethers } from "ethers"; import bs58 from "bs58"; ``` -### Create Wallet instances +### Creating our two wallet instances These wallets will represent the two parties involved in the swap. @@ -311,10 +307,10 @@ async function getWalletB() { provider ); return wallet; -}c +} ``` -### Create Lit Action and upload it to IPFS +### Creating our Lit Action and uploading it to IPFS Once we are done with our Lit Action, we need to upload it to IPFS so we get an immutable CID which will always point to our action. @@ -338,6 +334,7 @@ We'll create a single function to perform 3 calls at once - Burn the PKP NFT by transferring it to itself so auth methods become immutable Now, our PKP will only be used to execute the Lit Action we permitted. It will generate signatures only when the Lit Action is running and not in any other situations. We have already designed the Lit Action to create the correct signed transactions based on the conditions. + ```js export async function mintGrantBurnPKP(action_ipfs, mintedPKP) { console.log("minting started.."); @@ -388,7 +385,7 @@ export async function mintGrantBurnPKP(action_ipfs, mintedPKP) { } ``` -### Deposit Methods +### Depositing tokens for the swap To deposit swap tokens along with some native tokens for gas From 30185e8fdd79532766306cf2736f33c5726e9f50 Mon Sep 17 00:00:00 2001 From: Ansh Date: Sat, 24 Aug 2024 18:56:18 +0530 Subject: [PATCH 03/10] fix: more changes --- docs/additional-examples/evm-swap.md | 38 ++++++++++++++++++---------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/docs/additional-examples/evm-swap.md b/docs/additional-examples/evm-swap.md index c3da35b7..71374547 100644 --- a/docs/additional-examples/evm-swap.md +++ b/docs/additional-examples/evm-swap.md @@ -2,12 +2,12 @@ In this section, we will demonstrate how you can use PKPs and Lit Actions to perform a cross-chain swap. There are three parts to this flow: - Using Lit PKPs as escrow -- Using Lit Actions to define swap parameters +- Using Lit Actions to define swap conditions - Implementing Mint/Grant/Burn with SDK -## 1) Using Lit PKPs as escrow accounts +## 1) Using Lit PKPs as escrow -A Private key is meant for signing transactions which are executed on the blockchain, a network verifies if the transaction is a legitimate one and then executes it. With Lit Network we can generate a special type of private keys which can be programmed to sign transactions only when certain conditions are met. With this, we can create several escrow mechanisms, and we will look into how we can execute a cross-chain swap. +[PKPs](../user-wallets/pkps/overview) are decentralized key pairs generated by the Lit Network. Using Lit Actions, we can program them to sign transactions under specific conditions, enabling escrow mechanisms. We’ll explore how to execute a cross-chain swap with this setup. ### Example: Suppose Alice holds 100 token A on Base and Bob holds 100 token B on Chronicle and they both agree to a swap of, @@ -17,21 +17,17 @@ Suppose Alice holds 100 token A on Base and Bob holds 100 token B on Chronicle a We have an [example code](https://github.com/anshss/lit-evm-swap) for the below solution. ### How does this work? -When you generate a PKP on the LIT Network, a PKP NFT is first minted to your wallet, representing your ownership over the underlying private key residing on the LIT Network. This PKP NFT is responsible for managing auth methods over the private key. +1. Mint a PKP: Start by minting a PKP on the Lit Network. +2. Assign a Lit Action: Grant a specific Lit Action to the PKP using the Mint/Grant/Burn (M/G/B) approach, allowing it to generate signatures according to the programmed conditions. +3. Burn the PKP: Finally, burn the PKP to ensure it can only be used within the confines of the Lit Action logic. -Lit Actions are programmable code written in Javascript which can run on the LIT Network. We can program a Lit Action so that if certain permissions are met for a pkp, it must sign specific transactions that can be sent to the blockchain. We need to grant a Lit Action as a permitted action to the PKP to allow the Lit Action to generate signatures with it. - -We can create a PKP "escrow" using the Mint/Grant/Burn approach in the following way: - -- Mint a PKP on Lit -- Grant a permitted Lit Action to sign with it -- Burn the PKP so that it can't be used to sign anything else other than what is outlined in the Lit Action logic +Learn more about Lit Actions [here](../sdk/serverless-signing/overview). ### Architecture for Mint/Grant/Burn ![accessControl](/img/mgb-flow.png) -## 2) Lit Action +## 2) Lit Action to define swap conditions For a Swap Lit Action, both parties need to deposit their funds to the PKP and based on the conditions the PKP should be completing the swap: @@ -44,7 +40,7 @@ When the Lit Action is executed, each Lit node verifies that the conditions are If the swap conditions aren't met, the Lit Action execution will revert and the tokens will be returned to the initial depositors (Alice and Bob) -Now we'll dive into the depths of the Lit Action and explore how we can conduct conditional signing. +Now we'll write the Lit Action that will be used to set the specific swap conditions that will be followed. Below are the parameters for the cross-chain swap. In the example below, we'll be transferring 4 tokens A on Sepolia for 8 tokens B on Chronicle Yellowstone. These tokens are minted by a custom contract. @@ -327,6 +323,11 @@ export async function createLitAction() { ``` ### Create a Mint/Grant/Burn PKP + +:::info +Currently, direct calls to the smart contract’s m/g/b function are currently failing with the Lit Network. We’ll replicate the same functionality using the SDK. +::: + We'll create a single function to perform 3 calls at once - Mint a PKP with the user's wallet @@ -650,4 +651,13 @@ function formatSignature(signature) { } ``` -You can also explore other methods, such as checking permissions on the PKP, checking the fund status of each wallet, or the PKP itself [here](https://github.com/anshss/lit-evm-swap/blob/main/lit/utils.js). \ No newline at end of file +You can also explore other methods, such as checking permissions on the PKP, checking the fund status of each wallet, or the PKP itself [here](https://github.com/anshss/lit-evm-swap/blob/main/lit/utils.js). + +## Summary +- Created transactions and clawback transactions objects based on swap parameters. +- Wrote a Lit Action that returns signed transactions based on conditions. +- Minted a PKP and assigned it the Lit Action. +- Burned the PKP to restrict its signing ability to the Lit Action only. +- Deposited funds to the PKP on both chains. +- Executed the Lit Action on the Lit Network to receive signed transactions. +- Broadcast and executed the transactions on their respective chains. \ No newline at end of file From 8c9fdae3da0a82c24b54d0af2e3a08fcedfcf28e Mon Sep 17 00:00:00 2001 From: Ansh Date: Tue, 3 Sep 2024 04:02:41 +0530 Subject: [PATCH 04/10] fix: review changes --- docs/additional-examples/evm-swap.md | 85 +++++++++++++--------------- 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/docs/additional-examples/evm-swap.md b/docs/additional-examples/evm-swap.md index 71374547..eef20f25 100644 --- a/docs/additional-examples/evm-swap.md +++ b/docs/additional-examples/evm-swap.md @@ -3,22 +3,22 @@ In this section, we will demonstrate how you can use PKPs and Lit Actions to per - Using Lit PKPs as escrow - Using Lit Actions to define swap conditions -- Implementing Mint/Grant/Burn with SDK +- Implementing Mint/Grant/Burn with the Lit SDK ## 1) Using Lit PKPs as escrow -[PKPs](../user-wallets/pkps/overview) are decentralized key pairs generated by the Lit Network. Using Lit Actions, we can program them to sign transactions under specific conditions, enabling escrow mechanisms. We’ll explore how to execute a cross-chain swap with this setup. +[PKPs](../user-wallets/pkps/overview) are decentralized key pairs generated by the Lit Network. Using [Lit Actions](../sdk/serverless-signing/overview.md), we can program PKPs to sign transactions when our pre-defined conditions are met, enabling a sort of 'trustless' escrow. In the following example, we'll use this functionality to execute a cross-chain swap. ### Example: Suppose Alice holds 100 token A on Base and Bob holds 100 token B on Chronicle and they both agree to a swap of, - 4 token A from Alice to Bob on Base - 8 token B from Bob to Alice on Chronicle -We have an [example code](https://github.com/anshss/lit-evm-swap) for the below solution. +A complete code example can be found [here](https://github.com/LIT-Protocol/evm-swap-example). ### How does this work? 1. Mint a PKP: Start by minting a PKP on the Lit Network. -2. Assign a Lit Action: Grant a specific Lit Action to the PKP using the Mint/Grant/Burn (M/G/B) approach, allowing it to generate signatures according to the programmed conditions. +2. Assign a Lit Action: Grant a specific Lit Action the ability to use your PKP using the Mint/Grant/Burn (M/G/B) method which will allow it to generate signatures according to the conditions you set. 3. Burn the PKP: Finally, burn the PKP to ensure it can only be used within the confines of the Lit Action logic. Learn more about Lit Actions [here](../sdk/serverless-signing/overview). @@ -27,9 +27,9 @@ Learn more about Lit Actions [here](../sdk/serverless-signing/overview). ![accessControl](/img/mgb-flow.png) -## 2) Lit Action to define swap conditions +## 2) Creating a Lit Action to define your swap conditions -For a Swap Lit Action, both parties need to deposit their funds to the PKP and based on the conditions the PKP should be completing the swap: +For our swap Lit Action, both parties will need to deposit their funds to the PKP 'escrow'. The PKP will complete the swap when the conditions we set in the Lit Action have been met. - Alice (or Bob) creates a Mint/Grant/Burn PKP - Alice deposits 4 token A on Base Sepolia to the PKP @@ -77,12 +77,12 @@ The following code can be used to generate the swap Lit Action based on the para Remember, once a Mint/Grant/Burn PKP is created, anyone can execute the Lit Action on the Lit Network. This execution needs to define the parameters needed by the Lit Action to run. While generating a sign or checking conditions on the action, we need information around the pkp for which we are doing it. Due to this, we need to construct our Lit Action in a way that works with any PKP. -Our Lit Action primarily focuses on three factors: +Our Lit Action primarily focuses on 4 factors: -- Access control conditions for checking funds on both chains -- Transaction objects for transferring funds between swap parties +- Access control conditions (ACCs) to ensure that funds have been received on both chains +- Transaction objects for transferring funds between our two swap parties - Clawback transaction objects to revert transferred funds back to their owners if the swap parameters aren't met -- Lit action conditions which decide which transaction object to sign and return +- [Lit action conditions](../sdk/access-control/lit-action-conditions.md) to determine which transaction objects should be signed and returned We'll use an [Access Control Condition (ACC)](../sdk/access-control/evm/basic-examples#must-posess-at-least-one-erc20-token) here to verify if the swap conditions are met before it is executed. These conditions are: @@ -328,61 +328,55 @@ export async function createLitAction() { Currently, direct calls to the smart contract’s m/g/b function are currently failing with the Lit Network. We’ll replicate the same functionality using the SDK. ::: -We'll create a single function to perform 3 calls at once +We'll be using `mintNextAndAddAuthMethods` to perform 3 calls in a single transaction: - Mint a PKP with the user's wallet -- Add the Lit Action as a permitted auth Method -- Burn the PKP NFT by transferring it to itself so auth methods become immutable +- Add the Lit Action as a permitted auth method +- 'Burn' the PKP NFT by transferring it to itself so that no additional auth methods can be added. Effectively, this offers the same functionality as the M/G/B method -Now, our PKP will only be used to execute the Lit Action we permitted. It will generate signatures only when the Lit Action is running and not in any other situations. We have already designed the Lit Action to create the correct signed transactions based on the conditions. +Now our PKP can only be used to execute the Lit Action we permitted when we added it as an auth method. It will only generate signatures when the Lit Action is running and the conditions we set have been met. ```js export async function mintGrantBurnPKP(action_ipfs, mintedPKP) { console.log("minting started.."); const signerA = await getWalletA(); -// instantiating Contracts SDK const litContracts = new LitContracts({ signer: signerA, network: LitNetwork.DatilDev, debug: false, }); - await litContracts.connect(); - -// minting a new PKP - const mintPkp = await litContracts.pkpNftContractUtils.write.mint(); - const pkp = mintPkp.pkp; - console.log("PKP: ", pkp); - - console.log("adding permitted action.."); -// adding a permitted lit action - await litContracts.addPermittedAction({ - pkpTokenId: pkp.tokenId, - ipfsId: action_ipfs, - authMethodScopes: [AuthMethodScope.SignAnything], - }); + const bytesAction = await stringToBytes(action_ipfs); + const pkpMintCost = await litContracts.pkpNftContract.read.mintCost(); - console.log("transfer started.."); + await litContracts.connect(); -// burning the PKP NFT - const transferPkpOwnership = - await litContracts.pkpNftContract.write.transferFrom( - signerA.address, - pkp.ethAddress, - pkp.tokenId, + const tx = + await litContracts.pkpHelperContract.write.mintNextAndAddAuthMethods( + AuthMethodType.LitAction, + [AuthMethodType.LitAction], + [bytesAction], + ["0x"], + [[AuthMethodScope.SignAnything]], + false, + true, { - gasLimit: 125_000, + value: pkpMintCost, + maxFeePerGas: ethers.BigNumber.from("1800000000"), } ); - const receipt = await transferPkpOwnership.wait(); - + const receipt = await tx.wait(); console.log( - "Transferred PKP ownership to itself: ", + "pkp minted, added lit action as auth, and transferred to itself: ", receipt ); - return pkp; + + const pkpInfo = await getPkpInfoFromMintReceipt(receipt, litContracts); + console.log("pkp: ", pkpInfo); + + return pkpInfo; } ``` @@ -654,10 +648,11 @@ function formatSignature(signature) { You can also explore other methods, such as checking permissions on the PKP, checking the fund status of each wallet, or the PKP itself [here](https://github.com/anshss/lit-evm-swap/blob/main/lit/utils.js). ## Summary -- Created transactions and clawback transactions objects based on swap parameters. -- Wrote a Lit Action that returns signed transactions based on conditions. +In the following example you should have learned how to: +- Created transaction and clawback transaction objects based on specific swap parameters. +- Wrote a Lit Action that returns signed blockchain transactions based on the specific conditions you defined. - Minted a PKP and assigned it the Lit Action. - Burned the PKP to restrict its signing ability to the Lit Action only. -- Deposited funds to the PKP on both chains. -- Executed the Lit Action on the Lit Network to receive signed transactions. +- Deposited funds to the PKP on two blockchains where our swap will be conducted between. +- Executed the Lit Action on the Lit network to return our signed transaction objects. - Broadcast and executed the transactions on their respective chains. \ No newline at end of file From c5c91fc7d18ee5750473d2c8b84e84d704ec373a Mon Sep 17 00:00:00 2001 From: Ansh Saxena Date: Sat, 7 Sep 2024 02:17:07 +0530 Subject: [PATCH 05/10] Update docs/additional-examples/evm-swap.md Co-authored-by: Wyatt Barnes --- docs/additional-examples/evm-swap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/additional-examples/evm-swap.md b/docs/additional-examples/evm-swap.md index eef20f25..91e3ca8d 100644 --- a/docs/additional-examples/evm-swap.md +++ b/docs/additional-examples/evm-swap.md @@ -251,7 +251,7 @@ go(); We need to remember to set `Lit.Actions.setResponse` before we finish executing the Lit Action. This defines the response that will be shown when the Lit Action finishes executing. -The complete swap Lit Action can be found [here](https://github.com/anshss/lit-evm-swap/blob/main/lit/swapAction.js). +The complete swap Lit Action can be found [here](https://github.com/LIT-Protocol/evm-swap-example/blob/main/lit/litAction-example.js). ## 3) Implementing Mint/Grant/Burn with SDK From ee54aa36c5468f3c5df89bd7c4a4ca56c1faa0b3 Mon Sep 17 00:00:00 2001 From: Ansh Saxena Date: Sat, 7 Sep 2024 02:17:41 +0530 Subject: [PATCH 06/10] Update docs/additional-examples/evm-swap.md Co-authored-by: Wyatt Barnes --- docs/additional-examples/evm-swap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/additional-examples/evm-swap.md b/docs/additional-examples/evm-swap.md index 91e3ca8d..9ea4d811 100644 --- a/docs/additional-examples/evm-swap.md +++ b/docs/additional-examples/evm-swap.md @@ -645,7 +645,7 @@ function formatSignature(signature) { } ``` -You can also explore other methods, such as checking permissions on the PKP, checking the fund status of each wallet, or the PKP itself [here](https://github.com/anshss/lit-evm-swap/blob/main/lit/utils.js). +You can also explore other methods, such as checking permissions on the PKP, checking the fund status of each wallet, or the PKP itself [here](https://github.com/LIT-Protocol/evm-swap-example/blob/main/lit/utils.js). ## Summary In the following example you should have learned how to: From aac537150997e67d079a1c1e4e5b2479c615992c Mon Sep 17 00:00:00 2001 From: Ansh Saxena Date: Sat, 7 Sep 2024 02:18:19 +0530 Subject: [PATCH 07/10] Update docs/additional-examples/evm-swap.md Co-authored-by: Wyatt Barnes --- docs/additional-examples/evm-swap.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/additional-examples/evm-swap.md b/docs/additional-examples/evm-swap.md index 9ea4d811..da400c1d 100644 --- a/docs/additional-examples/evm-swap.md +++ b/docs/additional-examples/evm-swap.md @@ -258,8 +258,11 @@ The complete swap Lit Action can be found [here](https://github.com/LIT-Protocol ### Installing and importing the relevant packages ```bash -npm i @lit-protocol/lit-node-client @lit-protocol/contracts-sdk -@simplewebauthn/browser @lit-protocol/types ethers +npm i \ +@lit-protocol/lit-node-client \ +@lit-protocol/contracts-sdk \ +@simplewebauthn/browser \ +@lit-protocol/types ethers \ ``` From ab548ac9e67de9c60e3760f54d953ebfcdd21979 Mon Sep 17 00:00:00 2001 From: Ansh Saxena Date: Sat, 7 Sep 2024 02:20:37 +0530 Subject: [PATCH 08/10] Update docs/additional-examples/evm-swap.md Co-authored-by: Wyatt Barnes --- docs/additional-examples/evm-swap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/additional-examples/evm-swap.md b/docs/additional-examples/evm-swap.md index da400c1d..a8787d7f 100644 --- a/docs/additional-examples/evm-swap.md +++ b/docs/additional-examples/evm-swap.md @@ -269,7 +269,7 @@ npm i \ ```js import { LitNodeClient } from "@lit-protocol/lit-node-client"; import { LitContracts } from "@lit-protocol/contracts-sdk"; -import { LitNetwork, AuthMethodScope, LIT_CHAINS } from "@lit-protocol/constants"; +import { LitNetwork, AuthMethodScope, LIT_RPC, LIT_CHAINS } from "@lit-protocol/constants"; import { LitAbility } from "@lit-protocol/types"; import { LitActionResource, From cbde265ea524072f2f3e9f433e03d0ae5e4d9162 Mon Sep 17 00:00:00 2001 From: Ansh Saxena Date: Sat, 7 Sep 2024 02:20:49 +0530 Subject: [PATCH 09/10] Update docs/additional-examples/evm-swap.md Co-authored-by: Wyatt Barnes --- docs/additional-examples/evm-swap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/additional-examples/evm-swap.md b/docs/additional-examples/evm-swap.md index a8787d7f..5f86d52c 100644 --- a/docs/additional-examples/evm-swap.md +++ b/docs/additional-examples/evm-swap.md @@ -299,7 +299,7 @@ async function getWalletA() { async function getWalletB() { const provider = new ethers.providers.JsonRpcProvider( - `https://yellowstone-rpc.litprotocol.com/` + LIT_RPC.CHRONICLE_YELLOWSTONE ); const wallet = new ethers.Wallet( process.env.NEXT_PUBLIC_PRIVATE_KEY_2, From 9eb974dd5ae98c8da0aa53e3bb887171d06f0f2e Mon Sep 17 00:00:00 2001 From: Ansh Saxena Date: Sat, 7 Sep 2024 02:20:59 +0530 Subject: [PATCH 10/10] Update docs/additional-examples/evm-swap.md Co-authored-by: Wyatt Barnes --- docs/additional-examples/evm-swap.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/additional-examples/evm-swap.md b/docs/additional-examples/evm-swap.md index 5f86d52c..d3de2fb5 100644 --- a/docs/additional-examples/evm-swap.md +++ b/docs/additional-examples/evm-swap.md @@ -357,13 +357,13 @@ export async function mintGrantBurnPKP(action_ipfs, mintedPKP) { const tx = await litContracts.pkpHelperContract.write.mintNextAndAddAuthMethods( - AuthMethodType.LitAction, - [AuthMethodType.LitAction], - [bytesAction], - ["0x"], - [[AuthMethodScope.SignAnything]], - false, - true, + AuthMethodType.LitAction, // keyType + [AuthMethodType.LitAction], // permittedAuthMethodTypes + [bytesAction], // permittedAuthMethodIds + ["0x"], // permittedAuthMethodPubkeys + [[AuthMethodScope.SignAnything]], // permittedAuthMethodScopes + false, // addPkpEthAddressAsPermittedAddress + true, // sendPkpToItself { value: pkpMintCost, maxFeePerGas: ethers.BigNumber.from("1800000000"),