Wrap ETH and Transfer all WETH tokens

Introduction

We will make an FCT, where we will wrap ETH and transfer all WETH to other recipients. This FCT will consist of 3 Plugins - Wrap ETH, ERC20 Balance Of, and ERC20 Transfer.

If you have not worked with FCT before or have not seen any other examples, we highly encourage you to start with the Simple ERC20 Transfer example, which explains everything in more detail.

First, we need to import all the necessary tools

import { BatchMultiSigCall } from "@kirobo/fct-core"
import { ERC20, Utility } from "@kirobo/fct-plugins"

BatchMultiSigCall is the class for FCT building

Utility is a Protocol, which consists of various utility functions such as sendETH , wrapETH and unwrapETH.

Build all 3 plugins

First, we will create wrapETH plugin and add all parameters.

const wrapETH = new Utility.actions.WrapETH({
    chainId: 1,
})

wrapETH.input.set({
    value: "1" + "0".repeat(18) // We are going to wrap 1 Ether
})

Then we are going to create ERC20 Balance Of Plugin

const balanceOfWETH = new ERC20.getters.BalanceOf({
    chainId: 1,
})

balanceOfWETH.input.set({
    to: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    // Or take the address from wrapETH plugin like this
    // to: wrapETH.input.to.value
    methodParams: {
        owner: "0x...", 
        // Address which wrapped Ether tokens. In this case
        // that will be the vault address.
    }
})

And then the last plugin we are going to create is ERC20 Transfer

const transfer = new ERC20.actions.Transfer({
    chainId: 1,
})

transfer.input.set({
    to: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    // Or take the address from wrapETH plugin like this
    // to: wrapETH.input.to.value
    methodParams: {
        recipient: "0x...", // Address, which is going to receive the tokens
        amount: balanceOfWETH.output.balance.getOutputVariable("balanceOfWETH_id"),
        // "balanceOfWETH_id" is the nodeID we are going to use later on
    }
}

Build the FCT from plugins

First, we need to construct BatchMultiSigCall class.

const batchMultiSigCall = new BatchMultiSigCall({
     provider: new ethers.providers.JsonRpcProvider("..."),
     chainId: 1,
})

Once we have BatchMultiSigCall constructed, now we can add all of the plugins to BatchMultiSigCall class by calling createMultiple() function.

The order must be like it is in the example. If the order is different, FCT might not work correctly.

await batchMultiSigCall.create([
    {
        plugin: wrapETH,
        from: "0x...",
        nodeId: "wrapETH_id"
    },
    {
        plugin: balanceOfWETH,
        from: "0x...",
        nodeId: "balanceOfWETH_id" // This nodeId has to match the id, that was used in the ERC20 Transfer plugin amount
    },
    {
        plugin: transfer,
        from: "0x...", // Here we put the vault address, from whom the transfer will happen
        nodeId: "transfer_id"
    },
])

Now we have an FCT that is ready to be exported!

const FCT = await batchMultiSigCall.exportFCT()

Congratulations, you have built an FCT with 3 plugins!

Full code example

import { BatchMultiSigCall } from "@kirobo/fct-core"
import { ERC20, Utility } from "@kirobo/fct-plugins"

const wrapETH = new Utility.actions.WrapETH({
    chainId: 1,
})

wrapETH.input.set({
    value: "1" + "0".repeat(18) // We are going to wrap 1 Ether
})

const balanceOfWETH = new ERC20.getters.BalanceOf({
    chainId: 1,
})

balanceOfWETH.input.set({
    to: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    // Or take the address from wrapETH plugin like this
    // to: wrapETH.input.to.value
    methodParams: {
        owner: "0x...", 
        // Address which wrapped Ether tokens. In this case
        // that will be the vault address.
    }
})

const transfer = new ERC20.actions.Transfer({
    chainId: 1,
})

transfer.input.set({
    to: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    // Or take the address from wrapETH plugin like this
    // to: wrapETH.input.to.value
    methodParams: {
        recipient: "0x...", // Address, which is going to receive the tokens
        amount: balanceOfWETH.output.balance.getOutputVariable("balanceOfWETH_id"),
        // "balanceOfWETH_id" is the nodeID we are going to use later on
    }
})

const batchMultiSigCall = new BatchMultiSigCall({
     provider: new ethers.providers.JsonRpcProvider("..."),
     chainId: 1,
})

await batchMultiSigCall.create([
    {
        plugin: wrapETH,
        from: "0x...",
        nodeId: "wrapETH_id"
    },
    {
        plugin: balanceOfWETH,
        from: "0x...",
        nodeId: "balanceOfWETH_id" // This nodeId has to match the id, that was used in the ERC20 Transfer plugin amount
    },
    {
        plugin: transfer,
        from: "0x...", // Here we put the vault address, from whom the transfer will happen
        nodeId: "transfer_id"
    },
])

const FCT = await batchMultiSigCall.exportFCT()

// Use FCT.typedData to sign on to the FCT. If you are using @metamask/eth-sig-util
// to sign on EIP712 transaction, this is an example of how to sign on to FCT

import { signTypedData, SignTypedDataVersion } from "@metamask/eth-sig-util";

const signature = signTypedData({
    data: FCT.typedData,
    privateKey: Buffer.from(key, "hex"),
    version: SignTypedDataVersion.V4
})

Last updated