# Transact with a contract gaslessly

{% hint style="info" %}
An API key is required to use the infrastructure to power gasless transactions. Visit  <https://app.rallyprotocol.com/> to generate both Amoy and Mainnet Polygon API keys.&#x20;
{% endhint %}

## Contract requirements&#x20;

1. **Contract is compatible with the RallyMobile SDK**
   1. Contracts that are [ERC2771 compatible](https://docs.rallyprotocol.com/react-native-expo/guides/add-erc2771recipient#if-you-are-able-to-update-the-contract) are natively supported by the RallyMobile SDK. Those that are not ERC2771 compatible must be whitelisted by us, [view the guide here.](https://docs.rallyprotocol.com/react-native-expo/guides/add-erc2771recipient#if-you-are-able-to-update-the-contract)

## Transact with contracts with the relay method

To gaslessly execute a transaction with a contract, create a [GSN transaction object](https://github.com/rally-dfs/rly-network-mobile-sdk/blob/736e1de0859bec5230abba80e978f76f43fe2123/src/gsnClient/utils.ts#L16)  and use the `relay()` method to send the transaction to our relayer.

```dart
import { RlyAmoyNetwork } from 'rly-network-mobile-sdk';
import ethers from 'ethers';
....

//get web3 provider

const provider = new ethers.providers.JsonRpcProvider(providerUrl);

//get instance of your contract 

const myContract =  new ethers.Contract(contractAddress, contractAbi, signer);

//populate raw transaction object
const tx = await myContract.populateTransaction.myMethod.(
    param1,
    param2
  );

//get gas estimate for transaction
  const gas = await myContract.estimateGas.myMethod.(param1, param2);

//get current network fee data
  const { maxFeePerGas, maxPriorityFeePerGas } = await provider.getFeeData();

//create relay tx object

  const gsnTx = {
    from: account.address,
    data: tx.data,
    to: tx.to,
    gas: gas._hex,
    maxFeePerGas: maxFeePerGas._hex,
    maxPriorityFeePerGas: maxPriorityFeePerGas._hex,
  } as GsnTransactionDetails;

// relay transaction 

await RlyAmoyNetwork.relay(gsnTx);
```
