Skip to content

Commit 5a10fd2

Browse files
committed
v0.7.1
1 parent d62a255 commit 5a10fd2

File tree

10 files changed

+72
-44
lines changed

10 files changed

+72
-44
lines changed

src/solidity/Fees.sol

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,29 @@
11
// SPDX-License-Identifier: Apache-2.0.
22
pragma solidity ^0.8.0;
33

4+
// Estimate cost for L1-L2 message handler.
45
uint256 constant DEPOSIT_FEE_GAS = 20000;
56
uint256 constant DEPLOYMENT_FEE_GAS = 100000;
6-
uint256 constant MIN_FEE_MARGIN = 100000;
7-
uint256 constant MAX_FEE_MARGIN = 10**14;
87

9-
library Fees {
10-
function estimateDepositFee() internal view returns (uint256) {
11-
return DEPOSIT_FEE_GAS * block.basefee;
12-
}
8+
// We don't have a solid way to gauge block gas price
9+
// (block.basefee cannot be used).
10+
uint256 constant DEFAULT_WEI_PER_GAS = 5 * 10**9;
1311

14-
function estimateEnrollmentFee() internal view returns (uint256) {
15-
return DEPLOYMENT_FEE_GAS * block.basefee;
16-
}
12+
abstract contract Fees {
13+
// Effectively no minimum fee on testnet.
14+
uint256 immutable MIN_FEE = (block.chainid == 1) ? 10**12 : 1;
15+
uint256 constant MAX_FEE = 10**16;
1716

18-
function checkDepositFee(uint256 feeWei) internal view {
19-
checkFee(feeWei, estimateDepositFee());
17+
function estimateDepositFee() internal pure returns (uint256) {
18+
return DEPOSIT_FEE_GAS * DEFAULT_WEI_PER_GAS;
2019
}
2120

22-
function checkEnrollmentFee(uint256 feeWei) internal view {
23-
checkFee(feeWei, estimateEnrollmentFee());
21+
function estimateEnrollmentFee() internal pure returns (uint256) {
22+
return DEPLOYMENT_FEE_GAS * DEFAULT_WEI_PER_GAS;
2423
}
2524

26-
/*
27-
The fee should be within margins from the estimated fee:
28-
max(5, estimate/2 - MIN_FEE_MARGIN) <= fee <= 2*estimate + MAX_FEE_MARGIN.
29-
*/
30-
function checkFee(uint256 feeWei, uint256 feeEstimate) internal pure {
31-
uint256 minFee = feeEstimate >> 1;
32-
minFee = (minFee < MIN_FEE_MARGIN + 5) ? 5 : (minFee - MIN_FEE_MARGIN);
33-
uint256 maxFee = MAX_FEE_MARGIN + (feeEstimate << 1);
34-
require(feeWei >= minFee, "INSUFFICIENT_FEE_VALUE");
35-
require(feeWei <= maxFee, "FEE_VALUE_TOO_HIGH");
25+
function checkFee(uint256 feeWei) internal view {
26+
require(feeWei >= MIN_FEE, "INSUFFICIENT_FEE_VALUE");
27+
require(feeWei <= MAX_FEE, "FEE_VALUE_TOO_HIGH");
3628
}
3729
}

src/solidity/StarknetERC20Bridge.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ import "src/solidity/LegacyBridge.sol";
55

66
contract StarknetERC20Bridge is LegacyBridge {
77
function identify() external pure override returns (string memory) {
8-
return "StarkWare_StarknetERC20Bridge_2.0_3";
8+
return "StarkWare_StarknetERC20Bridge_2.0_4";
99
}
1010
}

src/solidity/StarknetEthBridge.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ contract StarknetEthBridge is LegacyBridge {
99
using Addresses for address;
1010

1111
function identify() external pure override returns (string memory) {
12-
return "StarkWare_StarknetEthBridge_2.0_3";
12+
return "StarkWare_StarknetEthBridge_2.0_4";
1313
}
1414

1515
function acceptDeposit(
@@ -19,7 +19,7 @@ contract StarknetEthBridge is LegacyBridge {
1919
// Make sure msg.value is enough to cover amount. The remaining value is fee.
2020
require(msg.value >= amount, "INSUFFICIENT_VALUE");
2121
uint256 fee = msg.value - amount;
22-
Fees.checkDepositFee(fee);
22+
Fees.checkFee(fee);
2323
// The msg.value was already credited to this contract. Fee will be passed to Starknet.
2424
require(address(this).balance - fee <= getMaxTotalBalance(ETH), "MAX_BALANCE_EXCEEDED");
2525
return fee;

src/solidity/StarknetTokenBridge.sol

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ contract StarknetTokenBridge is
2424
IStarkgateBridge,
2525
IStarkgateService,
2626
Identity,
27+
Fees,
2728
StarknetTokenStorage,
2829
ProxySupport
2930
{
@@ -90,7 +91,7 @@ contract StarknetTokenBridge is
9091
uint256 constant DEPOSIT_MESSAGE_FIXED_SIZE = 1;
9192

9293
function identify() external pure virtual returns (string memory) {
93-
return "StarkWare_StarknetTokenBridge_2.0_3";
94+
return "StarkWare_StarknetTokenBridge_2.0_4";
9495
}
9596

9697
function validateInitData(bytes calldata data) internal view virtual override {
@@ -139,17 +140,17 @@ contract StarknetTokenBridge is
139140
_;
140141
}
141142

142-
function estimateDepositFeeWei() external view returns (uint256) {
143+
function estimateDepositFeeWei() external pure returns (uint256) {
143144
return Fees.estimateDepositFee();
144145
}
145146

146-
function estimateEnrollmentFeeWei() external view returns (uint256) {
147+
function estimateEnrollmentFeeWei() external pure returns (uint256) {
147148
return Fees.estimateEnrollmentFee();
148149
}
149150

150151
// Virtual functions.
151152
function acceptDeposit(address token, uint256 amount) internal virtual returns (uint256) {
152-
Fees.checkDepositFee(msg.value);
153+
Fees.checkFee(msg.value);
153154
uint256 currentBalance = IERC20(token).balanceOf(address(this));
154155
require(currentBalance + amount <= getMaxTotalBalance(token), "MAX_BALANCE_EXCEEDED");
155156
Transfers.transferIn(token, msg.sender, amount);
@@ -429,7 +430,7 @@ contract StarknetTokenBridge is
429430

430431
function sendDeployMessage(address token) internal returns (bytes32) {
431432
require(l2TokenBridge() != 0, "L2_BRIDGE_NOT_SET");
432-
Fees.checkEnrollmentFee(msg.value);
433+
Fees.checkFee(msg.value);
433434

434435
(bytes32 deploymentMsgHash, ) = messagingContract().sendMessageToL2{value: msg.value}(
435436
l2TokenBridge(),

src/solidity/conftest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
StarknetTokenBridgeTester,
2323
StarknetERC20BridgeTester,
2424
SelfRemoveTester,
25+
FeeTester,
2526
)
2627

2728
DYNAMIC_FEE = -1
@@ -191,6 +192,11 @@ def regular_user(eth_test_utils: EthTestUtils) -> EthContract:
191192
return eth_test_utils.accounts[3]
192193

193194

195+
@pytest.fixture
196+
def fee_tester(governor: EthAccount) -> EthContract:
197+
return governor.deploy(FeeTester)
198+
199+
194200
@pytest.fixture
195201
def mock_erc20_contract(governor: EthAccount) -> EthContract:
196202
erc20_contract = governor.deploy(TestERC20)

src/solidity/files_to_compile.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ starkware/solidity/test_contracts/TestERC20.sol
1212
starkware/solidity/upgrade/Proxy.sol
1313
starkware/starknet/testing/MockStarknetMessaging.sol
1414
src/solidity/StarkgateUpgradeAssistExternalInitializer.sol
15+
src/solidity/test_contracts/TestFees.sol

src/solidity/legacy_token_bridge_test.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import pytest
22
from web3 import Web3
3-
from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME
43
from starkware.eth.eth_test_utils import EthContract, EthRevertException, EthTestUtils, EthAccount
54
from solidity.conftest import (
65
add_implementation_and_upgrade,
@@ -11,16 +10,8 @@
1110
deploy_proxy,
1211
messaging_contract,
1312
mock_erc20_contract,
14-
StarknetTokenBridgeWrapper,
15-
EthBridgeWrapper,
16-
StarknetERC20BridgeWrapper,
17-
TokenBridgeWrapper,
1813
L1_TOKEN_ADDRESS_OF_ETH,
19-
L2_TOKEN_CONTRACT,
2014
MAX_UINT,
21-
HANDLE_TOKEN_DEPOSIT_SELECTOR,
22-
HANDLE_DEPOSIT_WITH_MESSAGE_SELECTOR,
23-
HANDLE_TOKEN_DEPLOYMENT_SELECTOR,
2415
TOKEN_ADDRESS,
2516
UpgradeAssistEIC,
2617
StarknetTokenBridge,
@@ -48,6 +39,8 @@
4839
WITHDRAW_AMOUNT = 3
4940
MESSAGE_CANCEL_DELAY = 1000
5041
MAX_TVL = 496351
42+
MAX_FEE = 10**16
43+
MIN_FEE = 10**12
5144

5245

5346
@pytest.fixture(scope="session")
@@ -136,6 +129,23 @@ def legacy_tester_erc20_new_proxy_bridge(
136129
)
137130

138131

132+
def test_fee_values(fee_tester):
133+
with pytest.raises(EthRevertException, match="INSUFFICIENT_FEE_VALUE"):
134+
fee_tester.testCheckFee.call(0)
135+
136+
for valid_fee in [MIN_FEE, MAX_FEE]:
137+
fee_tester.testCheckFee.call(valid_fee)
138+
139+
deposit_fee = fee_tester.estimateDepositFeeWei.call()
140+
assert MIN_FEE * 10 < deposit_fee < MAX_FEE // 10
141+
142+
enrollment_fee = fee_tester.estimateEnrollmentFeeWei.call()
143+
assert MIN_FEE * 10 < enrollment_fee < MAX_FEE // 10
144+
145+
with pytest.raises(EthRevertException, match="FEE_VALUE_TOO_HIGH"):
146+
fee_tester.testCheckFee.call(1 + MAX_FEE)
147+
148+
139149
def test_erc20_bridge_deposit_cancel_upgrade(
140150
governor: EthAccount,
141151
mock_erc20_contract: EthContract,

src/solidity/test_contracts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
StarknetERC20BridgeTester = load_contract("StarknetERC20BridgeTester")
66
SelfRemoveTester = load_contract("SelfRemoveTester")
77
StarkgateRegistry = load_contract("StarkgateRegistry")
8+
FeeTester = load_contract("TestFees")
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// SPDX-License-Identifier: Apache-2.0.
2+
pragma solidity ^0.8.0;
3+
4+
import "src/solidity/Fees.sol";
5+
6+
contract TestFees is Fees {
7+
function estimateDepositFeeWei() external pure returns (uint256) {
8+
return Fees.estimateDepositFee();
9+
}
10+
11+
function estimateEnrollmentFeeWei() external pure returns (uint256) {
12+
return Fees.estimateEnrollmentFee();
13+
}
14+
15+
function testCheckFee(uint256 feeWei) external view {
16+
Fees.checkFee(feeWei);
17+
}
18+
}

src/solidity/token_bridge_test.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,18 +191,17 @@ def test_deposit_l2_token_contract_not_set(token_bridge_wrapper: TokenBridgeWrap
191191
def test_deposit_fee_too_low(token_bridge_wrapper: TokenBridgeWrapper):
192192
setup_contracts(token_bridge_wrapper=token_bridge_wrapper)
193193
with pytest.raises(EthRevertException, match="INSUFFICIENT_FEE_VALUE"):
194-
token_bridge_wrapper.deposit(amount=DEPOSIT_AMOUNT, l2_recipient=L2_RECIPIENT, fee=1)
194+
token_bridge_wrapper.deposit(amount=DEPOSIT_AMOUNT, l2_recipient=L2_RECIPIENT, fee=0)
195195

196196
with pytest.raises(EthRevertException, match="INSUFFICIENT_FEE_VALUE"):
197197
token_bridge_wrapper.deposit(
198-
amount=DEPOSIT_AMOUNT, l2_recipient=L2_RECIPIENT, fee=1, message=MESSAGE
198+
amount=DEPOSIT_AMOUNT, l2_recipient=L2_RECIPIENT, fee=0, message=MESSAGE
199199
)
200200

201201

202202
def test_deposit_fee_too_high(token_bridge_wrapper: TokenBridgeWrapper):
203203
setup_contracts(token_bridge_wrapper=token_bridge_wrapper)
204-
base_fee = token_bridge_wrapper.contract.estimateDepositFeeWei.call()
205-
too_high_fee = 2 * base_fee + 2 * 10**14
204+
too_high_fee = 2 + 10**16
206205
with pytest.raises(EthRevertException, match="FEE_VALUE_TOO_HIGH"):
207206
token_bridge_wrapper.deposit(
208207
amount=DEPOSIT_AMOUNT, l2_recipient=L2_RECIPIENT, fee=too_high_fee

0 commit comments

Comments
 (0)