Protocol
Guides
Batching transactions

Batching transactions

Primitive Portfolio uses a modified version of the famous multicall function, allowing users to batch transactions but also to spend funds before owning them. This feature is allowed thanks to a transient balance system, that tracks the balance of the user during the execution of all their transactions in the batch.

Here is the multicall function:

function multicall(bytes[] calldata data)
    external
    payable
    returns (bytes[] memory results);

Here is a complete example showing how to use that function:

MulticallExample.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
 
import "portfolio/interfaces/IPortfolio.sol";
 
contract MulticallExample {
    IPortfolio public portfolio;
    address public asset;
    address public quote;
 
    constructor(address portfolio_, address asset_, address quote_) {
        portfolio = IPortfolio(portfolio_);
        asset = asset_;
        quote = quote_;
    }
 
    function createPairAndPool() external {
        // In this example, we are going to create a new pair and a new pool in
        // one unique transaction.
 
        // Let's prepare the data for our multicall.
        bytes[] memory data = new bytes[](2);
 
        // First, let's create the pair.
        data[0] = abi.encodeCall(IPortfolioActions.createPair, (asset, quote));
 
        // Second, let's create the pool. Note that we are using the pairId 0,
        // this is a "magic value" referring to the last pair created.
        data[1] = abi.encodeCall(
            IPortfolioActions.createPool,
            (0, address(this), 10, 100, 10_000, 365, 1 ether, 1 ether)
        );
 
        // Finally, let's call the multicall function.
        portfolio.multicall(data);
    }
 
    function createPairAndPoolAndAllocate() external {
        // In this example, we are going to create a new pair, a new pool and
        // allocate liquidity in the same transaction.
 
        // Let's prepare the data for our multicall.
        bytes[] memory data = new bytes[](3);
 
        // First, let's create the pair.
        data[0] = abi.encodeCall(IPortfolioActions.createPair, (asset, quote));
 
        // Second, let's create the pool. Note that we are using the pairId 0,
        // this is a "magic value" referring to the last pair created.
        data[1] = abi.encodeCall(
            IPortfolioActions.createPool,
            (0, address(this), 10, 100, 10_000, 365, 1 ether, 1 ether)
        );
 
        // Third, let's allocate into the pool. Note that we are using poolId 0,
        // this is a "magic value" referring to the last pool created.
        data[2] = abi.encodeCall(
            IPortfolioActions.allocate,
            (false, 0, 1 ether, type(uint128).max, type(uint128).max)
        );
 
        // Finally, let's call the multicall function.
        portfolio.multicall(data);
    }
}

© 2023 Primitive™