Skip to content

Commit

Permalink
Add gasCost to GmpCreated
Browse files Browse the repository at this point in the history
  • Loading branch information
Lohann committed Jan 5, 2025
1 parent 58a9626 commit 825d7d5
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 22 deletions.
28 changes: 19 additions & 9 deletions src/Gateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ contract Gateway is IGateway, IExecutor, IUpgradable, GatewayEIP712 {

/**
* @dev Selector of `GmpCreated` event.
* keccak256("GmpCreated(bytes32,bytes32,address,uint16,uint256,uint256,bytes)");
* keccak256("GmpCreated(bytes32,bytes32,address,uint16,uint64,uint64,uint256,bytes)");
*/
bytes32 private constant GMP_CREATED_EVENT_SELECTOR =
0x0114885f90b5168242aa31b7afb9c2e9f88e90ce329c893d3e6c56021c4c03a5;
0xd9047a7e6f40289fbb463a818e2a4e84b4ef712beab3dc322f4bd3ab13dd79a3;

/**
* @dev The address of the `UniversalFactory` contract, must be the same on all networks.
Expand Down Expand Up @@ -500,7 +500,8 @@ contract Gateway is IGateway, IExecutor, IUpgradable, GatewayEIP712 {
// Check if the provided parameters are valid
// See `RouteStorage.estimateWeiCost` at `storage/Routes.sol` for more details.
RouteStore.NetworkInfo memory route = RouteStore.getMainStorage().get(NetworkID.wrap(routeId));
require(msg.value >= route.estimateWeiCost(data, executionGasLimit), "insufficient tx value");
(uint256 gasCost, uint256 fee) = route.estimateCost(data, executionGasLimit);
require(msg.value >= fee, "insufficient tx value");

// We use 20 bytes for represent the address and 1 bit for the contract flag
GmpSender source = msg.sender.toSender(false);
Expand All @@ -514,7 +515,14 @@ contract Gateway is IGateway, IExecutor, IUpgradable, GatewayEIP712 {

// Emit `GmpCreated` event without copy the data, to simplify the gas estimation.
_emitGmpCreated(
message.eip712hash(), source, destinationAddress, routeId, executionGasLimit, nextNonce, message.data
message.eip712hash(),
source,
destinationAddress,
routeId,
executionGasLimit,
gasCost,
nextNonce,
message.data
);
}

Expand All @@ -527,6 +535,7 @@ contract Gateway is IGateway, IExecutor, IUpgradable, GatewayEIP712 {
address destinationAddress,
uint16 destinationNetwork,
uint256 executionGasLimit,
uint256 gasCost,
uint256 salt,
bytes memory payload
) private {
Expand All @@ -537,13 +546,14 @@ contract Gateway is IGateway, IExecutor, IUpgradable, GatewayEIP712 {
// return prevHash;
// ```
assembly {
let ptr := sub(payload, 0x80)
mstore(ptr, destinationNetwork) // dest network
let ptr := sub(payload, 0xa0)
mstore(add(ptr, 0x00), destinationNetwork) // dest network
mstore(add(ptr, 0x20), executionGasLimit) // gas limit
mstore(add(ptr, 0x40), salt) // salt
mstore(add(ptr, 0x60), 0x80) // data offset
mstore(add(ptr, 0x40), gasCost) // gasCost
mstore(add(ptr, 0x60), salt) // salt
mstore(add(ptr, 0x80), 0xa0) // data offset
let size := and(add(mload(payload), 31), 0xffffffe0)
size := add(size, 160)
size := add(size, 192)
log4(ptr, size, GMP_CREATED_EVENT_SELECTOR, messageID, source, destinationAddress)
mstore(0, messageID)
return(0, 32)
Expand Down
4 changes: 3 additions & 1 deletion src/interfaces/IGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface IGateway {
* @param destinationAddress the target address on the destination chain.
* @param destinationNetwork the target chain where the contract call will be made.
* @param executionGasLimit the gas limit available for the contract call
* @param gasCost the gas limit available for the contract call
* @param salt salt is equal to the previous message id (EIP-712 hash).
* @param data message data with no specified format
*/
Expand All @@ -24,7 +25,8 @@ interface IGateway {
bytes32 indexed source,
address indexed destinationAddress,
uint16 destinationNetwork,
uint256 executionGasLimit,
uint64 executionGasLimit,
uint64 gasCost,
uint256 salt,
bytes data
);
Expand Down
23 changes: 23 additions & 0 deletions src/storage/Routes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ library RouteStore {
using EnumerableSet for EnumerableSet.Map;
using NetworkIDHelpers for NetworkID;
using UFloatMath for UFloat9x56;
using BranchlessMath for uint256;

/**
* @dev Namespace of the routes storage `analog.one.gateway.routes`.
Expand Down Expand Up @@ -234,6 +235,28 @@ library RouteStore {
require(messageSize <= MAX_PAYLOAD_SIZE, "maximum payload size exceeded");
}

/**
* @dev Utility function for measure the wei cost of a GMP message.
*/
function estimateCost(NetworkInfo memory route, bytes calldata data, uint256 gasLimit)
internal
pure
returns (uint256 gasCost, uint256 fee)
{
// Guarantee the networks exists and `data` is less than `MAX_PAYLOAD_SIZE`
_checkPreconditions(route, data.length, gasLimit);

// Compute base cost
uint256 nonZeros = GasUtils.countNonZerosCalldata(data);
uint256 zeros = data.length - nonZeros;

// Compute execution cost
gasCost = GasUtils.estimateGas(uint16(nonZeros), uint16(zeros), gasLimit);

// Calculate the gas cost: gasPrice * gasCost + baseFee
fee = UFloatMath.saturatingMul(route.relativeGasPrice, gasCost).saturatingAdd(route.baseFee);
}

/**
* @dev Utility function for measure the wei cost of a GMP message.
*/
Expand Down
6 changes: 3 additions & 3 deletions src/utils/GasUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ library GasUtils {
* @dev How much gas is used until the first `gasleft()` instruction is executed in the `Gateway.batchExecute` method.
*
* HOW TO UPDATE THIS VALUE:
* 1. Run `forge test --match-test=TempTest --debug`
* 1. Run `forge test --match-test=test_gasMeter --fuzz-runs=1 --debug`
* 2. Move the cursor until you enter the `src/Gateway.sol` file.
* 3. Execute the opcodes until you reach the first `GAS` opcode.
* 4. Execute the GAS opcode then copy the `Gas used in call` value to the constant below.
Expand All @@ -30,7 +30,7 @@ library GasUtils {
* @dev How much gas is used until the first `gasleft()` instruction is executed.
*
* HOW TO UPDATE THIS VALUE:
* 1. Run `forge test --match-test=TempTest --debug`
* 1. Run `forge test --match-test=test_submitMessageMeter --fuzz-runs=1 --debug`
* 2. Move the cursor until you enter the `src/Gateway.sol` file.
* 3. Execute the opcodes until you reach the first `GAS` opcode.
* 4. Execute the GAS opcode then copy the `Gas used in call` value to the constant below.
Expand All @@ -48,7 +48,7 @@ library GasUtils {
/**
* @dev Base cost of the `IGateway.submitMessage` method.
*/
uint256 internal constant SUBMIT_BASE_COST = 23873;
uint256 internal constant SUBMIT_BASE_COST = 24116;

/**
* @dev Extra gas cost of the first `IGateway.submitMessage` method.
Expand Down
18 changes: 17 additions & 1 deletion test/Example.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {GatewayProxy} from "../src/GatewayProxy.sol";
import {IGateway} from "../src/interfaces/IGateway.sol";
import {IGmpReceiver} from "../src/interfaces/IGmpReceiver.sol";
import {IExecutor} from "../src/interfaces/IExecutor.sol";
import {GasUtils} from "../src/utils/GasUtils.sol";
import {
GmpMessage,
UpdateKeysMessage,
Expand Down Expand Up @@ -113,11 +114,26 @@ contract ExampleTest is Test {
data: abi.encode(MockERC20.CrossChainTransfer({from: ALICE, to: BOB, amount: 100}))
});

// Calculate the expect GMP gas cost
uint256 gasCost;
{
uint256 nonZeros = GasUtils.countNonZeros(gmp.data);
uint256 zeros = gmp.data.length - nonZeros;
gasCost = GasUtils.estimateGas(uint16(nonZeros), uint16(zeros), gmp.gasLimit);
}

// Expect `GmpCreated` to be emitted
bytes32 messageID = gmp.eip712hash();
vm.expectEmit(true, true, true, true, address(srcGateway));
emit IGateway.GmpCreated(
messageID, GmpSender.unwrap(gmp.source), gmp.dest, gmp.destNetwork, gmp.gasLimit, gmp.salt, gmp.data
messageID,
GmpSender.unwrap(gmp.source),
gmp.dest,
gmp.destNetwork,
uint64(gmp.gasLimit),
uint64(gasCost),
gmp.salt,
gmp.data
);

{
Expand Down
35 changes: 27 additions & 8 deletions test/Gateway.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,6 @@ contract GatewayTest is BaseTest {
bytes memory encoded =
abi.encodeCall(IGateway.submitMessage, (gmp.dest, gmp.destNetwork, gmp.gasLimit, gmp.data));
assertEq(encoded.length, ((gmp.data.length + 31) & 0xffe0) + 164, "wrong encoded length");
emit log_named_bytes(" calldata", encoded);
baseCost = TestUtils.calculateBaseCost(encoded);
}

Expand All @@ -533,8 +532,16 @@ contract GatewayTest is BaseTest {
bytes32 id = gmp.eip712hash();
vm.expectEmit(true, true, true, true);
emit IGateway.GmpCreated(
id, GmpSender.unwrap(gmp.source), gmp.dest, gmp.destNetwork, gmp.gasLimit, gmp.salt, gmp.data
id,
GmpSender.unwrap(gmp.source),
gmp.dest,
gmp.destNetwork,
uint64(gmp.gasLimit),
uint64(ctx.value),
gmp.salt,
gmp.data
);
console.log("expect: ", ctx.value);
ctx.gasLimit += 17100;
assertEq(ctx.submitMessage(gmp), id, "unexpected GMP id");

Expand Down Expand Up @@ -738,14 +745,19 @@ contract GatewayTest is BaseTest {
vm.expectRevert("insufficient tx value");
ctx.submitMessage(gmp);

// Expect event
// Submit message with sufficient funds
ctx.value += 1;
vm.expectEmit(true, true, true, true);
emit IGateway.GmpCreated(
id, GmpSender.unwrap(gmp.source), gmp.dest, gmp.destNetwork, gmp.gasLimit, gmp.salt, gmp.data
id,
GmpSender.unwrap(gmp.source),
gmp.dest,
gmp.destNetwork,
uint64(gmp.gasLimit),
uint64(ctx.value),
gmp.salt,
gmp.data
);

// Submit message with sufficient funds
ctx.value += 1;
assertEq(ctx.submitMessage(gmp), id, "unexpected GMP id");

// Verify the gas cost
Expand All @@ -759,7 +771,14 @@ contract GatewayTest is BaseTest {
// Expect event
vm.expectEmit(true, true, true, true);
emit IGateway.GmpCreated(
id, GmpSender.unwrap(gmp.source), gmp.dest, gmp.destNetwork, gmp.gasLimit, gmp.salt, gmp.data
id,
GmpSender.unwrap(gmp.source),
gmp.dest,
gmp.destNetwork,
uint64(gmp.gasLimit),
uint64(ctx.value),
gmp.salt,
gmp.data
);
assertEq(ctx.submitMessage(gmp), id, "unexpected GMP id");
assertEq(ctx.executionCost, expectedCost - 6800, "unexpected execution gas cost in second call");
Expand Down

0 comments on commit 825d7d5

Please sign in to comment.