I am trying to make an external function call, with arguments, to a contract written in Solidity from a contract written in Huff. I am able to successfully call an external contract when the function does not accept any arguments, however when it does accept arguments, the fallback function is always triggered and caused the transaction to revert. I know this because if I will add a simple fallback function that does nothing, then the transaction doesn't revert anymore. I have created a set of files to reproduce the issue and please note that I am using Foundry and foundry-huff for development.
Counter.sol:
// SPDX-License-Identifier: BSL-1.1
pragma solidity 0.8.19;
contract Counter {
uint256 public count;
constructor() {}
// fallback() external {} // uncomment to stop increase from reverting
function increment() public {
count++;
}
function increase(uint256 amount_) public {
count += amount_;
}
}
HuffCounter.sol:
/// @title HuffCounter
/// @notice SPDX-License-Identifier: BSL-1.1
/* Interface */
#define function increment(address) nonpayable returns ()
#define function increase(address, uint256) nonpayable returns ()
/* Constructor */
#define macro CONSTRUCTOR() = takes (0) returns (0) {}
/* Methods */
#define macro INCREMENT_COUNT() = takes(0) returns (0) {
__FUNC_SIG("increment()") 0x00 mstore
0x00 // [ret_size]
0x00 // [ret_offset, ret_size]
0x04 // [args_size, ret_offset, ret_size]
0x1C // [args_offset, args_size, ret_offset, ret_size]
0x00 // [value, args_offset, args_size, ret_offset, ret_size]
0x04 calldataload // [counter_addr, value, args_offset, args_size, ret_offset, ret_size]
gas // [gas, counter_addr, value, args_offset, args_size, ret_offset, ret_size]
call // [successs]
0x00 eq err jumpi
cont jump
err:
0x00 0x00 revert
cont:
0x00 0x00 return
}
#define macro INCREASE_COUNT() = takes(0) returns (0) {
__FUNC_SIG("increase(uint256)") 0x00 mstore
0x24 calldataload
0x04 mstore
0x00 // [ret_size]
0x00 // [ret_offset, ret_size]
0x24 // [args_size, ret_offset, ret_size]
0x20 // [args_offset, args_size, ret_offset, ret_size]
0x00 // [value, args_offset, args_size, ret_offset, ret_size]
0x04 calldataload // [counter_addr, value, args_offset, args_size, ret_offset, ret_size]
gas // [gas, counter_addr, value, args_offset, args_size, ret_offset, ret_size]
call // [successs]
0x00 eq err jumpi
cont jump
err:
0x00 0x00 revert
cont:
0x00 0x00 return
}
#define macro MAIN() = takes (0) returns (0) {
// Identify which function is being called.
0x00 calldataload 0xE0 shr
dup1 __FUNC_SIG(increment) eq increment jumpi
dup1 __FUNC_SIG(increase) eq increase jumpi
0x00 0x00 revert
increment:
INCREMENT_COUNT()
increase:
INCREASE_COUNT()
}
HuffCounter.t.sol:
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.15;
import "forge-std/Test.sol";
import "foundry-huff/HuffDeployer.sol";
import "forge-std/console.sol";
import {Counter} from "src/Counter.sol";
contract BundleExecutorTest is Test {
Counter public counter;
IHuffCounter public huffCounter;
function setUp() public {
counter = new Counter();
huffCounter = IHuffCounter(HuffDeployer.deploy("HuffCounter"));
}
function testIncrement() public {
huffCounter.increment(address(counter));
uint256 count_ = counter.count();
console.log(count_);
}
function testIncrease() public {
huffCounter.increase(address(counter), 3);
uint256 count_ = counter.count();
console.log(count_);
}
}
interface IHuffCounter {
function increment(address) external;
function increase(address, uint256) external;
}