Skip to content

Commit 737c5fe

Browse files
governance minimization and bug fixes
1 parent 4e393e3 commit 737c5fe

8 files changed

+78
-115
lines changed

contracts/src/bridge/FastBridgeReceiverOnEthereum.sol

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -46,36 +46,26 @@ contract FastBridgeReceiverOnEthereum is SafeBridgeReceiverOnEthereum, IFastBrid
4646
// * Storage * //
4747
// ************************************* //
4848

49-
uint256 public constant ONE_BASIS_POINT = 1e4; // One basis point, for scaling.
5049
uint256 public override claimDeposit; // The deposit required to submit a claim.
5150
uint256 public override challengeDeposit; // The deposit required to submit a challenge.
5251
uint256 public override challengeDuration; // The duration of the period allowing to challenge a claim.
53-
uint256 public override alpha; // Basis point of claim or challenge deposit that are lost when dishonest.
5452
mapping(uint256 => Ticket) public tickets; // The tickets by ticketID.
55-
5653
/**
5754
* @dev Constructor.
58-
* @param _governor The governor's address.
59-
* @param _safeBridgeSender The address of the Safe Bridge sender on Arbitrum.
6055
* @param _inbox The address of the Arbitrum Inbox contract.
6156
* @param _claimDeposit The deposit amount to submit a claim in wei.
6257
* @param _challengeDeposit The deposit amount to submit a challenge in wei.
6358
* @param _challengeDuration The duration of the period allowing to challenge a claim.
64-
* @param _alpha Basis point of claim or challenge deposit that are lost when dishonest.
6559
*/
6660
constructor(
67-
address _governor,
68-
address _safeBridgeSender,
6961
address _inbox,
7062
uint256 _claimDeposit,
7163
uint256 _challengeDeposit,
72-
uint256 _challengeDuration,
73-
uint256 _alpha
74-
) SafeBridgeReceiverOnEthereum(_governor, _safeBridgeSender, _inbox) {
64+
uint256 _challengeDuration
65+
) SafeBridgeReceiverOnEthereum(_inbox) {
7566
claimDeposit = _claimDeposit;
7667
challengeDeposit = _challengeDeposit;
7768
challengeDuration = _challengeDuration;
78-
alpha = _alpha;
7969
}
8070

