Skip to content
This repository was archived by the owner on Jun 24, 2025. It is now read-only.

Commit f651e16

Browse files
authored
Store routes. (#50)
1 parent c7b35cf commit f651e16

File tree

14 files changed

+134
-1117
lines changed

14 files changed

+134
-1117
lines changed

src/Gateway.sol

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -94,21 +94,6 @@ contract Gateway is IGateway, IExecutor, IUpgradable, GatewayEIP712 {
9494

9595
constructor(uint16 network, address proxy) payable GatewayEIP712(network, proxy) {}
9696

97-
// EIP-712 typed hash
98-
function initialize(address proxyAdmin, TssKey[] calldata keys, Network[] calldata networks) external {
99-
require(PROXY_ADDRESS == address(this) || msg.sender == FACTORY, "only proxy can be initialize");
100-
ERC1967.setAdmin(proxyAdmin);
101-
102-
// Register networks
103-
RouteStore.getMainStorage().initialize(networks, NetworkID.wrap(NETWORK_ID));
104-
105-
// Register keys
106-
ShardStore.getMainStorage().registerTssKeys(keys);
107-
108-
// emit event
109-
emit ShardsRegistered(keys);
110-
}
111-
11297
function nonceOf(address account) external view returns (uint64) {
11398
return uint64(_nonces[account]);
11499
}
@@ -591,13 +576,6 @@ contract Gateway is IGateway, IExecutor, IUpgradable, GatewayEIP712 {
591576
return route.estimateWeiCost(uint16(messageSize), gasLimit);
592577
}
593578

594-
/**
595-
* Deposit funds to the gateway contract
596-
* IMPORTANT: this function must be called only by the administrator!!!!
597-
*/
598-
function deposit() external payable {}
599-
receive() external payable {}
600-
601579
/**
602580
* Withdraw funds from the gateway contract
603581
* @param amount The amount to withdraw
@@ -784,33 +762,4 @@ contract Gateway is IGateway, IExecutor, IUpgradable, GatewayEIP712 {
784762
prev = key;
785763
}
786764
}
787-
788-
function upgrade(address newImplementation) external payable {
789-
require(msg.sender == ERC1967.getAdmin(), "unauthorized");
790-
791-
// Store the address of the implementation contract
792-
ERC1967.setImplementation(newImplementation);
793-
}
794-
795-
function upgradeAndCall(address newImplementation, bytes memory initializer)
796-
external
797-
payable
798-
returns (bytes memory returndata)
799-
{
800-
require(msg.sender == ERC1967.getAdmin(), "unauthorized");
801-
802-
// Store the address of the implementation contract
803-
ERC1967.setImplementation(newImplementation);
804-
805-
// Initialize storage by calling the implementation's using `delegatecall`.
806-
bool success;
807-
(success, returndata) = newImplementation.delegatecall(initializer);
808-
809-
// Revert if the initialization failed
810-
if (!success) {
811-
assembly ("memory-safe") {
812-
revert(add(returndata, 32), mload(returndata))
813-
}
814-
}
815-
}
816765
}

src/GatewayProxy.sol

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@
44
pragma solidity >=0.8.0;
55

66
import {ERC1967} from "./utils/ERC1967.sol";
7-
import {Context, CreateKind, IUniversalFactory} from "../lib/universal-factory/src/IUniversalFactory.sol";
87

98
contract GatewayProxy {
10-
/**
11-
* @dev The address of the `UniversalFactory` contract, must be the same on all networks.
12-
*/
13-
IUniversalFactory internal constant FACTORY = IUniversalFactory(0x0000000000001C4Bf962dF86e38F0c10c7972C6E);
14-
159
/**
1610
* @dev EIP-1967 storage slot with the address of the current implementation.
1711
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
@@ -20,33 +14,19 @@ contract GatewayProxy {
2014
bytes32 private constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
2115

2216
constructor(address admin) payable {
23-
// This contract must be deployed by the `UniversalFactory`
24-
Context memory ctx = FACTORY.context();
25-
require(ctx.contractAddress == address(this), "Only the UniversalFactory can deploy this contract");
26-
require(ctx.kind == CreateKind.CREATE2, "Only CREATE2 is allowed");
27-
28-
require(ctx.data.length > 0, "ctx.data cannot be empty length");
29-
require(ctx.data.length >= 128, "unexpected ctx.data format, expected 128 bytes");
30-
31-
// Store the address of the implementation contract
32-
// DeploymentAuthorization memory authorization;
33-
uint8 v;
34-
bytes32 r;
35-
bytes32 s;
36-
address implementation;
37-
(v, r, s, implementation) = abi.decode(ctx.data, (uint8, bytes32, bytes32, address));
38-
39-
// Verify the signature
40-
bytes32 digest = keccak256(abi.encode(address(this), implementation));
41-
require(admin == ecrecover(digest, v, r, s), "invalid signature");
42-
4317
// Set the ERC1967 admin.
4418
ERC1967.setAdmin(admin);
19+
}
4520

46-
// Set the ERC1967 implementation.
47-
ERC1967.setImplementation(implementation);
21+
function upgrade(address newImplementation) external payable {
22+
require(msg.sender == ERC1967.getAdmin(), "unauthorized");
23+
24+
// Store the address of the implementation contract
25+
ERC1967.setImplementation(newImplementation);
4826
}
4927

28+
receive() external payable {}
29+
5030
fallback() external payable {
5131
assembly ("memory-safe") {
5232
// Copy the calldata to memory
File renamed without changes.

src/storage/Routes.sol

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,27 @@ library RouteStore {
3030
/**
3131
* @dev Network info stored in the Gateway Contract
3232
* @param gasLimit The maximum amount of gas we allow on this particular network.
33-
* @param relativeGasPrice Gas price of destination chain, in terms of the source chain token.
33+
* @param relativeGasPriceNumerator Gas price of destination chain, in terms of the source chain token.
34+
* @param relativeGasPriceDenominator Gas price of destination chain, in terms of the source chain token.
3435
* @param baseFee Base fee for cross-chain message approval on destination, in terms of source native gas token.
3536
*/
3637
struct NetworkInfo {
38+
bytes32 gateway;
3739
uint64 gasLimit;
38-
UFloat9x56 relativeGasPrice;
3940
uint128 baseFee;
41+
uint256 relativeGasPriceNumerator;
42+
uint256 relativeGasPriceDenominator;
4043
}
4144

4245
/**
4346
* @dev Emitted when a route is updated.
4447
* @param networkId Network identifier.
45-
* @param relativeGasPrice Gas price of destination chain, in terms of the source chain token.
48+
* @param relativeGasPriceNumerator Gas price of destination chain, in terms of the source chain token.
49+
* @param relativeGasPriceDenominator Gas price of destination chain, in terms of the source chain token.
4650
* @param baseFee Base fee for cross-chain message approval on destination, in terms of source native gas token.
4751
* @param gasLimit The maximum amount of gas we allow on this particular network.
4852
*/
49-
event RouteUpdated(uint16 indexed networkId, UFloat9x56 relativeGasPrice, uint128 baseFee, uint64 gasLimit);
53+
event RouteUpdated(uint16 indexed networkId, uint256 relativeGasPriceNumerator, uint256 relativeGasPriceDenominator, uint128 baseFee, uint64 gasLimit);
5054

5155
/**
5256
* @dev Shard info stored in the Gateway Contract
@@ -169,13 +173,12 @@ library RouteStore {
169173

170174
// Update relative gas price and base fee if any of them are greater than zero
171175
if (route.relativeGasPriceDenominator > 0) {
172-
UFloat9x56 relativeGasPrice =
173-
UFloatMath.fromRational(route.relativeGasPriceNumerator, route.relativeGasPriceDenominator);
174-
stored.relativeGasPrice = relativeGasPrice;
176+
stored.relativeGasPriceNumerator = route.relativeGasPriceNumerator;
177+
stored.relativeGasPriceDenominator = route.relativeGasPriceDenominator;
175178
stored.baseFee = route.baseFee;
176179
}
177180

178-
emit RouteUpdated(route.networkId.asUint(), stored.relativeGasPrice, stored.baseFee, stored.gasLimit);
181+
emit RouteUpdated(route.networkId.asUint(), stored.relativeGasPriceNumerator, stored.relativeGasPriceDenominator, stored.baseFee, stored.gasLimit);
179182
}
180183

181184
/**
@@ -191,7 +194,8 @@ library RouteStore {
191194
require(created, "network already initialized");
192195
require(network.id != networkdID.asUint() || network.gateway == address(this), "wrong gateway address");
193196
info.gasLimit = 15_000_000; // Default to 15M gas
194-
info.relativeGasPrice = UFloatMath.ONE;
197+
info.relativeGasPriceNumerator = 1;
198+
info.relativeGasPriceDenominator = 1;
195199
info.baseFee = 0;
196200
}
197201
}
@@ -208,16 +212,16 @@ library RouteStore {
208212
bytes32[] memory idx = store.routes.keys;
209213
Route[] memory routes = new Route[](idx.length);
210214
for (uint256 i = 0; i < idx.length; i++) {
211-
(bool success, NetworkInfo storage route) = tryGet(store, NetworkID.wrap(uint16(uint256(idx[i]))));
215+
NetworkID networkId = NetworkID.wrap(uint16(uint256(idx[i])));
216+
(bool success, NetworkInfo storage route) = tryGet(store, networkId);
212217
require(success, "route not found");
213-
(uint256 numerator, uint256 denominator) = route.relativeGasPrice.toRational();
214218
routes[i] = Route({
215-
networkId: NetworkID.wrap(uint16(uint256(idx[i]))),
219+
networkId: networkId,
216220
gasLimit: route.gasLimit,
217221
baseFee: route.baseFee,
218-
gateway: bytes32(uint256(uint160(address(this)))),
219-
relativeGasPriceNumerator: numerator,
220-
relativeGasPriceDenominator: denominator
222+
gateway: route.gateway,
223+
relativeGasPriceNumerator: route.relativeGasPriceNumerator,
224+
relativeGasPriceDenominator: route.relativeGasPriceDenominator
221225
});
222226
}
223227
return routes;
@@ -228,7 +232,7 @@ library RouteStore {
228232
*/
229233
function _checkPreconditions(NetworkInfo memory route, uint256 messageSize, uint256 gasLimit) private pure {
230234
// Verify if the network exists
231-
require(route.baseFee > 0 || UFloat9x56.unwrap(route.relativeGasPrice) > 0, "route is temporarily disabled");
235+
require(route.baseFee > 0 || route.relativeGasPriceDenominator > 0, "route is temporarily disabled");
232236

233237
// Verify if the gas limit and message size are within the limits
234238
require(gasLimit <= route.gasLimit, "gas limit exceeded");
@@ -254,22 +258,7 @@ library RouteStore {
254258
gasCost = GasUtils.estimateGas(uint16(nonZeros), uint16(zeros), gasLimit);
255259

256260
// Calculate the gas cost: gasPrice * gasCost + baseFee
257-
fee = UFloatMath.saturatingMul(route.relativeGasPrice, gasCost).saturatingAdd(route.baseFee);
258-
}
259-
260-
/**
261-
* @dev Utility function for measure the wei cost of a GMP message.
262-
*/
263-
function estimateWeiCost(NetworkInfo memory route, bytes calldata data, uint256 gasLimit)
264-
internal
265-
pure
266-
returns (uint256)
267-
{
268-
_checkPreconditions(route, data.length, gasLimit);
269-
uint256 nonZeros = GasUtils.countNonZerosCalldata(data);
270-
uint256 zeros = data.length - nonZeros;
271-
return
272-
GasUtils.estimateWeiCost(route.relativeGasPrice, route.baseFee, uint16(nonZeros), uint16(zeros), gasLimit);
261+
fee = route.relativeGasPriceNumerator.saturatingMul(gasCost).saturatingDiv(route.relativeGasPriceDenominator).saturatingAdd(route.baseFee);
273262
}
274263

275264
/**
@@ -281,6 +270,9 @@ library RouteStore {
281270
returns (uint256)
282271
{
283272
_checkPreconditions(route, messageSize, gasLimit);
284-
return GasUtils.estimateWeiCost(route.relativeGasPrice, route.baseFee, uint16(messageSize), 0, gasLimit);
273+
274+
UFloat9x56 relativeGasPrice =
275+
UFloatMath.fromRational(route.relativeGasPriceNumerator, route.relativeGasPriceDenominator);
276+
return GasUtils.estimateWeiCost(relativeGasPrice, route.baseFee, uint16(messageSize), 0, gasLimit);
285277
}
286278
}

src/utils/GasUtils.sol

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,23 @@ library GasUtils {
3838
* Obs: To guarantee the overhead is constant regardless the input size, always use `calldata` instead of `memory`
3939
* for external functions.
4040
*/
41-
uint256 internal constant EXECUTION_SELECTOR_OVERHEAD = 496;
41+
uint256 internal constant EXECUTION_SELECTOR_OVERHEAD = 496 - 44;
4242

4343
/**
4444
* @dev Base cost of the `IExecutor.execute` method.
4545
*/
46-
uint256 internal constant EXECUTION_BASE_COST = EXECUTION_SELECTOR_OVERHEAD + 46960 + 144;
46+
uint256 internal constant EXECUTION_BASE_COST = EXECUTION_SELECTOR_OVERHEAD + 46960 + 144 + 22;
4747

4848
/**
4949
* @dev Base cost of the `IGateway.submitMessage` method.
5050
*/
51-
uint256 internal constant SUBMIT_BASE_COST = 24064;
51+
uint256 internal constant SUBMIT_BASE_COST = 24064 - 66 + 133 + 44;
5252

5353
/**
5454
* @dev Extra gas cost that any account `Contract or EOA` must pay when calling `IGateway.submitMessage` method.
5555
* This cost is necessary for initialize the account's `nonce` storage slot.
5656
*/
57-
uint256 internal constant FIRST_MESSAGE_EXTRA_COST = 17100;
57+
uint256 internal constant FIRST_MESSAGE_EXTRA_COST = 17100 + 6000;
5858

5959
/**
6060
* @dev Solidity's reserved location for the free memory pointer.
@@ -106,7 +106,7 @@ library GasUtils {
106106

107107
// Base cost: OPCODES + COLD SLOAD + COLD DELEGATECALL + RETURNDATACOPY
108108
// uint256 gasCost = 57 + 2100 + 2600;
109-
uint256 gasCost = 31 + 2100 + 2600 + 32;
109+
uint256 gasCost = 31 + 2100 + 2600 + 32 + 66;
110110

111111
// CALLDATACOPY
112112
gasCost = gasCost.saturatingAdd(calldataLen * 3);
@@ -140,7 +140,7 @@ library GasUtils {
140140
gasCost += words << 8;
141141

142142
// Memory expansion cost
143-
words += 17 - 1;
143+
words += 17 - 1 + 2;
144144
gasCost += ((words * words) >> 9) + (words * 3);
145145

146146
return gasCost;

0 commit comments

Comments
 (0)