Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move gas bound caller to a separate folder #425

Merged
merged 7 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions gas-bound-caller/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# GasBoundCaller

Starting from v24 On Era, the gas for pubdata is charged at the end of the execution of the entire transaction. This means that if a subcall is not trusted, it can consume a significant amount of pubdata during the process. While this may not be an issue for most contracts, there are use cases, e.g., for relayers, where it is crucial to ensure that the subcall will not spend more money than intended.

The `GasBoundCaller` is a contract with the following interface:

```solidity
function gasBoundCall(address _to, uint256 _maxTotalGas, bytes calldata _data) external payable
```

> Note that the amount of gas passed into this function should be less than or equal to `_maxTotalGas`. If the computational gas provided is higher than `_maxTotalGas`, the higher value will be used.

This contract will call the address `_to` with the entire execution gas passed to it, while ensuring that the total consumed gas does not exceed `_maxTotalGas` under any circumstances.

If the call to the `_to` address fails, the gas used on pubdata is considered zero, and the total gas used is fully equivalent to the gas consumed within the execution. The `GasBoundCaller` will relay the revert message as-is.

If the call to the `_to` address succeeds, the `GasBoundCaller` will ensure that the total consumed gas does not exceed `_maxTotalGas`. If it does, it will revert with a "Not enough gas for pubdata" error. If the total consumed gas is less than or equal to `_maxTotalGas`, the `GasBoundCaller` will return returndata equal to `abi.encode(bytes returndataFromSubcall, uint256 gasUsedForPubdata)`.

## Usage
StanislavBreadless marked this conversation as resolved.
Show resolved Hide resolved

Summing up the information from the previous chapter, the `GasBoundCaller` should be used in the following way:

TODO(EVM-585): switch `addr` with address.

```solidity
uint256 computeGasBefore = gasleft();

(bool success, bytes memory returnData) = address(this).call{gas: _gasToPass}(abi.encodeWithSelector(GasBoundCaller.gasBoundCall.selector, _to, _maxTotalGas, _data));

uint256 pubdataGasSpent;
if (success) {
(returnData, pubdataGasSpent) = abi.decode(returnData, (bytes, uint256));
} else {
// `returnData` is fully equal to the returndata, while `pubdataGasSpent` is equal to 0
}

uint256 computeGasAfter = gasleft();

// This is the total gas that the subcall made the transaction to be charged for
uint256 totalGasConsumed = computeGasBefore - computeGasAfter + pubdataGasSpent;
```

### Preserving `msg.sender`

Since `GasBoundCaller` would be the contract that calls the `_to` contract, the `msg.sender` will be equal to the `GasBoundCaller`'s address. To preserve the current `msg.sender`, this contract can be inherited from and used the same way, but instead of calling `GasBoundCaller.gasBoundCall`, `this.gasBoundCall` could be called.

## Deployed Address

It should be deployed via a built-in CREATE2 factory on each individual chain.

