TAC proxy functions receive their parameters as ABI-encoded bytes. This guide shows the exact encoding patterns from the TAC engineering team for different data structure complexities.
All proxy functions must follow the signature function name(bytes calldata tacHeader, bytes calldata arguments)
.
The arguments
parameter contains your custom ABI-encoded data.
Basic Encoding Patterns
Simple Parameters
You typically define a struct that represents the arguments your proxy function expects:
struct MyProxyFunctionArguments {
address tokenFrom;
address tokenTo;
uint256 amount;
}
You then encode these fields in your frontend code using ethers.js:
import { ethers } from "ethers";
const abiCoder = ethers.AbiCoder.defaultAbiCoder();
const myProxyFunctionArguments = abiCoder.encode(
["address", "address", "uint256"],
[tokenFromAddress, tokenToAddress, tokenFromAmount]
);
Advanced Encoding Patterns
Complex Example with Nested Structures
For structs containing other structs:
struct AnyExtraInfo {
address feeCollector;
uint256 feeRate;
}
struct MyProxyFunctionArguments {
AnyExtraInfo extraInfo;
address tokenFrom;
address tokenTo;
uint256 amount;
}
Encoding:
const extraInfo = [feeCollectorAddress, feeRate];
const myProxyFunctionArguments = abiCoder.encode(
["tuple(address,uint256)", "address", "address", "uint256"],
[extraInfo, tokenFromAddress, tokenToAddress, tokenAmount]
);
Complex Example with Dynamic Arrays
For structs containing arrays:
struct MyProxyFunctionArguments {
address[] path;
uint256 amount;
}
Encoding:
const path = [tokenFromAddress, tokenToAddress];
const myProxyFunctionArguments = abiCoder.encode(
["tuple(address[],uint256)"],
[[path, tokenFromAmount]]
);
TAC SDK Integration
When using the tac-sdk to create messages for bridging, you must provide:
- target: the address of your Proxy contract
- method_name: the complete function signature, e.g.
"myProxyFunction(bytes,bytes)"
- arguments: the ABI-encoded arguments (second parameter in your proxy function)
- gasLimit (optional): the parameter that will be passed to the TAC side. The executor must allocate at least
gasLimit
gas for executing the transaction on the TAC side. If this parameter is not specified, it will be calculated using the simulateEVMMessage
method (preferred)
Example:
const myProxyFunctionName = "myProxyFunction(bytes,bytes)";
const userMessage = {
target: MyProxyContractAddress,
method_name: myProxyFunctionName,
arguments: myProxyFunctionArguments, // from the previous encoding step
gasLimit?: // optional
};
Decoding in Proxy Functions
Your proxy functions decode the arguments using abi.decode()
:
function executeSwap(bytes calldata tacHeader, bytes calldata arguments)
external
_onlyCrossChainLayer
{
TacHeaderV1 memory header = _decodeTacHeader(tacHeader);
// Decode the custom arguments
SwapParams memory params = abi.decode(arguments, (SwapParams));
// Use the decoded parameters
require(params.amountIn > 0, "Invalid amount");
require(params.deadline > block.timestamp, "Expired");
// Execute swap logic
performSwap(params);
}
What’s Next?
You now understand all the argument encoding patterns for TAC proxy development: