Skip to main content

Interact with other contracts

Disclaimer

This guide might contain outdated information and will be updated soon.

In this guide, we will learn how to use our Universal Profile to interact with any other smart contract (like if we were using a regular Externally Owned Account).

Interaction flow:

Guide - Interact with other contracts using a Universal Profile

Introduction​

We have seen in the previous example how to send LYX from our UP via the execute(...) function.

This function offers a fourth parameter: _data, that provides a lot of flexibility when interacting from our UP. The _data parameter is handy when the _to recipient is a smart contract.

If you want to call a specific smart contract that was deployed on the network by the Universal Profile, the parameters of the execute(...) function will be as follow:

  • _operation: 0 (for CALL).
  • _to: the address of the smart contract we want to interact with.
  • _value_: empty (0).
  • _data: the ABI-encoded function name and arguments, to be run at the _to contract address.

Suppose a smart contract targetContract was deployed on the network and we want our UP to call the function myCoolFunction on this contract. We will have to:

  1. ABI-encode the function call with the parameters we want to pass.
  2. Pass the encoded calldata as argument _data of the execute(...) function.

Setup​

To complete this guide, we will need:

  • an EOA with some LYX for gas fees and the required permissions for the interaction.
  • the UniversalProfile and KeyManager contracts ABIs from the @lukso/lsp-smart-contracts npm package.
  • the address of our Universal Profile.
  • the targetContract ABI.
  • the address of the Target Contract.
info

The chosen EOA needs to have CALL Permission together with Allowed Calls or SUPER_CALL Permission

Make sure you have the following dependencies installed before beginning this tutorial:

Install the dependencies
npm install web3 @lukso/lsp-smart-contracts

Step 1 - Create the contracts instances​

The first step is to create instances of our Universal Profile, Key Manager contracts and the Target Contract.

  • Create an Universal Profile contract instance from universalProfileAddress.
  • Create a Target Contract instance from the targetContractAddress.
caution

Save the Target Contract ABI in a separate JSON and import it in the main file.
You can quickly compile and get a contract's ABI in Remix IDE.

Imports & Constants
import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json';
import TargetContractABI from './TargetContractABI.json';
import Web3 from 'web3';

const web3 = new Web3('https://rpc.testnet.lukso.network');

const universalProfileAddress = '0x...';
const universalProfile = new web3.eth.Contract(
UniversalProfile.abi,
universalProfileAddress,
);

const targetContractAddress = '0x...';
const targetContract = new web3.eth.Contract(
TargetContractABI,
targetContractAddress,
);

Step 2 - Encode the calldatas​

We need to create a calldata that will be executed on the Target Contract.

Target calldata
// 1. encode the calldata to be run at the targetContract
// assuming targetContract is a Contract instance
const targetCalldata = targetContract.methods
.myCoolfunction('dummyParameter')
.encodeABI();

Step 3 - Execute the calldata​

Load the EOA​

Like in other guides, an important step is to load our EOA that is a controller for our Universal Profile.

Setup EOA
const PRIVATE_KEY = '0x...'; // your EOA private key (controller address)
const EOA = web3.eth.accounts.wallet.add(PRIVATE_KEY);

Send the execute calldata​

The final step is to pass the encoded calldata to the Universal Profile. Since we are calling from an EOA that is a controller on the UP, the Key Manager will authorize the transaction.

Send transaction
await universalProfile.methods
.execute(OPERATION_CALL, targetContract.address, 0, targetCalldata)
.send({
from: EOA.address,
gasLimit: 300_000,
});

Final Code​

Final code
import UniversalProfile from '@lukso/lsp-smart-contracts/artifacts/UniversalProfile.json';
import TargetContractABI from './TargetContractABI.json';
import Web3 from 'web3';

const web3 = new Web3('https://rpc.testnet.lukso.network');

const universalProfileAddress = '0x...';
const universalProfile = new web3.eth.Contract(
UniversalProfile.abi,
universalProfileAddress,
);

const targetContractAddress = '0x...';
const targetContract = new web3.eth.Contract(
TargetContractABI,
targetContractAddress,
);

// 1. encode the calldata to be run on the UP
const targetCalldata = targetContract.methods
.myCoolfunction('dummyParameter')
.encodeABI();

const OPERATION_CALL = 0;

const PRIVATE_KEY = '0x...'; // your EOA private key (controller address)
const EOA = web3.eth.accounts.wallet.add(PRIVATE_KEY);

// 2. execute the calldata through the UP
await universalProfile.methods
.execute(OPERATION_CALL, targetContract.address, 0, targetCalldata)
.send({
from: EOA.address,
gasLimit: 300_000,
});