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 thesendToMany
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.