Im working in a bridge for NFTs in a collection and I'm trying to mint from sepolia to mumbai, I've been trying but I get an execution error in the destination chain. The tx went through in the source chain but it gets an error in the destination one I know this is an error of mine, but I wanted to know why is this happening, as I can't see the internal txs of the tx in the destination chain, I can't see the error, here is my code from CCIPReceiver in mumbai:
`// SPDX-License-Identifier: MIT pragma solidity 0.8.19;
import {CCIPReceiver} from "@chainlink/contracts-ccip/src/v0.8/ccip/applications/CCIPReceiver.sol"; import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol"; import {EndersComicsMultiTokensTest} from "./EndersComicsTest.sol";
contract DestinationMinterEdited is CCIPReceiver { EndersComicsMultiTokensTest nft;
event MintCallSuccessfull();
constructor(address router, address nftAddress) CCIPReceiver(router) {
nft = EndersComicsMultiTokensTest(nftAddress);
}
function _ccipReceive(
Client.Any2EVMMessage memory message
) internal override {
(bool success, ) = address(nft).call(message.data);
require(success, "tx failed");
emit MintCallSuccessfull();
}
}`
This is the code for the Source Minter in sepolia:
`// SPDX-License-Identifier: MIT pragma solidity 0.8.19;
import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol"; import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol"; import {Withdraw} from "./utils/Withdraw.sol";
contract SourceMinterEdited is Withdraw { enum PayFeesIn { Native, LINK }
address immutable i_router;
address immutable i_link;
event MessageSent(bytes32 messageId);
constructor(address router, address link) {
i_router = router;
i_link = link;
LinkTokenInterface(i_link).approve(i_router, type(uint256).max);
}
receive() external payable {}
function mint(
uint64 destinationChainSelector,
address receiver,
uint256 id,
uint256 amount,
PayFeesIn payFeesIn
) external {
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
receiver: abi.encode(receiver),
data: abi.encodeWithSignature(
"mintBatch(address,uint256[],uint256[])",
msg.sender,
id,
amount
),
tokenAmounts: new Client.EVMTokenAmount[](0),
extraArgs: Client._argsToBytes(
// Additional arguments, setting gas limit
Client.EVMExtraArgsV1({gasLimit: 2_000_000})
),
feeToken: payFeesIn == PayFeesIn.LINK ? i_link : address(0)
});
uint256 fee = IRouterClient(i_router).getFee(
destinationChainSelector,
message
);
bytes32 messageId;
if (payFeesIn == PayFeesIn.LINK) {
// LinkTokenInterface(i_link).approve(i_router, fee);
messageId = IRouterClient(i_router).ccipSend(
destinationChainSelector,
message
);
} else {
messageId = IRouterClient(i_router).ccipSend{value: fee}(
destinationChainSelector,
message
);
}
emit MessageSent(messageId);
}
} `
This is the code of EndersComicsMultiTokensTest contract mintBatch function, as you see is a simple mintBatch:
function mintBatch( address _receiver, uint256[] calldata ids, uint256[] calldata amounts ) external { _mintBatch(_receiver, ids, amounts, ""); }
Probably the mistake is in the encodeSignature in the sender contract but is something I can't address. I would really appreciate your help.
Here are some of the txs that failed: https://ccip.chain.link/address/0x65b5df19756925Fe1a799dd65742185f117ca0d3 https://ccip.chain.link/address/0x17f806eFadA3a4cF9B18Fa51382c0937a45d4de7
I have try several things, changing the gas_limit in the encodeWithSignature function, also changing the attributes from mintBatch to be only atomic types (non arrays) but none of that worked
As you correctly assumed, the problem is on the encoding side:
Because both variables
idandamountareuint256while you are expected to encode twouint256arrays.The solution will be to:
a) either pass two
uint256arrays instead ofidandamountvariables like this:b) or to create two in-memory arrays containing mentioned variables, like this: