@@ -28,24 +28,19 @@ contract ExecutorQuoter is IExecutorQuoter {
2828 uint64 dstPrice;
2929 }
3030
31- struct ChainDecimals {
31+ struct ChainInfo {
3232 bool enabled;
3333 uint8 gasPriceDecimals;
3434 uint8 nativeDecimals;
3535 }
3636
37- struct QuoteUpdate {
37+ struct Update {
3838 uint16 chainId;
39- OnChainQuoteBody quote;
40- }
41-
42- struct DecimalsUpdate {
43- uint16 chainId;
44- ChainDecimals decimals;
39+ bytes32 update;
4540 }
4641
4742 mapping (uint16 => OnChainQuoteBody) public quoteByDstChain;
48- mapping (uint16 => ChainDecimals ) public decimalsByDstChain ;
43+ mapping (uint16 => ChainInfo ) public chainInfos ;
4944
5045 /// @dev Selector 0x40788bb5.
5146 error InvalidUpdater (address sender , address expected );
@@ -56,43 +51,57 @@ contract ExecutorQuoter is IExecutorQuoter {
5651 /// @dev Selector 0x3a5a1720.
5752 error MoreThanOneDropOff ();
5853
54+ modifier onlyUpdater () {
55+ if (msg .sender != updaterAddress) {
56+ revert InvalidUpdater (msg .sender , updaterAddress);
57+ }
58+ _;
59+ }
60+
5961 constructor (address _quoterAddress , address _updaterAddress , uint8 _srcTokenDecimals , bytes32 _payeeAddress ) {
6062 quoterAddress = _quoterAddress;
6163 updaterAddress = _updaterAddress;
6264 srcTokenDecimals = _srcTokenDecimals;
6365 payeeAddress = _payeeAddress;
6466 }
6567
66- function decimalsUpdate (DecimalsUpdate[] calldata updates ) public {
67- if (msg .sender != updaterAddress) {
68- revert InvalidUpdater (msg .sender , updaterAddress);
69- }
70- uint256 updatesLength = updates.length ;
71- for (uint256 i = 0 ; i < updatesLength;) {
72- DecimalsUpdate memory update = updates[i];
73- decimalsByDstChain[update.chainId] = update.decimals;
74- unchecked {
75- i += 1 ;
68+ function _batchUpdate (Update[] calldata updates , uint256 mappingSlot ) private {
69+ assembly {
70+ let len := updates.length
71+ let baseOffset := updates.offset
72+
73+ for { let i := 0 } lt (i, len) { i := add (i, 1 ) } {
74+ // Load update directly from calldata
75+ let updatePtr := add (baseOffset, mul (i, 0x40 ))
76+ let chainId := calldataload (updatePtr)
77+ let newValue := calldataload (add (updatePtr, 0x20 ))
78+
79+ // Calculate storage slot for mapping[chainId]
80+ mstore (0x00 , chainId)
81+ mstore (0x20 , mappingSlot)
82+ let slot := keccak256 (0x00 , 0x40 )
83+ sstore (slot, newValue)
7684 }
7785 }
7886 }
7987
80- // TODO: pack these updates instead to save l2 cost
81- function quoteUpdate (QuoteUpdate[] calldata updates ) public {
82- if ( msg . sender != updaterAddress) {
83- revert InvalidUpdater ( msg . sender , updaterAddress);
88+ function chainInfoUpdate (Update[] calldata updates ) external onlyUpdater {
89+ uint256 slot;
90+ assembly {
91+ slot := chainInfos.slot
8492 }
85- uint256 updatesLength = updates. length ;
86- for ( uint256 i = 0 ; i < updatesLength;) {
87- QuoteUpdate memory update = updates[i];
88- quoteByDstChain[update.chainId] = update.quote;
89- unchecked {
90- i += 1 ;
91- }
93+ _batchUpdate ( updates, slot) ;
94+ }
95+
96+ function quoteUpdate (Update[] calldata updates ) external onlyUpdater {
97+ uint256 slot;
98+ assembly {
99+ slot := quoteByDstChain.slot
92100 }
101+ _batchUpdate (updates, slot);
93102 }
94103
95- function normalize (uint256 amount , uint8 from , uint8 to ) internal pure returns (uint256 ) {
104+ function normalize (uint256 amount , uint8 from , uint8 to ) private pure returns (uint256 ) {
96105 if (from > to) {
97106 return amount / 10 ** uint256 (from - to);
98107 } else if (from < to) {
@@ -101,11 +110,11 @@ contract ExecutorQuoter is IExecutorQuoter {
101110 return amount;
102111 }
103112
104- function mul (uint256 a , uint256 b , uint8 decimals ) internal pure returns (uint256 ) {
113+ function mul (uint256 a , uint256 b , uint8 decimals ) private pure returns (uint256 ) {
105114 return (a * b) / 10 ** uint256 (decimals);
106115 }
107116
108- function div (uint256 a , uint256 b , uint8 decimals ) internal pure returns (uint256 ) {
117+ function div (uint256 a , uint256 b , uint8 decimals ) private pure returns (uint256 ) {
109118 return (a * 10 ** uint256 (decimals)) / b;
110119 }
111120
@@ -115,7 +124,7 @@ contract ExecutorQuoter is IExecutorQuoter {
115124 /// - `GasDropOffInstruction` contributes only to `msgValue`.
116125 /// Throws If an unsupported instruction type is encountered.
117126 function totalGasLimitAndMsgValue (bytes calldata relayInstructions )
118- internal
127+ private
119128 pure
120129 returns (uint256 gasLimit , uint256 msgValue )
121130 {
@@ -157,23 +166,22 @@ contract ExecutorQuoter is IExecutorQuoter {
157166
158167 function estimateQuote (
159168 OnChainQuoteBody storage quote ,
160- ChainDecimals storage dstChainDecimals ,
169+ ChainInfo storage dstChainInfo ,
161170 uint256 gasLimit ,
162171 uint256 msgValue
163- ) internal view returns (uint256 ) {
172+ ) private view returns (uint256 ) {
164173 uint256 srcChainValueForBaseFee = normalize (quote.baseFee, QUOTE_DECIMALS, srcTokenDecimals);
165174
166175 uint256 nSrcPrice = normalize (quote.srcPrice, QUOTE_DECIMALS, DECIMAL_RESOLUTION);
167176 uint256 nDstPrice = normalize (quote.dstPrice, QUOTE_DECIMALS, DECIMAL_RESOLUTION);
168177 uint256 scaledConversion = div (nDstPrice, nSrcPrice, DECIMAL_RESOLUTION);
169178
170179 uint256 nGasLimitCost =
171- normalize (gasLimit * quote.dstGasPrice, dstChainDecimals.gasPriceDecimals, DECIMAL_RESOLUTION);
172-
180+ normalize (gasLimit * quote.dstGasPrice, dstChainInfo.gasPriceDecimals, DECIMAL_RESOLUTION);
173181 uint256 srcChainValueForGasLimit =
174182 normalize (mul (nGasLimitCost, scaledConversion, DECIMAL_RESOLUTION), DECIMAL_RESOLUTION, srcTokenDecimals);
175183
176- uint256 nMsgValue = normalize (msgValue, dstChainDecimals .nativeDecimals, DECIMAL_RESOLUTION);
184+ uint256 nMsgValue = normalize (msgValue, dstChainInfo .nativeDecimals, DECIMAL_RESOLUTION);
177185 uint256 srcChainValueForMsgValue =
178186 normalize (mul (nMsgValue, scaledConversion, DECIMAL_RESOLUTION), DECIMAL_RESOLUTION, srcTokenDecimals);
179187 return srcChainValueForBaseFee + srcChainValueForGasLimit + srcChainValueForMsgValue;
@@ -185,15 +193,15 @@ contract ExecutorQuoter is IExecutorQuoter {
185193 address , //refundAddr,
186194 bytes calldata , //requestBytes,
187195 bytes calldata relayInstructions
188- ) public view returns (bytes32 , uint256 ) {
189- ChainDecimals storage dstChainDecimals = decimalsByDstChain [dstChain];
190- if (! dstChainDecimals .enabled) {
196+ ) external view returns (bytes32 , uint256 ) {
197+ ChainInfo storage dstChainInfo = chainInfos [dstChain];
198+ if (! dstChainInfo .enabled) {
191199 revert ChainDisabled (dstChain);
192200 }
193201 OnChainQuoteBody storage quote = quoteByDstChain[dstChain];
194202 (uint256 gasLimit , uint256 msgValue ) = totalGasLimitAndMsgValue (relayInstructions);
195203 // NOTE: this does not include any maxGasLimit or maxMsgValue checks
196- uint256 requiredPayment = estimateQuote (quote, dstChainDecimals , gasLimit, msgValue);
204+ uint256 requiredPayment = estimateQuote (quote, dstChainInfo , gasLimit, msgValue);
197205
198206 return (payeeAddress, requiredPayment);
199207 }
0 commit comments