8171
// ************************************* //
@@ -127,18 +117,18 @@ contract FastBridgeReceiverOnEthereum is SafeBridgeReceiverOnEthereum, IFastBrid
127117
/**
128118
* @dev Relay the message for this `ticketID` if the challenge period has passed and the claim is unchallenged. The hash computed over `messageData` and the other parameters must match the hash provided by the claim.
129119
* @param _ticketID The ticket identifier referring to a message going through the bridge.
130-
* @param _blockNumber The block number on the cross-domain chain when the message with this ticketID has been sent.
120+
* @param _blocknumber The block number on the cross-domain chain when the message with this ticketID has been sent.
131121
* @param _messageData The data on the cross-domain chain for the message sent with this ticketID.
132122
*/
133123
function verifyAndRelay(
134124
uint256 _ticketID,
135-
uint256 _blockNumber,
125+
uint256 _blocknumber,
136126
bytes calldata _messageData
137127
) external override {
138128
Ticket storage ticket = tickets[_ticketID];
139129
require(ticket.claim.bridger != address(0), "Claim does not exist");
140130
require(
141-
ticket.claim.messageHash == keccak256(abi.encode(_ticketID, _blockNumber, _messageData)),
131+
ticket.claim.messageHash == keccak256(abi.encode(_ticketID, _blocknumber, _messageData)),
142132
"Invalid hash"
143133
);
144134
require(ticket.claim.claimedAt + challengeDuration < block.timestamp, "Challenge period not over");
@@ -154,12 +144,12 @@ contract FastBridgeReceiverOnEthereum is SafeBridgeReceiverOnEthereum, IFastBrid
154144
* Note: Access restricted to the Safe Bridge.
155145
* @dev Relay the message for this `ticketID` as provided by the Safe Bridge. Resolve a challenged claim for this `ticketID` if any.
156146
* @param _ticketID The ticket identifier referring to a message going through the bridge.
157-
* @param _blockNumber The block number on the cross-domain chain when the message with this ticketID has been sent.
147+
* @param _blocknumber The block number on the cross-domain chain when the message with this ticketID has been sent.
158148
* @param _messageData The data on the cross-domain chain for the message sent with this ticketID.
159149
*/
160150
function verifyAndRelaySafe(
161151
uint256 _ticketID,
162-
uint256 _blockNumber,
152+
uint256 _blocknumber,
163153
bytes calldata _messageData
164154
) external override {
165155
require(isSentBySafeBridge(), "Access not allowed: SafeBridgeSender only.");
@@ -168,7 +158,7 @@ contract FastBridgeReceiverOnEthereum is SafeBridgeReceiverOnEthereum, IFastBrid
168158
require(ticket.relayed == false, "Message already relayed");
169159

170160
// Claim assessment if any
171-
bytes32 messageHash = keccak256(abi.encode(_ticketID, _blockNumber, _messageData));
161+
bytes32 messageHash = keccak256(abi.encode(_ticketID, _blocknumber, _messageData));
172162
if (ticket.claim.bridger != address(0) && ticket.claim.messageHash == messageHash) {
173163
ticket.claim.verified = true;
174164
}
@@ -187,7 +177,7 @@ contract FastBridgeReceiverOnEthereum is SafeBridgeReceiverOnEthereum, IFastBrid
187177
require(ticket.claim.bridger != address(0), "Claim does not exist");
188178
require(ticket.claim.verified == true, "Claim not verified: deposit forfeited");
189179

190-
uint256 amount = ticket.claim.claimDeposit + (ticket.challenge.challengeDeposit * alpha) / ONE_BASIS_POINT;
180+
uint256 amount = ticket.claim.claimDeposit + ticket.challenge.challengeDeposit / 2;
191181
ticket.claim.claimDeposit = 0;
192182
ticket.challenge.challengeDeposit = 0;
193183
payable(ticket.claim.bridger).send(amount); // Use of send to prevent reverting fallback. User is responsibility for accepting ETH.
@@ -204,7 +194,7 @@ contract FastBridgeReceiverOnEthereum is SafeBridgeReceiverOnEthereum, IFastBrid
204194
require(ticket.challenge.challenger != address(0), "Challenge does not exist");
205195
require(ticket.claim.verified == false, "Claim verified: deposit forfeited");
206196

207-
uint256 amount = ticket.challenge.challengeDeposit + (ticket.claim.claimDeposit * alpha) / ONE_BASIS_POINT;
197+
uint256 amount = ticket.challenge.challengeDeposit + ticket.claim.claimDeposit / 2;
208198
ticket.claim.claimDeposit = 0;
209199
ticket.challenge.challengeDeposit = 0;
210200
payable(ticket.challenge.challenger).send(amount); // Use of send to prevent reverting fallback. User is responsibility for accepting ETH.
@@ -229,26 +219,6 @@ contract FastBridgeReceiverOnEthereum is SafeBridgeReceiverOnEthereum, IFastBrid
229219
return (start, end);
230220
}
231221

232-
// ************************ //
233-
// * Governance * //
234-
// ************************ //
235-
236-
function changeClaimDeposit(uint256 _claimDeposit) external onlyByGovernor {
237-
claimDeposit = _claimDeposit;
238-
}
239-
240-
function changeChallengeDeposit(uint256 _challengeDeposit) external onlyByGovernor {
241-
challengeDeposit = _challengeDeposit;
242-
}
243-
244-
function changeChallengePeriodDuration(uint256 _challengeDuration) external onlyByGovernor {
245-
challengeDuration = _challengeDuration;
246-
}
247-
248-
function changeAlpha(uint256 _alpha) external onlyByGovernor {
249-
alpha = _alpha;
250-
}
251-
252222
// ************************ //
253223
// * Internal * //
254224
// ************************ //

contracts/src/bridge/FastBridgeSenderToEthereum.sol

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -25,105 +25,88 @@ contract FastBridgeSenderToEthereum is SafeBridgeSenderToEthereum, IFastBridgeSe
2525

2626
struct Ticket {
2727
bytes32 messageHash;
28-
uint256 blockNumber;
28+
uint256 blocknumber;
2929
bool sentSafe;
3030
}
3131

3232
// ************************************* //
3333
// * Storage * //
3434
// ************************************* //
3535

36-
address public governor; // The governor of the contract.
3736
IFastBridgeReceiver public fastBridgeReceiver; // The address of the Fast Bridge on Ethereum.
38-
address public fastBridgeSender; // The address of the Fast Bridge sender on Arbitrum, generally the Home Gateway.
3937
uint256 public currentTicketID = 1; // Zero means not set, start at 1.
4038
mapping(uint256 => Ticket) public tickets; // The tickets by ticketID.
4139

42-
// ************************************* //
43-
// * Function Modifiers * //
44-
// ************************************* //
45-
46-
modifier onlyByGovernor() {
47-
require(governor == msg.sender, "Access not allowed: Governor only.");
48-
_;
49-
}
50-
5140
/**
5241
* @dev Constructor.
53-
* @param _governor The governor's address.
5442
* @param _fastBridgeReceiver The address of the Fast Bridge on Ethereum.
55-
* @param _fastBridgeSender The address of the Fast Bridge sender on Arbitrum, generally the Home Gateway.
5643
*/
5744
constructor(
58-
address _governor,
59-
IFastBridgeReceiver _fastBridgeReceiver,
60-
address _fastBridgeSender
45+
IFastBridgeReceiver _fastBridgeReceiver
6146
) SafeBridgeSenderToEthereum() {
62-
governor = _governor;
6347
fastBridgeReceiver = _fastBridgeReceiver;
64-
fastBridgeSender = _fastBridgeSender;
6548
}
6649

6750
// ************************************* //
6851
// * State Modifiers * //
6952
// ************************************* //
7053

7154
/**
72-
* Note: Access restricted to the `fastSender`, generally the Gateway.
7355
* @dev Sends an arbitrary message to Ethereum using the Fast Bridge.
7456
* @param _receiver The address of the contract on Ethereum which receives the calldata.
7557
* @param _calldata The receiving domain encoded message data.
7658
* @return ticketID The identifier to provide to sendSafeFallback().
7759
*/
7860
function sendFast(address _receiver, bytes memory _calldata) external override returns (uint256 ticketID) {
79-
require(msg.sender == fastBridgeSender, "Access not allowed: Fast Sender only.");
80-
61+
require(_calldata.length >= 4, "Malformed calldata: lacks function selector.");
8162
ticketID = currentTicketID++;
8263

83-
(bytes32 messageHash, bytes memory messageData) = _encode(ticketID, _receiver, _calldata);
84-
emit OutgoingMessage(ticketID, block.number, _receiver, messageHash, messageData);
64+
(bytes32 messageHash, ) = _encode(
65+
ticketID,
66+
block.number,
67+
msg.sender,
68+
_receiver,
69+
_calldata);
70+
emit OutgoingMessage(ticketID, block.number, msg.sender, _receiver, messageHash, _calldata);
8571

86-
tickets[ticketID] = Ticket({messageHash: messageHash, blockNumber: block.number, sentSafe: false});
72+
tickets[ticketID] = Ticket({messageHash: messageHash, blocknumber: block.number, sentSafe: false});
8773
}
8874

75+
8976
/**
9077
* @dev Sends an arbitrary message to Ethereum using the Safe Bridge, which relies on Arbitrum's canonical bridge. It is unnecessary during normal operations but essential only in case of challenge.
9178
* @param _ticketID The ticketID as returned by `sendFast()`.
79+
* @param _fastMsgSender The msg.sender which called sendFast() to register this ticketID.
9280
* @param _receiver The address of the contract on Ethereum which receives the calldata.
9381
* @param _calldata The receiving domain encoded message data.
9482
*/
9583
function sendSafeFallback(
9684
uint256 _ticketID,
85+
address _fastBridgeReceiver,
86+
address _fastMsgSender,
9787
address _receiver,
9888
bytes memory _calldata
9989
) external payable override {
10090
// TODO: check if keeping _calldata in storage in sendFast() is cheaper than passing it again as a parameter here
91+
// However calldata gas cost-benefit analysis will change with EIP-4488.
10192
Ticket storage ticket = tickets[_ticketID];
10293
require(ticket.messageHash != 0, "Ticket does not exist.");
10394
require(ticket.sentSafe == false, "Ticket already sent safely.");
10495

105-
(bytes32 messageHash, bytes memory messageData) = _encode(_ticketID, _receiver, _calldata);
96+
(bytes32 messageHash, bytes memory messageData) = _encode(_ticketID, ticket.blocknumber, _fastMsgSender, _receiver, _calldata);
10697
require(ticket.messageHash == messageHash, "Invalid message for ticketID.");
10798

10899
// Safe Bridge message envelope
109100
bytes4 methodSelector = IFastBridgeReceiver.verifyAndRelaySafe.selector;
110101
bytes memory safeMessageData = abi.encodeWithSelector(
111102
methodSelector,
112103
_ticketID,
113-
ticket.blockNumber,
104+
ticket.blocknumber,
114105
messageData
115106
);
116-
107+
ticket.sentSafe = true;
117108
// TODO: how much ETH should be provided for bridging? add an ISafeBridgeSender.bridgingCost() if needed
118-
_sendSafe(address(fastBridgeReceiver), safeMessageData);
119-
}
120-
121-
// ************************ //
122-
// * Governance * //
123-
// ************************ //
124-
125-
function changeFastSender(address _fastBridgeSender) external onlyByGovernor {
126-
fastBridgeSender = _fastBridgeSender;
109+
_sendSafe(address(_fastBridgeReceiver), safeMessageData);
127110
}
128111

129112
// ************************ //
@@ -132,13 +115,16 @@ contract FastBridgeSenderToEthereum is SafeBridgeSenderToEthereum, IFastBridgeSe
132115

133116
function _encode(
134117
uint256 _ticketID,
118+
uint256 _blocknumber,
119+
address _msgSender,
135120
address _receiver,
136121
bytes memory _calldata
137-
) internal view returns (bytes32 messageHash, bytes memory messageData) {
138-
// Encode the receiver address with the function signature + arguments i.e calldata
139-
messageData = abi.encode(_receiver, _calldata);
122+
) internal pure returns (bytes32 messageHash, bytes memory messageData) {
123+
// Encode the receiver address with the function signature + _msgSender as the first argument, then the rest of the args
124+
(bytes4 functionSelector, bytes memory _args) = abi.decode(_calldata, (bytes4, bytes));
125+
messageData = abi.encode(_receiver, abi.encodeWithSelector(functionSelector, _msgSender, _args));
140126

141127
// Compute the hash over the message header (ticketID, blockNumber) and body (data).
142-
messageHash = keccak256(abi.encode(_ticketID, block.number, messageData));
128+
messageHash = keccak256(abi.encode(_ticketID, _blocknumber, messageData));
143129
}
144130
}