TODO(EVM-585)
1 change: 1 addition & 0 deletions gas-bound-caller/canonical-bytecodes/GasBoundCaller
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0x00120000000000020006000000000002000000000301001900000060043002700000009e03400197000100000031035500020000003103550003000000310355000400000031035500050000003103550006000000310355000700000031035500080000003103550009000000310355000a000000310355000b000000310355000c000000310355000d000000310355000e000000310355000f000000310355001000000031035500110000000103550000009e0040019d0000008004000039000000400040043f00000001022001900000004d0000c13d000000040230008c000000a50000413d000000000201043b000000a002200197000000a10220009c000000a50000c13d000000040230008a000000600220008c000000a50000413d0000000402100370000000000802043b000000a20280009c000000a50000213d0000004402100370000000000202043b000000a30420009c000000a50000213d0000002304200039000000a405000041000000000634004b00000000060000190000000006058019000000a404400197000000000704004b0000000005008019000000a40440009c000000000506c019000000000405004b000000a50000c13d0000000404200039000000000441034f000000000604043b000000a30460009c000000a50000213d00000024052000390000000004560019000000000234004b000000a50000213d0000002401100370000000000201043b0000000003000414000003200100008a000000000113004b000000550000413d000000b10100004100000000001004350000001101000039000000040010043f000000b20100004100000274000104300000000001000416000000000101004b000000a50000c13d0000002001000039000001000010044300000120000004430000009f01000041000002730001042e0000000001000414000000000121004b000000620000a13d000000af01000041000000800010043f0000002001000039000000840010043f0000001401000039000000a40010043f000000b401000041000000c40010043f000000b5010000410000027400010430000200000006001d000100000005001d000500000004001d000600000008001d000000a501000041000000800010043f0000009e01000041000400000002001d0000000002000414000300000003001d0000009e0320009c0000000002018019000000c001200210000000a6011001c70000800b02000039027202680000040f00000003030000290000000403300069000003200a30008a0000000403a0006c00000000030000190000000103002039000000000303004b000000000a00c019000000000301001900000060033002700000009e03300197000000200430008c000000000403001900000020040080390000001f0540018f00000005064002720000008c0000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000000840000413d000000000705004b000000060b0000290000009c0000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f00000000005604350000000102200190000000050c000029000000a70000613d0000001f01400039000000600210018f00000080012001bf000000400010043f000000200330008c000000ca0000813d00000000010000190000027400010430000000400200043d0000001f0430018f0000000505300272000000b40000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000000ac0000413d000000000604004b000000c30000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000009e010000410000009e0420009c000000000201801900000040012002100000006002300210000000000121019f0000027400010430000000800900043d0000000004000414000000000600003100000011050003670000000003000416000000000703004b000000e80000c13d000000020300006b000000da0000613d00000001030000290000009e0330019700010000003503550000000007c6004b000000470000413d000000000535034f0000000006c600490000009e0360019700010000003503e50000009e0640009c000000f50000213d000400000009001d00050000000a001d00000000013503df000000c002400210000000a802200197000000aa022001c700010000002103b500000000012103af00000000020b00190000010f0000013d000000020700006b000000f10000613d00000001070000290000009e0770019700010000007503550000000008c6004b000000470000413d000000000575034f0000000006c600490000009e0660019700010000006503e5000000a70740009c000001030000413d000000af03000041000000000031043500000084032001bf00000020040000390000000000430435000000c403200039000000b3040000410000000000430435000000a402200039000000080300003900000000003204350000004001100210000000b0011001c70000027400010430000400000009001d00050000000a001d00000000016503df000000c002400210000000a802200197000000a9022001c700010000002103b500000000012103af000080090200003900000000040b0019000000000500001900000000060000190272026d0000040f000000000301001900000060033002700000009e033001970000000102200190000001d90000613d0000003f02300039000000ab02200197000000400600043d0000000002260019000000000462004b00000000040000190000000104004039000000a30520009c000001d50000213d0000000104400190000001d50000c13d000000400020043f000200000006001d00000000023604360000001f043000390000000504400272000001310000613d00000000050000310000001105500367000000000600001900000005076002100000000008720019000000000775034f000000000707043b00000000007804350000000106600039000000000746004b000001290000413d000000000400004b000001330000613d0000001f0430018f00000005033002720000013f0000613d000000000500001900000005065002100000000007620019000000000661034f000000000606043b00000000006704350000000105500039000000000635004b000001370000413d000000000504004b0000014e0000613d0000000503300210000000000131034f00000000023200190000000303400210000000000402043300000000043401cf000000000434022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f0000000000120435000000400400043d000600000004001d000000a50100004100000000001404350000009e0100004100000000020004140000009e0320009c00000000020180190000009e0340009c00000000010440190000004001100210000000c002200210000000000112019f000000ac011001c70000800b02000039027202680000040f000000060a000029000000000301001900000060033002700000009e03300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000001710000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000001690000413d00000000090a0019000000000705004b000001810000613d0000000506600210000000000761034f00000000066900190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f00000000005604350000000102200190000001f40000613d0000001f01400039000000600110018f0000000002910019000000000112004b00000000010000190000000101004039000300000002001d000000a30220009c000001d50000213d0000000101100190000001d50000c13d0000000301000029000000400010043f000000200130008c0000000501000029000000a50000413d000500000001001d0000000001090433000600000001001d000000ad01000041000000030400002900000000001404350000009e0100004100000000020004140000009e0320009c00000000020180190000009e0340009c00000000010440190000004001100210000000c002200210000000000112019f000000ac011001c70000800b02000039027202680000040f000000030b0000290000000605000029000000040450006a000000000354004b00000000030000190000000103002039000000000303004b000000000400c019000000000301001900000060033002700000009e03300197000000200530008c000000000503001900000020050080390000001f0650018f0000000507500272000001bf0000613d00000000080000190000000509800210000000000a9b0019000000000991034f000000000909043b00000000009a04350000000108800039000000000978004b000001b70000413d000000000806004b000001ce0000613d0000000507700210000000000871034f00000003077000290000000306600210000000000907043300000000096901cf000000000969022f000000000808043b0000010006600089000000000868022f00000000066801cf000000000696019f00000000006704350000000102200190000002110000613d0000001f01500039000000600110018f0000000301100029000000a30210009c0000022e0000a13d000000b101000041000000000010043500000041010000390000004a0000013d0000001f0430018f0000000502300272000001e40000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000001dd0000413d000000000504004b000001f20000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000012043500000060013002100000027400010430000000400200043d0000001f0430018f0000000505300272000002010000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000001f90000413d000000000604004b000002100000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000000c30000013d000000400200043d0000001f0430018f00000005053002720000021e0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000002160000413d000000000604004b0000022d0000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000000c30000013d000000400010043f000000200230008c000000a50000413d0000000302000029000000000302043300000000524300a9000000000503004b0000023b0000613d00000000533200d9000000000343004b000000470000c13d000000000302004b0000024c0000c13d0000000203000029000000200130008a0000000000210435000000400130008a00000040020000390000000000210435000000000203043300000060022000390000009e030000410000009e0420009c00000000020380190000009e0410009c000000000103801900000040011002100000006002200210000000000112019f000002730001042e00000000040004140000000503400029000000000443004b000000000400001900000001040040390000000104400190000000470000c13d000001910400008a000000000442004b000000470000213d0000019004200039000000000343004b0000023b0000813d0000004402100039000000ae03000041000000000032043500000024021000390000001a030000390000000000320435000000af0200004100000000002104350000000402100039000000200300003900000000003204350000009e020000410000009e0310009c0000000001028019000001000000013d0000026b002104230000000102000039000000000001042d0000000002000019000000000001042d00000270002104210000000102000039000000000001042d0000000002000019000000000001042d0000027200000432000002730001042e000002740001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0000000200000000000000000000000000000040000001000000000000000000ffffffff0000000000000000000000000000000000000000000000000000000041a8596c00000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000c0d5b949000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000800000000000000000000000000000000000000000000000000000000000000000000000010000000000000000ffffffff0000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000040000000000000000000000007cb9357e000000000000000000000000000000000000000000000000000000004e6f7420656e6f7567682067617320666f72207075626461746100000000000008c379a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000004f766572666c6f77000000000000000000000000000000000000000000000000476173206c696d697420697320746f6f206c6f7700000000000000000000000000000000000000000000000000000000000000640000008000000000000000006c300d3e2b009b9a5b1fe7d853a9ae64e30e1d513df698d5c9801da939df7831
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

