I am trying to see if I can make Axelar send aUSDC from Optimism Goerli to Base Goerli. Attached below, I've written two contracts, OPSender.sol and BaseReceiver.sol, and deployed it on Optimism Goerli and Base Goerli, respectively. I tried calling the sendToMany function on OPSender to send the aUSDC from OP Goerli to Base Goerli, however I got the error
Transaction mined but execution failed
I am running everything on Remix IDE.
Here are the parameters I put into sendToMany
{
"string _destChain": "Base",
"string _destContractAddr": "0x291b1B6EB9DE79f0cb181bCF68Ae1ea70d9B8760",
"address[] _destinationAddrs": [
"0xD1872508B5A49eD6Ea5EefD93e643623c0F83a78"
],
"string _symbol": "aUSDC",
"uint256 _amount": "100"
}
val 10000000000000000 wei
Here is the tx
I put the tx into tenderly to try and debug and it gave me an arthimetic error (arthimetic overflow / underflow), however I'm not dealing with much math here.
Here are the contracts
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC20 } from '@axelar-network/axelar-cgp-solidity/contracts/interfaces/IERC20.sol';
import { IAxelarGateway } from '@axelar-network/axelar-cgp-solidity/contracts/interfaces/IAxelarExecutable.sol';
import { IAxelarGasService } from '@axelar-network/axelar-cgp-solidity/contracts/interfaces/IAxelarGasService.sol';
contract OPSender {
IAxelarGasService gasReceiver;
IAxelarGateway gateway;
constructor (
address _gateway,
address _gasReceiver
) {
gateway = IAxelarGateway(_gateway);
gasReceiver = IAxelarGasService(_gasReceiver);
}
function sendToMany(
string memory _destChain,
string memory _destContractAddr,
address[] calldata _destinationAddrs,
string memory _symbol,
uint256 _amount
) external payable {
require(msg.value > 0, "Gas payment required");
// get token address from symbol
address tokenAddress = gateway.tokenAddresses(_symbol);
// send funds to this contract
IERC20(tokenAddress).transferFrom(msg.sender, address(this), _amount);
// approve gateway to spend funds
IERC20(tokenAddress).approve(address(gateway), _amount);
// encode recipient addresses tx on destination chain
bytes memory _payload = abi.encode(_destinationAddrs);
//pay gas from source chain
gasReceiver.payNativeGasForContractCallWithToken{value: msg.value} (
address(this),
_destChain,
_destContractAddr,
_payload,
_symbol,
_amount,
msg.sender
);
// send token and execute call
gateway.callContractWithToken(
_destChain,
_destContractAddr,
_payload,
_symbol,
_amount
);
}
}
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC20 } from '@axelar-network/axelar-cgp-solidity/contracts/interfaces/IERC20.sol';
import { IAxelarExecutable } from '@axelar-network/axelar-cgp-solidity/contracts/interfaces/IAxelarExecutable.sol';
import { IAxelarGasService } from '@axelar-network/axelar-cgp-solidity/contracts/interfaces/IAxelarGasService.sol';
contract BaseReceiver is IAxelarExecutable {
IAxelarGasService public immutable gasService;
constructor (address _gateway, address _gasService)
IAxelarExecutable(_gateway)
{
gasService = IAxelarGasService(_gasService);
}
event Executed();
function _executeWithToken(
string memory,
string memory,
bytes calldata _payload,
string memory _tokenSymbol,
uint256 _amount
) internal override {
// decode recipients
address[] memory recipients = abi.decode(_payload, (address[]));
// get token addr
address tokenAddress = gateway.tokenAddresses(_tokenSymbol);
// get first address
address recipient = recipients[0];
// transfer to recipient
IERC20(tokenAddress).transfer(recipient, _amount);
emit Executed();
}
}
I am not sure why when I call the sendToMany()
function I get the Transaction mined but execution failed
error message
I think the missing step here is approval, you need to approve the amount to be spent spent by the contract before calling the sendToMany
function.
Check this guide: https://axelar.network/blog/cross-chain-airdrop-dapp-tutorial scroll to the Implementing smart-contract write functionality
section to see how the approval is done on the frontend before calling the sendToMany
function.
Or you can approve directly on the aUSDC contract in Optimism Goerli https://goerli-optimism.etherscan.io/address/0x254d06f33bDc5b8ee05b2ea472107E300226659A#writeContract
Note: The arithmetic error (arithmetic overflow/underflow) occurs because the amount is currently 0. The error arises from an attempt to divide by 0. However, once you approve the spender amount, a valid value will be present, and as a result, such an error will no longer occur.