The permit function allows a spender to transfer tokens on behalf of the token holder with a signed permission. This tutorial breaks down the use of the permit function into digestible steps.
Import the SigningKey module for signing the permit digest.
const { SigningKey } = require("@ethersproject/signing-key");
Create instances of the smart contracts by using the ABI and address. Obtain the controller address through the instantiated EUR contract.
const { ethers } = require("ethers");
// EUR contract instantiation
const eurABI = [...] // EUR ABI goes here
const eurAddress = "<eur_contract_address>";
const eurContract = new ethers.Contract(eurAddress, eurABI, signer);
// Fetch the controller address from the EUR contract
const ctrlAddress = await eurContract.getController();
// Controller contract instantiation
const controllerABI = [...] // SmartController ABI goes here
const controller = new ethers.Contract(ctrlAddress, controllerABI, signer);
Define the nonce and deadline for the permit function.
const nonce = await controller.nonce(<yourAddress>);
const deadline = Math.floor(Date.now() / 1000) + 60 * 60; // 1 hour from now
Generate the digest that the permit function will use for transaction verification.
const digest = await controller.getPermitDigest(
<yourAddress>,
<spenderAddress>,
<value>,
nonce,
deadline
);
Use your private key to sign the digest. This signature proves that you have authorized the transaction.
const signingKey = new SigningKey(<yourPrivateKey>);
const signature = signingKey.signDigest(digest);
Complete the process by submitting the permit function with the required parameters and the signature.
await controller.permit(
<yourAddress>,
<spenderAddress>,
<value>,
<deadline>,
signature.v,
signature.r,
signature.s
);
const { ethers } = require("ethers");
const { SigningKey } = require("@ethersproject/signing-key");
// Replace the following with your contract's ABI and addresses
const eurABI = [...] // EUR ABI goes here
const eurAddress = "<eur_contract_address>"; // EUR contract address
const controllerABI = [...] // SmartController ABI goes here
async function permitFunction(yourAddress, spenderAddress, value, yourPrivateKey) {
// Provider and signer would be set up here (e.g., using ethers.js)
const provider = new ethers.providers.JsonRpcProvider("http://localhost:8545");
const signer = new ethers.Wallet(yourPrivateKey, provider);
// Instantiate the contracts
const eurContract = new ethers.Contract(eurAddress, eurABI, signer);
const ctrlAddress = await eurContract.getController();
const controller = new ethers.Contract(ctrlAddress, controllerABI, signer);
// Prepare the permit details
const nonce = await controller.nonce(yourAddress);
const deadline = Math.floor(Date.now() / 1000) + 60 * 60; // 1 hour from now
// Create the permit digest
const digest = await controller.getPermitDigest(
yourAddress,
spenderAddress,
value,
nonce,
deadline
);
// Sign the digest
const signingKey = new SigningKey(yourPrivateKey);
const signature = signingKey.signDigest(digest);
// Submit the permit transaction
const tx = await controller.permit(
yourAddress,
spenderAddress,
value,
deadline,
signature.v,
signature.r,
signature.s
);
return tx;
}
// Usage: call permitFunction with the required parameters
// permitFunction(<yourAddress>, <spenderAddress>, <value>, <yourPrivateKey>).then(...);