pragma solidity 0.8.20;

import {EfficientCall} from "./libraries/EfficientCall.sol";
import {REAL_SYSTEM_CONTEXT_CONTRACT} from "./Constants.sol";
import {EfficientCall} from "@matterlabs/zksync-contracts/l2/system-contracts/libraries/EfficientCall.sol";
import {ISystemContext} from "./ISystemContext.sol";

ISystemContext constant SYSTEM_CONTEXT_CONTRACT = ISystemContext(address(0x800b));

/**
* @author Matter Labs
Expand All @@ -18,7 +20,7 @@ contract GasBoundCaller {
uint256 constant CALL_ENTRY_OVERHEAD = 800;
/// @notice We assume that no more than `CALL_RETURN_OVERHEAD` ergs are used for the O(1) operations at the end of the execution,
/// as such relaying the return.
uint256 constant CALL_RETURN_OVERHEAD = 200;
uint256 constant CALL_RETURN_OVERHEAD = 400;

/// @notice The function that implements limiting of the total gas expenditure of the call.
/// @dev On Era, the gas for pubdata is charged at the end of the execution of the entire transaction, meaning
Expand Down Expand Up @@ -48,7 +50,7 @@ contract GasBoundCaller {
// This is the amount of gas that can be spent *exclusively* on pubdata in addition to the `gas` provided to this function.
uint256 pubdataAllowance = _maxTotalGas > expectedForCompute ? _maxTotalGas - expectedForCompute : 0;

uint256 pubdataPublishedBefore = REAL_SYSTEM_CONTEXT_CONTRACT.getCurrentPubdataSpent();
uint256 pubdataPublishedBefore = SYSTEM_CONTEXT_CONTRACT.getCurrentPubdataSpent();

// We never permit system contract calls.
// If the call fails, the `EfficientCall.call` will propagate the revert.
Expand All @@ -62,15 +64,24 @@ contract GasBoundCaller {
_isSystem: false
});

uint256 pubdataPublishedAfter = REAL_SYSTEM_CONTEXT_CONTRACT.getCurrentPubdataSpent();
// We will calculate the length of the returndata to be used at the end of the function.
// We need additional `96` bytes to encode the offset `0x40` for the entire pubdata,
// the gas spent on pubdata as well as the length of the original returndata.
// Note, that it has to be padded to the 32 bytes to adhere to proper ABI encoding.
uint256 paddedReturndataLen = returnData.length + 96;
if (paddedReturndataLen % 32 != 0) {
paddedReturndataLen += 32 - (paddedReturndataLen % 32);
}

uint256 pubdataPublishedAfter = SYSTEM_CONTEXT_CONTRACT.getCurrentPubdataSpent();

// It is possible that pubdataPublishedAfter < pubdataPublishedBefore if the call, e.g. removes
// some of the previously created state diffs
uint256 pubdataSpent = pubdataPublishedAfter > pubdataPublishedBefore
? pubdataPublishedAfter - pubdataPublishedBefore
: 0;

uint256 pubdataGasRate = REAL_SYSTEM_CONTEXT_CONTRACT.gasPerPubdataByte();
uint256 pubdataGasRate = SYSTEM_CONTEXT_CONTRACT.gasPerPubdataByte();

// In case there is an overflow here, the `_maxTotalGas` wouldn't be able to cover it anyway, so
// we don't mind the contract panicking here in case of it.
Expand All @@ -83,8 +94,16 @@ contract GasBoundCaller {
}

assembly {
// We just relay the return data from the call.
return(add(returnData, 0x20), mload(returnData))
// This place does interfere with the memory layout, however, it is done right before
// the `return` statement, so it is safe to do.
// We need to transform `bytes memory returnData` into (bytes memory returndata, gasSpentOnPubdata)
// `bytes memory returnData` is encoded as `length` + `data`.
// We need to prepend it with 0x40 and `pubdataGas`.
//
// It is assumed that the position of returndata is >= 0x40, since 0x40 is the free memory pointer location.
mstore(sub(returnData, 0x40), 0x40)
mstore(sub(returnData, 0x20), pubdataGas)
return(sub(returnData, 0x40), paddedReturndataLen)
}
}
}
Loading
Loading