contracts/src/bridge/SafeBridgeReceiverOnEthereum.sol

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,35 +23,24 @@ contract SafeBridgeReceiverOnEthereum is ISafeBridgeReceiver {
2323
// * Storage * //
2424
// ************************************* //
2525

26-
address public governor; // The governor of the contract.
2726
address public safeBridgeSender; // The address of the Safe Bridge sender on Arbitrum.
2827
IInbox public inbox; // The address of the Arbitrum Inbox contract.
2928

30-
// ************************************* //
31-
// * Function Modifiers * //
32-
// ************************************* //
33-
34-
modifier onlyByGovernor() {
35-
require(governor == msg.sender, "Access not allowed: Governor only.");
36-
_;
37-
}
38-
3929
/**
4030
* @dev Constructor.
41-
* @param _governor The governor's address.
4231
* @param _safeBridgeSender The address of the Safe Bridge sender on Arbitrum.
4332
* @param _inbox The address of the Arbitrum Inbox contract.
4433
*/
4534
constructor(
46-
address _governor,
47-
address _safeBridgeSender,
4835
address _inbox
4936
) {
50-
governor = _governor;
5137
inbox = IInbox(_inbox);
52-
safeBridgeSender = _safeBridgeSender;
5338
}
5439

40+
function setSafeBridgeSender(address _safeBridgeSender) external {
41+
if (safeBridgeSender == address(0) )
42+
safeBridgeSender = _safeBridgeSender;
43+
}
5544
// ************************************* //
5645
// * Views * //
5746
// ************************************* //
@@ -60,16 +49,4 @@ contract SafeBridgeReceiverOnEthereum is ISafeBridgeReceiver {
6049
IOutbox outbox = IOutbox(inbox.bridge().activeOutbox());
6150
return outbox.l2ToL1Sender() == safeBridgeSender;
6251
}
63-
64-
// ************************ //
65-
// * Governance * //
66-
// ************************ //
67-
68-
function setSafeBridgeSender(address _safeBridgeSender) external onlyByGovernor {
69-
safeBridgeSender = _safeBridgeSender;
70-
}
71-
72-
function setInbox(address _inbox) external onlyByGovernor {
73-
inbox = IInbox(_inbox);
74-
}
7552
}

contracts/src/bridge/interfaces/IFastBridgeReceiver.sol

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,4 @@ interface IFastBridgeReceiver {
109109
* @return amount The duration of the period allowing to challenge a claim.
110110
*/
111111
function challengeDuration() external view returns (uint256 amount);
112-
113-
/**
114-
* @return amount Basis point of claim or challenge deposit that are lost when dishonest.
115-
*/
116-
function alpha() external view returns (uint256 amount);
117112
}

contracts/src/bridge/interfaces/IFastBridgeSender.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ interface IFastBridgeSender {
1111
* @dev The Fast Bridge participants need to watch for these events and relay the messageHash on the FastBridgeReceiverOnEthereum.
1212
* @param ticketID The ticket identifier referring to a message going through the bridge.
1313
* @param blockNumber The block number when the message with this ticketID has been created.
14+
* @param messageSender The address of the cross-domain receiver of the message, generally the Foreign Gateway.
1415
* @param target The address of the cross-domain receiver of the message, generally the Foreign Gateway.
1516
* @param messageHash The hash uniquely identifying this message.
1617
* @param message The message data.
1718
*/
1819
event OutgoingMessage(
1920
uint256 indexed ticketID,
2021
uint256 blockNumber,
22+
address messageSender,
2123
address target,
2224
bytes32 indexed messageHash,
2325
bytes message
@@ -39,11 +41,15 @@ interface IFastBridgeSender {
3941
/**
4042
* @dev Sends an arbitrary message across domain using the Safe Bridge, which relies on the chain's canonical bridge. It is unnecessary during normal operations but essential only in case of challenge.
4143
* @param _ticketID The ticketID as returned by `sendFast()`.
44+
* @param _fastBridgeReceiver The address of the fast bridge receiver deployment.
45+
* @param _fastMsgSender The msg.sender which called sendFast()
4246
* @param _receiver The cross-domain contract address which receives the calldata.
4347
* @param _calldata The receiving domain encoded message data.
4448
*/
4549
function sendSafeFallback(
4650
uint256 _ticketID,
51+
address _fastBridgeReceiver,
52+
address _fastMsgSender,
4753
address _receiver,
4854
bytes memory _calldata
4955
) external payable;

0 commit comments

Comments
 (0)